[PATCH] PCI Hotplug: CPCI update

[PATCH] CPCI: update

I have finally done some work to update the CompactPCI hotplug driver to
fix some of the outstanding issues in 2.6:
- Added adapter and latch status ops so that those files will get created
by the current PCI hotplug core. This used to not be required, but
seems to be now after some of the sysfs rework in the core.
- Replaced slot list spinlock with a r/w semaphore to avoid any potential
issues with sleeping. This quiets all of the runtime warnings.
- Reworked interrupt driven hot extraction handling to remove need for a
polling operator for ENUM# status. There are a lot of boards that only
have an interrupt driven by ENUM#, so this lowers the bar to entry.
- Replaced pci_visit_dev usage with better use of the PCI core functions.
The new code is functionally equivalent to the previous code, but the
use of pci_enable_device on insert needs to be investigated further, as
I need to do some more testing to see if it is still necessary.

Signed-off-by: Scott Murray <scottm@somanetworks.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Scott Murray and committed by
Greg KH
43b7d7cf 8b245e45

+113 -412
+1 -1
drivers/pci/hotplug/cpci_hotplug.h
··· 31 31 #include <linux/types.h> 32 32 #include <linux/pci.h> 33 33 34 - /* PICMG 2.12 R2.0 HS CSR bits: */ 34 + /* PICMG 2.1 R2.0 HS CSR bits: */ 35 35 #define HS_CSR_INS 0x0080 36 36 #define HS_CSR_EXT 0x0040 37 37 #define HS_CSR_PI 0x0030
+86 -83
drivers/pci/hotplug/cpci_hotplug_core.c
··· 33 33 #include <linux/init.h> 34 34 #include <linux/interrupt.h> 35 35 #include <linux/smp_lock.h> 36 + #include <asm/atomic.h> 36 37 #include <linux/delay.h> 37 38 #include "pci_hotplug.h" 38 39 #include "cpci_hotplug.h" 39 40 40 - #define DRIVER_VERSION "0.2" 41 41 #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" 42 42 #define DRIVER_DESC "CompactPCI Hot Plug Core" 43 43 ··· 54 54 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) 55 55 56 56 /* local variables */ 57 - static spinlock_t list_lock; 57 + static DECLARE_RWSEM(list_rwsem); 58 58 static LIST_HEAD(slot_list); 59 59 static int slots; 60 + static atomic_t extracting; 60 61 int cpci_debug; 61 62 static struct cpci_hp_controller *controller; 62 63 static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ ··· 69 68 static int set_attention_status(struct hotplug_slot *slot, u8 value); 70 69 static int get_power_status(struct hotplug_slot *slot, u8 * value); 71 70 static int get_attention_status(struct hotplug_slot *slot, u8 * value); 71 + static int get_adapter_status(struct hotplug_slot *slot, u8 * value); 72 + static int get_latch_status(struct hotplug_slot *slot, u8 * value); 72 73 73 74 static struct hotplug_slot_ops cpci_hotplug_slot_ops = { 74 75 .owner = THIS_MODULE, ··· 79 76 .set_attention_status = set_attention_status, 80 77 .get_power_status = get_power_status, 81 78 .get_attention_status = get_attention_status, 79 + .get_adapter_status = get_adapter_status, 80 + .get_latch_status = get_latch_status, 82 81 }; 83 82 84 83 static int ··· 153 148 warn("failure to update adapter file"); 154 149 } 155 150 156 - slot->extracting = 0; 157 - 151 + if(slot->extracting) { 152 + slot->extracting = 0; 153 + atomic_dec(&extracting); 154 + } 158 155 return retval; 159 156 } 160 157 ··· 193 186 set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) 194 187 { 195 188 return cpci_set_attention_status(hotplug_slot->private, status); 189 + } 190 + 191 + static int 192 + get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) 193 + { 194 + *value = hotplug_slot->info->adapter_status; 195 + return 0; 196 + } 197 + 198 + static int 199 + get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value) 200 + { 201 + *value = hotplug_slot->info->latch_status; 202 + return 0; 196 203 } 197 204 198 205 static void release_slot(struct hotplug_slot *hotplug_slot) ··· 294 273 } 295 274 296 275 /* Add slot to our internal list */ 297 - spin_lock(&list_lock); 276 + down_write(&list_rwsem); 298 277 list_add(&slot->slot_list, &slot_list); 299 278 slots++; 300 - spin_unlock(&list_lock); 279 + up_write(&list_rwsem); 301 280 } 302 281 return 0; 303 282 error_name: ··· 320 299 struct list_head *next; 321 300 int status; 322 301 323 - spin_lock(&list_lock); 302 + down_write(&list_rwsem); 324 303 if(!slots) { 325 - spin_unlock(&list_lock); 304 + up_write(&list_rwsem); 326 305 return -1; 327 306 } 328 307 list_for_each_safe(tmp, next, &slot_list) { ··· 340 319 slots--; 341 320 } 342 321 } 343 - spin_unlock(&list_lock); 322 + up_write(&list_rwsem); 344 323 return 0; 345 324 } 346 325 ··· 368 347 } 369 348 370 349 /* 371 - * According to PICMG 2.12 R2.0, section 6.3.2, upon 350 + * According to PICMG 2.1 R2.0, section 6.3.2, upon 372 351 * initialization, the system driver shall clear the 373 352 * INS bits of the cold-inserted devices. 374 353 */ ··· 380 359 struct pci_dev* dev; 381 360 382 361 dbg("%s - enter", __FUNCTION__); 383 - spin_lock(&list_lock); 362 + down_read(&list_rwsem); 384 363 if(!slots) { 385 - spin_unlock(&list_lock); 364 + up_read(&list_rwsem); 386 365 return -1; 387 366 } 388 367 list_for_each(tmp, &slot_list) { ··· 407 386 } 408 387 } 409 388 } 410 - spin_unlock(&list_lock); 389 + up_read(&list_rwsem); 411 390 dbg("%s - exit", __FUNCTION__); 412 391 return 0; 413 392 } ··· 419 398 struct list_head *tmp; 420 399 int extracted; 421 400 int inserted; 401 + u16 hs_csr; 422 402 423 - spin_lock(&list_lock); 403 + down_read(&list_rwsem); 424 404 if(!slots) { 425 - spin_unlock(&list_lock); 405 + up_read(&list_rwsem); 426 406 err("no slots registered, shutting down"); 427 407 return -1; 428 408 } ··· 433 411 dbg("%s - looking at slot %s", 434 412 __FUNCTION__, slot->hotplug_slot->name); 435 413 if(cpci_check_and_clear_ins(slot)) { 436 - u16 hs_csr; 437 - 438 414 /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */ 439 415 if(slot->dev) { 440 416 warn("slot %s already inserted", slot->hotplug_slot->name); ··· 482 462 483 463 inserted++; 484 464 } else if(cpci_check_ext(slot)) { 485 - u16 hs_csr; 486 - 487 465 /* Process extraction request */ 488 466 dbg("%s - slot %s extracted", 489 467 __FUNCTION__, slot->hotplug_slot->name); ··· 494 476 if(!slot->extracting) { 495 477 if(update_latch_status(slot->hotplug_slot, 0)) { 496 478 warn("failure to update latch file"); 479 + 497 480 } 481 + atomic_inc(&extracting); 498 482 slot->extracting = 1; 499 483 } 500 484 extracted++; 485 + } else if(slot->extracting) { 486 + hs_csr = cpci_get_hs_csr(slot); 487 + if(hs_csr == 0xffff) { 488 + /* 489 + * Hmmm, we're likely hosed at this point, should we 490 + * bother trying to tell the driver or not? 491 + */ 492 + err("card in slot %s was improperly removed", 493 + slot->hotplug_slot->name); 494 + if(update_adapter_status(slot->hotplug_slot, 0)) { 495 + warn("failure to update adapter file"); 496 + } 497 + slot->extracting = 0; 498 + atomic_dec(&extracting); 499 + } 501 500 } 502 501 } 503 - spin_unlock(&list_lock); 502 + up_read(&list_rwsem); 503 + dbg("inserted=%d, extracted=%d, extracting=%d", 504 + inserted, extracted, atomic_read(&extracting)); 504 505 if(inserted || extracted) { 505 506 return extracted; 506 507 } 507 - else { 508 + else if(!atomic_read(&extracting)) { 508 509 err("cannot find ENUM# source, shutting down"); 509 510 return -1; 510 511 } 512 + return 0; 511 513 } 512 514 513 515 /* This is the interrupt mode worker thread body */ ··· 535 497 event_thread(void *data) 536 498 { 537 499 int rc; 538 - struct slot *slot; 539 - struct list_head *tmp; 540 500 541 501 lock_kernel(); 542 502 daemonize("cpci_hp_eventd"); ··· 548 512 thread_finished); 549 513 if(thread_finished || signal_pending(current)) 550 514 break; 551 - while(controller->ops->query_enum()) { 515 + do { 552 516 rc = check_slots(); 553 - if (rc > 0) 517 + if (rc > 0) { 554 518 /* Give userspace a chance to handle extraction */ 555 519 msleep(500); 556 - else if (rc < 0) { 520 + } else if (rc < 0) { 557 521 dbg("%s - error checking slots", __FUNCTION__); 558 522 thread_finished = 1; 559 523 break; 560 524 } 561 - } 562 - /* Check for someone yanking out a board */ 563 - list_for_each(tmp, &slot_list) { 564 - slot = list_entry(tmp, struct slot, slot_list); 565 - if(slot->extracting) { 566 - /* 567 - * Hmmm, we're likely hosed at this point, should we 568 - * bother trying to tell the driver or not? 569 - */ 570 - err("card in slot %s was improperly removed", 571 - slot->hotplug_slot->name); 572 - if(update_adapter_status(slot->hotplug_slot, 0)) { 573 - warn("failure to update adapter file"); 574 - } 575 - slot->extracting = 0; 576 - } 577 - } 525 + } while(atomic_read(&extracting) != 0); 578 526 579 527 /* Re-enable ENUM# interrupt */ 580 528 dbg("%s - re-enabling irq", __FUNCTION__); 581 529 controller->ops->enable_irq(); 582 530 } 583 - 584 531 dbg("%s - event thread signals exit", __FUNCTION__); 585 532 up(&thread_exit); 586 533 return 0; ··· 574 555 poll_thread(void *data) 575 556 { 576 557 int rc; 577 - struct slot *slot; 578 - struct list_head *tmp; 579 558 580 559 lock_kernel(); 581 560 daemonize("cpci_hp_polld"); ··· 582 565 while(1) { 583 566 if(thread_finished || signal_pending(current)) 584 567 break; 585 - 586 - while(controller->ops->query_enum()) { 587 - rc = check_slots(); 588 - if(rc > 0) 589 - /* Give userspace a chance to handle extraction */ 590 - msleep(500); 591 - else if (rc < 0) { 592 - dbg("%s - error checking slots", __FUNCTION__); 593 - thread_finished = 1; 594 - break; 595 - } 596 - } 597 - /* Check for someone yanking out a board */ 598 - list_for_each(tmp, &slot_list) { 599 - slot = list_entry(tmp, struct slot, slot_list); 600 - if(slot->extracting) { 601 - /* 602 - * Hmmm, we're likely hosed at this point, should we 603 - * bother trying to tell the driver or not? 604 - */ 605 - err("card in slot %s was improperly removed", 606 - slot->hotplug_slot->name); 607 - if(update_adapter_status(slot->hotplug_slot, 0)) { 608 - warn("failure to update adapter file"); 568 + if(controller->ops->query_enum()) { 569 + do { 570 + rc = check_slots(); 571 + if(rc > 0) { 572 + /* Give userspace a chance to handle extraction */ 573 + msleep(500); 574 + } else if(rc < 0) { 575 + dbg("%s - error checking slots", __FUNCTION__); 576 + thread_finished = 1; 577 + break; 609 578 } 610 - slot->extracting = 0; 611 - } 579 + } while(atomic_read(&extracting) != 0); 612 580 } 613 - 614 581 msleep(100); 615 582 } 616 583 dbg("poll thread signals exit"); ··· 668 667 int status = 0; 669 668 670 669 if(controller) { 670 + if(atomic_read(&extracting) != 0) { 671 + return -EBUSY; 672 + } 671 673 if(!thread_finished) { 672 674 cpci_stop_thread(); 673 675 } ··· 695 691 return -ENODEV; 696 692 } 697 693 698 - spin_lock(&list_lock); 699 - if(!slots) { 700 - spin_unlock(&list_lock); 694 + down_read(&list_rwsem); 695 + if(list_empty(&slot_list)) { 696 + up_read(&list_rwsem); 701 697 return -ENODEV; 702 698 } 703 - spin_unlock(&list_lock); 699 + up_read(&list_rwsem); 704 700 705 701 if(first) { 706 702 status = init_slots(); ··· 731 727 if(!controller) { 732 728 return -ENODEV; 733 729 } 734 - 730 + if(atomic_read(&extracting) != 0) { 731 + return -EBUSY; 732 + } 735 733 if(controller->irq) { 736 734 /* Stop enum interrupt processing */ 737 735 dbg("%s - disabling irq", __FUNCTION__); ··· 753 747 * Unregister all of our slots with the pci_hotplug subsystem, 754 748 * and free up all memory that we had allocated. 755 749 */ 756 - spin_lock(&list_lock); 750 + down_write(&list_rwsem); 757 751 if(!slots) { 758 752 goto null_cleanup; 759 753 } ··· 767 761 kfree(slot); 768 762 } 769 763 null_cleanup: 770 - spin_unlock(&list_lock); 764 + up_write(&list_rwsem); 771 765 return; 772 766 } 773 767 774 768 int __init 775 769 cpci_hotplug_init(int debug) 776 770 { 777 - spin_lock_init(&list_lock); 778 771 cpci_debug = debug; 779 - 780 - info(DRIVER_DESC " version: " DRIVER_VERSION); 781 772 return 0; 782 773 } 783 774
+26 -328
drivers/pci/hotplug/cpci_hotplug_pci.c
··· 32 32 #include "pci_hotplug.h" 33 33 #include "cpci_hotplug.h" 34 34 35 - #if !defined(MODULE) 36 35 #define MY_NAME "cpci_hotplug" 37 - #else 38 - #define MY_NAME THIS_MODULE->name 39 - #endif 40 36 41 37 extern int cpci_debug; 42 38 ··· 122 126 } 123 127 return hs_csr; 124 128 } 125 - 126 - #if 0 127 - u16 cpci_set_hs_csr(struct slot* slot, u16 hs_csr) 128 - { 129 - int hs_cap; 130 - u16 new_hs_csr; 131 - 132 - hs_cap = pci_bus_find_capability(slot->bus, 133 - slot->devfn, 134 - PCI_CAP_ID_CHSWP); 135 - if(!hs_cap) { 136 - return 0xFFFF; 137 - } 138 - 139 - /* Write out the new value */ 140 - if(pci_bus_write_config_word(slot->bus, 141 - slot->devfn, 142 - hs_cap + 2, 143 - hs_csr)) { 144 - return 0xFFFF; 145 - } 146 - 147 - /* Read back what we just wrote out */ 148 - if(pci_bus_read_config_word(slot->bus, 149 - slot->devfn, 150 - hs_cap + 2, 151 - &new_hs_csr)) { 152 - return 0xFFFF; 153 - } 154 - return new_hs_csr; 155 - } 156 - #endif 157 129 158 130 int cpci_check_and_clear_ins(struct slot* slot) 159 131 { ··· 225 261 return -ENODEV; 226 262 } 227 263 if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) { 228 - /* Set LOO */ 229 264 hs_csr |= HS_CSR_LOO; 230 265 if(pci_bus_write_config_word(slot->bus, 231 266 slot->devfn, ··· 256 293 return -ENODEV; 257 294 } 258 295 if(hs_csr & HS_CSR_LOO) { 259 - /* Clear LOO */ 260 296 hs_csr &= ~HS_CSR_LOO; 261 297 if(pci_bus_write_config_word(slot->bus, 262 298 slot->devfn, ··· 274 312 * Device configuration functions 275 313 */ 276 314 277 - static int cpci_configure_dev(struct pci_bus *bus, struct pci_dev *dev) 315 + static void cpci_enable_device(struct pci_dev *dev) 278 316 { 279 - u8 irq_pin; 280 - int r; 317 + struct pci_bus *bus; 281 318 282 - dbg("%s - enter", __FUNCTION__); 283 - 284 - /* NOTE: device already setup from prior scan */ 285 - 286 - /* FIXME: How would we know if we need to enable the expansion ROM? */ 287 - pci_write_config_word(dev, PCI_ROM_ADDRESS, 0x00L); 288 - 289 - /* Assign resources */ 290 - dbg("assigning resources for %02x:%02x.%x", 291 - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); 292 - for (r = 0; r < 6; r++) { 293 - struct resource *res = dev->resource + r; 294 - if(res->flags) 295 - pci_assign_resource(dev, r); 296 - } 297 - dbg("finished assigning resources for %02x:%02x.%x", 298 - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); 299 - 300 - /* Does this function have an interrupt at all? */ 301 - dbg("checking for function interrupt"); 302 - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin); 303 - if(irq_pin) { 304 - dbg("function uses interrupt pin %d", irq_pin); 305 - } 306 - 307 - /* 308 - * Need to explicitly set irq field to 0 so that it'll get assigned 309 - * by the pcibios platform dependent code called by pci_enable_device. 310 - */ 311 - dev->irq = 0; 312 - 313 - dbg("enabling device"); 314 - pci_enable_device(dev); /* XXX check return */ 315 - dbg("now dev->irq = %d", dev->irq); 316 - if(irq_pin && dev->irq) { 317 - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); 318 - } 319 - 320 - /* Can't use pci_insert_device at the moment, do it manually for now */ 321 - pci_proc_attach_device(dev); 322 - dbg("notifying drivers"); 323 - //pci_announce_device_to_drivers(dev); 324 - dbg("%s - exit", __FUNCTION__); 325 - return 0; 326 - } 327 - 328 - static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev) 329 - { 330 - int rc; 331 - struct pci_bus* child; 332 - struct resource* r; 333 - u8 max, n; 334 - u16 command; 335 - 336 - dbg("%s - enter", __FUNCTION__); 337 - 338 - /* Do basic bridge initialization */ 339 - rc = pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); 340 - if(rc) { 341 - printk(KERN_ERR "%s - write of PCI_LATENCY_TIMER failed\n", __FUNCTION__); 342 - } 343 - rc = pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x40); 344 - if(rc) { 345 - printk(KERN_ERR "%s - write of PCI_SEC_LATENCY_TIMER failed\n", __FUNCTION__); 346 - } 347 - rc = pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4); 348 - if(rc) { 349 - printk(KERN_ERR "%s - write of PCI_CACHE_LINE_SIZE failed\n", __FUNCTION__); 350 - } 351 - 352 - /* 353 - * Set parent bridge's subordinate field so that configuration space 354 - * access will work in pci_scan_bridge and friends. 355 - */ 356 - max = pci_max_busnr(); 357 - bus->subordinate = max + 1; 358 - pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, max + 1); 359 - 360 - /* Scan behind bridge */ 361 - n = pci_scan_bridge(bus, dev, max, 2); 362 - child = pci_find_bus(0, max + 1); 363 - if (!child) 364 - return -ENODEV; 365 - pci_proc_attach_bus(child); 366 - 367 - /* 368 - * Update parent bridge's subordinate field if there were more bridges 369 - * behind the bridge that was scanned. 370 - */ 371 - if(n > max) { 372 - bus->subordinate = n; 373 - pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, n); 374 - } 375 - 376 - /* 377 - * Update the bridge resources of the bridge to accommodate devices 378 - * behind it. 379 - */ 380 - pci_bus_size_bridges(child); 381 - pci_bus_assign_resources(child); 382 - 383 - /* Enable resource mapping via command register */ 384 - command = PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; 385 - r = child->resource[0]; 386 - if(r && r->start) { 387 - command |= PCI_COMMAND_IO; 388 - } 389 - r = child->resource[1]; 390 - if(r && r->start) { 391 - command |= PCI_COMMAND_MEMORY; 392 - } 393 - r = child->resource[2]; 394 - if(r && r->start) { 395 - command |= PCI_COMMAND_MEMORY; 396 - } 397 - rc = pci_write_config_word(dev, PCI_COMMAND, command); 398 - if(rc) { 399 - err("Error setting command register"); 400 - return rc; 401 - } 402 - 403 - /* Set bridge control register */ 404 - command = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA; 405 - rc = pci_write_config_word(dev, PCI_BRIDGE_CONTROL, command); 406 - if(rc) { 407 - err("Error setting bridge control register"); 408 - return rc; 409 - } 410 - dbg("%s - exit", __FUNCTION__); 411 - return 0; 412 - } 413 - 414 - static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev, 415 - struct pci_bus_wrapped *wrapped_bus) 416 - { 417 - int rc; 418 - struct pci_dev *dev = wrapped_dev->dev; 419 - struct pci_bus *bus = wrapped_bus->bus; 420 - struct slot* slot; 421 - 422 - dbg("%s - enter", __FUNCTION__); 423 - 424 - /* 425 - * We need to fix up the hotplug representation with the Linux 426 - * representation. 427 - */ 428 - if(wrapped_dev->data) { 429 - slot = (struct slot*) wrapped_dev->data; 430 - slot->dev = dev; 431 - } 432 - 433 - /* If it's a bridge, scan behind it for devices */ 319 + pci_enable_device(dev); 434 320 if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 435 - rc = cpci_configure_bridge(bus, dev); 436 - if(rc) 437 - return rc; 438 - } 439 - 440 - /* Actually configure device */ 441 - if(dev) { 442 - rc = cpci_configure_dev(bus, dev); 443 - if(rc) 444 - return rc; 445 - } 446 - dbg("%s - exit", __FUNCTION__); 447 - return 0; 448 - } 449 - 450 - static int unconfigure_visit_pci_dev_phase2(struct pci_dev_wrapped *wrapped_dev, 451 - struct pci_bus_wrapped *wrapped_bus) 452 - { 453 - struct pci_dev *dev = wrapped_dev->dev; 454 - struct slot* slot; 455 - 456 - dbg("%s - enter", __FUNCTION__); 457 - if(!dev) 458 - return -ENODEV; 459 - 460 - /* Remove the Linux representation */ 461 - if(pci_remove_device_safe(dev)) { 462 - err("Could not remove device\n"); 463 - return -1; 464 - } 465 - 466 - /* 467 - * Now remove the hotplug representation. 468 - */ 469 - if(wrapped_dev->data) { 470 - slot = (struct slot*) wrapped_dev->data; 471 - slot->dev = NULL; 472 - } else { 473 - dbg("No hotplug representation for %02x:%02x.%x", 474 - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); 475 - } 476 - dbg("%s - exit", __FUNCTION__); 477 - return 0; 478 - } 479 - 480 - static int unconfigure_visit_pci_bus_phase2(struct pci_bus_wrapped *wrapped_bus, 481 - struct pci_dev_wrapped *wrapped_dev) 482 - { 483 - struct pci_bus *bus = wrapped_bus->bus; 484 - struct pci_bus *parent = bus->self->bus; 485 - 486 - dbg("%s - enter", __FUNCTION__); 487 - 488 - /* The cleanup code for proc entries regarding buses should be in the kernel... */ 489 - if(bus->procdir) 490 - dbg("detach_pci_bus %s", bus->procdir->name); 491 - pci_proc_detach_bus(bus); 492 - 493 - /* The cleanup code should live in the kernel... */ 494 - bus->self->subordinate = NULL; 495 - 496 - /* unlink from parent bus */ 497 - list_del(&bus->node); 498 - 499 - /* Now, remove */ 500 - if(bus) 501 - kfree(bus); 502 - 503 - /* Update parent's subordinate field */ 504 - if(parent) { 505 - u8 n = pci_bus_max_busnr(parent); 506 - if(n < parent->subordinate) { 507 - parent->subordinate = n; 508 - pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, n); 321 + bus = dev->subordinate; 322 + list_for_each_entry(dev, &bus->devices, bus_list) { 323 + cpci_enable_device(dev); 509 324 } 510 325 } 511 - dbg("%s - exit", __FUNCTION__); 512 - return 0; 513 326 } 514 - 515 - static struct pci_visit configure_functions = { 516 - .visit_pci_dev = configure_visit_pci_dev, 517 - }; 518 - 519 - static struct pci_visit unconfigure_functions_phase2 = { 520 - .post_visit_pci_bus = unconfigure_visit_pci_bus_phase2, 521 - .post_visit_pci_dev = unconfigure_visit_pci_dev_phase2 522 - }; 523 - 524 327 525 328 int cpci_configure_slot(struct slot* slot) 526 329 { 527 - int rc = 0; 330 + unsigned char busnr; 331 + struct pci_bus *child; 528 332 529 333 dbg("%s - enter", __FUNCTION__); 530 334 ··· 316 588 slot->dev = pci_find_slot(slot->bus->number, slot->devfn); 317 589 if(slot->dev == NULL) { 318 590 err("Could not find PCI device for slot %02x", slot->number); 319 - return 0; 320 - } 321 - } 322 - dbg("slot->dev = %p", slot->dev); 323 - if(slot->dev) { 324 - struct pci_dev *dev; 325 - struct pci_dev_wrapped wrapped_dev; 326 - struct pci_bus_wrapped wrapped_bus; 327 - int i; 328 - 329 - memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped)); 330 - memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped)); 331 - 332 - for (i = 0; i < 8; i++) { 333 - dev = pci_find_slot(slot->bus->number, 334 - PCI_DEVFN(PCI_SLOT(slot->dev->devfn), i)); 335 - if(!dev) 336 - continue; 337 - wrapped_dev.dev = dev; 338 - wrapped_bus.bus = slot->dev->bus; 339 - if(i) 340 - wrapped_dev.data = NULL; 341 - else 342 - wrapped_dev.data = (void*) slot; 343 - rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus); 591 + return 1; 344 592 } 345 593 } 346 594 347 - dbg("%s - exit, rc = %d", __FUNCTION__, rc); 348 - return rc; 595 + if (slot->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 596 + pci_read_config_byte(slot->dev, PCI_SECONDARY_BUS, &busnr); 597 + child = pci_add_new_bus(slot->dev->bus, slot->dev, busnr); 598 + pci_do_scan_bus(child); 599 + pci_bus_size_bridges(child); 600 + } 601 + 602 + pci_bus_assign_resources(slot->dev->bus); 603 + 604 + cpci_enable_device(slot->dev); 605 + 606 + dbg("%s - exit", __FUNCTION__); 607 + return 0; 349 608 } 350 609 351 610 int cpci_unconfigure_slot(struct slot* slot) 352 611 { 353 - int rc = 0; 354 612 int i; 355 - struct pci_dev_wrapped wrapped_dev; 356 - struct pci_bus_wrapped wrapped_bus; 357 613 struct pci_dev *dev; 358 614 359 615 dbg("%s - enter", __FUNCTION__); 360 - 361 616 if(!slot->dev) { 362 617 err("No device for slot %02x\n", slot->number); 363 618 return -ENODEV; 364 619 } 365 620 366 - memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped)); 367 - memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped)); 368 - 369 621 for (i = 0; i < 8; i++) { 370 622 dev = pci_find_slot(slot->bus->number, 371 623 PCI_DEVFN(PCI_SLOT(slot->devfn), i)); 372 624 if(dev) { 373 - wrapped_dev.dev = dev; 374 - wrapped_bus.bus = dev->bus; 375 - if(i) 376 - wrapped_dev.data = NULL; 377 - else 378 - wrapped_dev.data = (void*) slot; 379 - dbg("%s - unconfigure phase 2", __FUNCTION__); 380 - rc = pci_visit_dev(&unconfigure_functions_phase2, 381 - &wrapped_dev, 382 - &wrapped_bus); 383 - if(rc) 384 - break; 625 + pci_remove_bus_device(dev); 626 + slot->dev = NULL; 385 627 } 386 628 } 387 - dbg("%s - exit, rc = %d", __FUNCTION__, rc); 388 - return rc; 629 + dbg("%s - exit", __FUNCTION__); 630 + return 0; 389 631 }