[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 #include <linux/types.h> 32 #include <linux/pci.h> 33 34 - /* PICMG 2.12 R2.0 HS CSR bits: */ 35 #define HS_CSR_INS 0x0080 36 #define HS_CSR_EXT 0x0040 37 #define HS_CSR_PI 0x0030
··· 31 #include <linux/types.h> 32 #include <linux/pci.h> 33 34 + /* PICMG 2.1 R2.0 HS CSR bits: */ 35 #define HS_CSR_INS 0x0080 36 #define HS_CSR_EXT 0x0040 37 #define HS_CSR_PI 0x0030
+86 -83
drivers/pci/hotplug/cpci_hotplug_core.c
··· 33 #include <linux/init.h> 34 #include <linux/interrupt.h> 35 #include <linux/smp_lock.h> 36 #include <linux/delay.h> 37 #include "pci_hotplug.h" 38 #include "cpci_hotplug.h" 39 40 - #define DRIVER_VERSION "0.2" 41 #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" 42 #define DRIVER_DESC "CompactPCI Hot Plug Core" 43 ··· 54 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) 55 56 /* local variables */ 57 - static spinlock_t list_lock; 58 static LIST_HEAD(slot_list); 59 static int slots; 60 int cpci_debug; 61 static struct cpci_hp_controller *controller; 62 static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ ··· 69 static int set_attention_status(struct hotplug_slot *slot, u8 value); 70 static int get_power_status(struct hotplug_slot *slot, u8 * value); 71 static int get_attention_status(struct hotplug_slot *slot, u8 * value); 72 73 static struct hotplug_slot_ops cpci_hotplug_slot_ops = { 74 .owner = THIS_MODULE, ··· 79 .set_attention_status = set_attention_status, 80 .get_power_status = get_power_status, 81 .get_attention_status = get_attention_status, 82 }; 83 84 static int ··· 153 warn("failure to update adapter file"); 154 } 155 156 - slot->extracting = 0; 157 - 158 return retval; 159 } 160 ··· 193 set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) 194 { 195 return cpci_set_attention_status(hotplug_slot->private, status); 196 } 197 198 static void release_slot(struct hotplug_slot *hotplug_slot) ··· 294 } 295 296 /* Add slot to our internal list */ 297 - spin_lock(&list_lock); 298 list_add(&slot->slot_list, &slot_list); 299 slots++; 300 - spin_unlock(&list_lock); 301 } 302 return 0; 303 error_name: ··· 320 struct list_head *next; 321 int status; 322 323 - spin_lock(&list_lock); 324 if(!slots) { 325 - spin_unlock(&list_lock); 326 return -1; 327 } 328 list_for_each_safe(tmp, next, &slot_list) { ··· 340 slots--; 341 } 342 } 343 - spin_unlock(&list_lock); 344 return 0; 345 } 346 ··· 368 } 369 370 /* 371 - * According to PICMG 2.12 R2.0, section 6.3.2, upon 372 * initialization, the system driver shall clear the 373 * INS bits of the cold-inserted devices. 374 */ ··· 380 struct pci_dev* dev; 381 382 dbg("%s - enter", __FUNCTION__); 383 - spin_lock(&list_lock); 384 if(!slots) { 385 - spin_unlock(&list_lock); 386 return -1; 387 } 388 list_for_each(tmp, &slot_list) { ··· 407 } 408 } 409 } 410 - spin_unlock(&list_lock); 411 dbg("%s - exit", __FUNCTION__); 412 return 0; 413 } ··· 419 struct list_head *tmp; 420 int extracted; 421 int inserted; 422 423 - spin_lock(&list_lock); 424 if(!slots) { 425 - spin_unlock(&list_lock); 426 err("no slots registered, shutting down"); 427 return -1; 428 } ··· 433 dbg("%s - looking at slot %s", 434 __FUNCTION__, slot->hotplug_slot->name); 435 if(cpci_check_and_clear_ins(slot)) { 436 - u16 hs_csr; 437 - 438 /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */ 439 if(slot->dev) { 440 warn("slot %s already inserted", slot->hotplug_slot->name); ··· 482 483 inserted++; 484 } else if(cpci_check_ext(slot)) { 485 - u16 hs_csr; 486 - 487 /* Process extraction request */ 488 dbg("%s - slot %s extracted", 489 __FUNCTION__, slot->hotplug_slot->name); ··· 494 if(!slot->extracting) { 495 if(update_latch_status(slot->hotplug_slot, 0)) { 496 warn("failure to update latch file"); 497 } 498 slot->extracting = 1; 499 } 500 extracted++; 501 } 502 } 503 - spin_unlock(&list_lock); 504 if(inserted || extracted) { 505 return extracted; 506 } 507 - else { 508 err("cannot find ENUM# source, shutting down"); 509 return -1; 510 } 511 } 512 513 /* This is the interrupt mode worker thread body */ ··· 535 event_thread(void *data) 536 { 537 int rc; 538 - struct slot *slot; 539 - struct list_head *tmp; 540 541 lock_kernel(); 542 daemonize("cpci_hp_eventd"); ··· 548 thread_finished); 549 if(thread_finished || signal_pending(current)) 550 break; 551 - while(controller->ops->query_enum()) { 552 rc = check_slots(); 553 - if (rc > 0) 554 /* Give userspace a chance to handle extraction */ 555 msleep(500); 556 - else if (rc < 0) { 557 dbg("%s - error checking slots", __FUNCTION__); 558 thread_finished = 1; 559 break; 560 } 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 - } 578 579 /* Re-enable ENUM# interrupt */ 580 dbg("%s - re-enabling irq", __FUNCTION__); 581 controller->ops->enable_irq(); 582 } 583 - 584 dbg("%s - event thread signals exit", __FUNCTION__); 585 up(&thread_exit); 586 return 0; ··· 574 poll_thread(void *data) 575 { 576 int rc; 577 - struct slot *slot; 578 - struct list_head *tmp; 579 580 lock_kernel(); 581 daemonize("cpci_hp_polld"); ··· 582 while(1) { 583 if(thread_finished || signal_pending(current)) 584 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"); 609 } 610 - slot->extracting = 0; 611 - } 612 } 613 - 614 msleep(100); 615 } 616 dbg("poll thread signals exit"); ··· 668 int status = 0; 669 670 if(controller) { 671 if(!thread_finished) { 672 cpci_stop_thread(); 673 } ··· 695 return -ENODEV; 696 } 697 698 - spin_lock(&list_lock); 699 - if(!slots) { 700 - spin_unlock(&list_lock); 701 return -ENODEV; 702 } 703 - spin_unlock(&list_lock); 704 705 if(first) { 706 status = init_slots(); ··· 731 if(!controller) { 732 return -ENODEV; 733 } 734 - 735 if(controller->irq) { 736 /* Stop enum interrupt processing */ 737 dbg("%s - disabling irq", __FUNCTION__); ··· 753 * Unregister all of our slots with the pci_hotplug subsystem, 754 * and free up all memory that we had allocated. 755 */ 756 - spin_lock(&list_lock); 757 if(!slots) { 758 goto null_cleanup; 759 } ··· 767 kfree(slot); 768 } 769 null_cleanup: 770 - spin_unlock(&list_lock); 771 return; 772 } 773 774 int __init 775 cpci_hotplug_init(int debug) 776 { 777 - spin_lock_init(&list_lock); 778 cpci_debug = debug; 779 - 780 - info(DRIVER_DESC " version: " DRIVER_VERSION); 781 return 0; 782 } 783
··· 33 #include <linux/init.h> 34 #include <linux/interrupt.h> 35 #include <linux/smp_lock.h> 36 + #include <asm/atomic.h> 37 #include <linux/delay.h> 38 #include "pci_hotplug.h" 39 #include "cpci_hotplug.h" 40 41 #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" 42 #define DRIVER_DESC "CompactPCI Hot Plug Core" 43 ··· 54 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) 55 56 /* local variables */ 57 + static DECLARE_RWSEM(list_rwsem); 58 static LIST_HEAD(slot_list); 59 static int slots; 60 + static atomic_t extracting; 61 int cpci_debug; 62 static struct cpci_hp_controller *controller; 63 static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ ··· 68 static int set_attention_status(struct hotplug_slot *slot, u8 value); 69 static int get_power_status(struct hotplug_slot *slot, u8 * value); 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); 73 74 static struct hotplug_slot_ops cpci_hotplug_slot_ops = { 75 .owner = THIS_MODULE, ··· 76 .set_attention_status = set_attention_status, 77 .get_power_status = get_power_status, 78 .get_attention_status = get_attention_status, 79 + .get_adapter_status = get_adapter_status, 80 + .get_latch_status = get_latch_status, 81 }; 82 83 static int ··· 148 warn("failure to update adapter file"); 149 } 150 151 + if(slot->extracting) { 152 + slot->extracting = 0; 153 + atomic_dec(&extracting); 154 + } 155 return retval; 156 } 157 ··· 186 set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) 187 { 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; 203 } 204 205 static void release_slot(struct hotplug_slot *hotplug_slot) ··· 273 } 274 275 /* Add slot to our internal list */ 276 + down_write(&list_rwsem); 277 list_add(&slot->slot_list, &slot_list); 278 slots++; 279 + up_write(&list_rwsem); 280 } 281 return 0; 282 error_name: ··· 299 struct list_head *next; 300 int status; 301 302 + down_write(&list_rwsem); 303 if(!slots) { 304 + up_write(&list_rwsem); 305 return -1; 306 } 307 list_for_each_safe(tmp, next, &slot_list) { ··· 319 slots--; 320 } 321 } 322 + up_write(&list_rwsem); 323 return 0; 324 } 325 ··· 347 } 348 349 /* 350 + * According to PICMG 2.1 R2.0, section 6.3.2, upon 351 * initialization, the system driver shall clear the 352 * INS bits of the cold-inserted devices. 353 */ ··· 359 struct pci_dev* dev; 360 361 dbg("%s - enter", __FUNCTION__); 362 + down_read(&list_rwsem); 363 if(!slots) { 364 + up_read(&list_rwsem); 365 return -1; 366 } 367 list_for_each(tmp, &slot_list) { ··· 386 } 387 } 388 } 389 + up_read(&list_rwsem); 390 dbg("%s - exit", __FUNCTION__); 391 return 0; 392 } ··· 398 struct list_head *tmp; 399 int extracted; 400 int inserted; 401 + u16 hs_csr; 402 403 + down_read(&list_rwsem); 404 if(!slots) { 405 + up_read(&list_rwsem); 406 err("no slots registered, shutting down"); 407 return -1; 408 } ··· 411 dbg("%s - looking at slot %s", 412 __FUNCTION__, slot->hotplug_slot->name); 413 if(cpci_check_and_clear_ins(slot)) { 414 /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */ 415 if(slot->dev) { 416 warn("slot %s already inserted", slot->hotplug_slot->name); ··· 462 463 inserted++; 464 } else if(cpci_check_ext(slot)) { 465 /* Process extraction request */ 466 dbg("%s - slot %s extracted", 467 __FUNCTION__, slot->hotplug_slot->name); ··· 476 if(!slot->extracting) { 477 if(update_latch_status(slot->hotplug_slot, 0)) { 478 warn("failure to update latch file"); 479 + 480 } 481 + atomic_inc(&extracting); 482 slot->extracting = 1; 483 } 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 + } 500 } 501 } 502 + up_read(&list_rwsem); 503 + dbg("inserted=%d, extracted=%d, extracting=%d", 504 + inserted, extracted, atomic_read(&extracting)); 505 if(inserted || extracted) { 506 return extracted; 507 } 508 + else if(!atomic_read(&extracting)) { 509 err("cannot find ENUM# source, shutting down"); 510 return -1; 511 } 512 + return 0; 513 } 514 515 /* This is the interrupt mode worker thread body */ ··· 497 event_thread(void *data) 498 { 499 int rc; 500 501 lock_kernel(); 502 daemonize("cpci_hp_eventd"); ··· 512 thread_finished); 513 if(thread_finished || signal_pending(current)) 514 break; 515 + do { 516 rc = check_slots(); 517 + if (rc > 0) { 518 /* Give userspace a chance to handle extraction */ 519 msleep(500); 520 + } else if (rc < 0) { 521 dbg("%s - error checking slots", __FUNCTION__); 522 thread_finished = 1; 523 break; 524 } 525 + } while(atomic_read(&extracting) != 0); 526 527 /* Re-enable ENUM# interrupt */ 528 dbg("%s - re-enabling irq", __FUNCTION__); 529 controller->ops->enable_irq(); 530 } 531 dbg("%s - event thread signals exit", __FUNCTION__); 532 up(&thread_exit); 533 return 0; ··· 555 poll_thread(void *data) 556 { 557 int rc; 558 559 lock_kernel(); 560 daemonize("cpci_hp_polld"); ··· 565 while(1) { 566 if(thread_finished || signal_pending(current)) 567 break; 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; 578 } 579 + } while(atomic_read(&extracting) != 0); 580 } 581 msleep(100); 582 } 583 dbg("poll thread signals exit"); ··· 667 int status = 0; 668 669 if(controller) { 670 + if(atomic_read(&extracting) != 0) { 671 + return -EBUSY; 672 + } 673 if(!thread_finished) { 674 cpci_stop_thread(); 675 } ··· 691 return -ENODEV; 692 } 693 694 + down_read(&list_rwsem); 695 + if(list_empty(&slot_list)) { 696 + up_read(&list_rwsem); 697 return -ENODEV; 698 } 699 + up_read(&list_rwsem); 700 701 if(first) { 702 status = init_slots(); ··· 727 if(!controller) { 728 return -ENODEV; 729 } 730 + if(atomic_read(&extracting) != 0) { 731 + return -EBUSY; 732 + } 733 if(controller->irq) { 734 /* Stop enum interrupt processing */ 735 dbg("%s - disabling irq", __FUNCTION__); ··· 747 * Unregister all of our slots with the pci_hotplug subsystem, 748 * and free up all memory that we had allocated. 749 */ 750 + down_write(&list_rwsem); 751 if(!slots) { 752 goto null_cleanup; 753 } ··· 761 kfree(slot); 762 } 763 null_cleanup: 764 + up_write(&list_rwsem); 765 return; 766 } 767 768 int __init 769 cpci_hotplug_init(int debug) 770 { 771 cpci_debug = debug; 772 return 0; 773 } 774
+26 -328
drivers/pci/hotplug/cpci_hotplug_pci.c
··· 32 #include "pci_hotplug.h" 33 #include "cpci_hotplug.h" 34 35 - #if !defined(MODULE) 36 #define MY_NAME "cpci_hotplug" 37 - #else 38 - #define MY_NAME THIS_MODULE->name 39 - #endif 40 41 extern int cpci_debug; 42 ··· 122 } 123 return hs_csr; 124 } 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 158 int cpci_check_and_clear_ins(struct slot* slot) 159 { ··· 225 return -ENODEV; 226 } 227 if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) { 228 - /* Set LOO */ 229 hs_csr |= HS_CSR_LOO; 230 if(pci_bus_write_config_word(slot->bus, 231 slot->devfn, ··· 256 return -ENODEV; 257 } 258 if(hs_csr & HS_CSR_LOO) { 259 - /* Clear LOO */ 260 hs_csr &= ~HS_CSR_LOO; 261 if(pci_bus_write_config_word(slot->bus, 262 slot->devfn, ··· 274 * Device configuration functions 275 */ 276 277 - static int cpci_configure_dev(struct pci_bus *bus, struct pci_dev *dev) 278 { 279 - u8 irq_pin; 280 - int r; 281 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 */ 434 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); 509 } 510 } 511 - dbg("%s - exit", __FUNCTION__); 512 - return 0; 513 } 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 525 int cpci_configure_slot(struct slot* slot) 526 { 527 - int rc = 0; 528 529 dbg("%s - enter", __FUNCTION__); 530 ··· 316 slot->dev = pci_find_slot(slot->bus->number, slot->devfn); 317 if(slot->dev == NULL) { 318 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); 344 } 345 } 346 347 - dbg("%s - exit, rc = %d", __FUNCTION__, rc); 348 - return rc; 349 } 350 351 int cpci_unconfigure_slot(struct slot* slot) 352 { 353 - int rc = 0; 354 int i; 355 - struct pci_dev_wrapped wrapped_dev; 356 - struct pci_bus_wrapped wrapped_bus; 357 struct pci_dev *dev; 358 359 dbg("%s - enter", __FUNCTION__); 360 - 361 if(!slot->dev) { 362 err("No device for slot %02x\n", slot->number); 363 return -ENODEV; 364 } 365 366 - memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped)); 367 - memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped)); 368 - 369 for (i = 0; i < 8; i++) { 370 dev = pci_find_slot(slot->bus->number, 371 PCI_DEVFN(PCI_SLOT(slot->devfn), i)); 372 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; 385 } 386 } 387 - dbg("%s - exit, rc = %d", __FUNCTION__, rc); 388 - return rc; 389 }
··· 32 #include "pci_hotplug.h" 33 #include "cpci_hotplug.h" 34 35 #define MY_NAME "cpci_hotplug" 36 37 extern int cpci_debug; 38 ··· 126 } 127 return hs_csr; 128 } 129 130 int cpci_check_and_clear_ins(struct slot* slot) 131 { ··· 261 return -ENODEV; 262 } 263 if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) { 264 hs_csr |= HS_CSR_LOO; 265 if(pci_bus_write_config_word(slot->bus, 266 slot->devfn, ··· 293 return -ENODEV; 294 } 295 if(hs_csr & HS_CSR_LOO) { 296 hs_csr &= ~HS_CSR_LOO; 297 if(pci_bus_write_config_word(slot->bus, 298 slot->devfn, ··· 312 * Device configuration functions 313 */ 314 315 + static void cpci_enable_device(struct pci_dev *dev) 316 { 317 + struct pci_bus *bus; 318 319 + pci_enable_device(dev); 320 if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 321 + bus = dev->subordinate; 322 + list_for_each_entry(dev, &bus->devices, bus_list) { 323 + cpci_enable_device(dev); 324 } 325 } 326 } 327 328 int cpci_configure_slot(struct slot* slot) 329 { 330 + unsigned char busnr; 331 + struct pci_bus *child; 332 333 dbg("%s - enter", __FUNCTION__); 334 ··· 588 slot->dev = pci_find_slot(slot->bus->number, slot->devfn); 589 if(slot->dev == NULL) { 590 err("Could not find PCI device for slot %02x", slot->number); 591 + return 1; 592 } 593 } 594 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; 608 } 609 610 int cpci_unconfigure_slot(struct slot* slot) 611 { 612 int i; 613 struct pci_dev *dev; 614 615 dbg("%s - enter", __FUNCTION__); 616 if(!slot->dev) { 617 err("No device for slot %02x\n", slot->number); 618 return -ENODEV; 619 } 620 621 for (i = 0; i < 8; i++) { 622 dev = pci_find_slot(slot->bus->number, 623 PCI_DEVFN(PCI_SLOT(slot->devfn), i)); 624 if(dev) { 625 + pci_remove_bus_device(dev); 626 + slot->dev = NULL; 627 } 628 } 629 + dbg("%s - exit", __FUNCTION__); 630 + return 0; 631 }