[PATCH] PCI Hotplug: more CPCI updates

Here is my third attempt at a patch to further update the CompactPCI
hotplug driver infrastructure to address the pci_enable_device issue
discussed on the list as well as a few other issues I discovered during
some more testing. This version addresses a few more issues pointed out
by Prarit Bhargava. Changes include:
- cpci_enable_device and its recursive calling of pci_enable_device on
new devices removed.
- Use list_rwsem to avoid slot status change races between disable_slot
and check_slots.
- Fixed oopsing in cpci_hp_unregister_bus caused by calling list_del on
a slot after calling pci_hp_deregister.
- Removed kfree calls in cleanup_slots since release_slot will have
done it already.
- Reworked init_slots a bit to fix latch and adapter file updating on
subsequent calls to cpci_hp_start.
- Improved sanity checking in cpci_hp_register_controller.
- Now shut things down correctly in cpci_hotplug_exit.
- Switch to pci_get_slot instead of deprecated pci_find_slot.
- A bunch of CodingStyle fixes.

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
bcc488ab af00f981

+195 -257
+141 -167
drivers/pci/hotplug/cpci_hotplug_core.c
··· 1 /* 2 * CompactPCI Hot Plug Driver 3 * 4 - * Copyright (C) 2002 SOMA Networks, Inc. 5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 6 * Copyright (C) 2001 IBM Corp. 7 * ··· 45 46 #define dbg(format, arg...) \ 47 do { \ 48 - if(cpci_debug) \ 49 printk (KERN_DEBUG "%s: " format "\n", \ 50 MY_NAME , ## arg); \ 51 - } while(0) 52 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) 53 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) 54 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) ··· 111 112 dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); 113 114 - if(controller->ops->set_power) { 115 retval = controller->ops->set_power(slot, 1); 116 - } 117 - 118 return retval; 119 } 120 ··· 124 125 dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); 126 127 /* Unconfigure device */ 128 dbg("%s - unconfiguring slot %s", 129 __FUNCTION__, slot->hotplug_slot->name); 130 - if((retval = cpci_unconfigure_slot(slot))) { 131 err("%s - could not unconfigure slot %s", 132 __FUNCTION__, slot->hotplug_slot->name); 133 - return retval; 134 } 135 dbg("%s - finished unconfiguring slot %s", 136 __FUNCTION__, slot->hotplug_slot->name); 137 138 /* Clear EXT (by setting it) */ 139 - if(cpci_clear_ext(slot)) { 140 err("%s - could not clear EXT for slot %s", 141 __FUNCTION__, slot->hotplug_slot->name); 142 retval = -ENODEV; 143 } 144 cpci_led_on(slot); 145 146 - if(controller->ops->set_power) { 147 - retval = controller->ops->set_power(slot, 0); 148 - } 149 150 - if(update_adapter_status(slot->hotplug_slot, 0)) { 151 warn("failure to update adapter file"); 152 - } 153 154 - if(slot->extracting) { 155 slot->extracting = 0; 156 atomic_dec(&extracting); 157 } 158 return retval; 159 } 160 ··· 167 { 168 u8 power = 1; 169 170 - if(controller->ops->get_power) { 171 power = controller->ops->get_power(slot); 172 - } 173 return power; 174 } 175 ··· 238 int status = -ENOMEM; 239 int i; 240 241 - if(!(controller && bus)) { 242 return -ENODEV; 243 - } 244 245 /* 246 * Create a structure for each slot, and register that slot ··· 316 cpci_hp_unregister_bus(struct pci_bus *bus) 317 { 318 struct slot *slot; 319 - struct list_head *tmp; 320 - struct list_head *next; 321 - int status; 322 323 down_write(&list_rwsem); 324 - if(!slots) { 325 up_write(&list_rwsem); 326 return -1; 327 } 328 - list_for_each_safe(tmp, next, &slot_list) { 329 - slot = list_entry(tmp, struct slot, slot_list); 330 - if(slot->bus == bus) { 331 - dbg("deregistering slot %s", slot->hotplug_slot->name); 332 - status = pci_hp_deregister(slot->hotplug_slot); 333 - if(status) { 334 - err("pci_hp_deregister failed with error %d", 335 - status); 336 - return status; 337 - } 338 - 339 list_del(&slot->slot_list); 340 slots--; 341 } 342 } 343 up_write(&list_rwsem); 344 - return 0; 345 } 346 347 /* This is the interrupt mode interrupt handler */ ··· 349 dbg("entered cpci_hp_intr"); 350 351 /* Check to see if it was our interrupt */ 352 - if((controller->irq_flags & SA_SHIRQ) && 353 !controller->ops->check_irq(controller->dev_id)) { 354 dbg("exited cpci_hp_intr, not our interrupt"); 355 return IRQ_NONE; ··· 371 * INS bits of the cold-inserted devices. 372 */ 373 static int 374 - init_slots(void) 375 { 376 struct slot *slot; 377 - struct list_head *tmp; 378 struct pci_dev* dev; 379 380 dbg("%s - enter", __FUNCTION__); 381 down_read(&list_rwsem); 382 - if(!slots) { 383 up_read(&list_rwsem); 384 return -1; 385 } 386 - list_for_each(tmp, &slot_list) { 387 - slot = list_entry(tmp, struct slot, slot_list); 388 dbg("%s - looking at slot %s", 389 __FUNCTION__, slot->hotplug_slot->name); 390 - if(cpci_check_and_clear_ins(slot)) { 391 dbg("%s - cleared INS for slot %s", 392 __FUNCTION__, slot->hotplug_slot->name); 393 - dev = pci_find_slot(slot->bus->number, PCI_DEVFN(slot->number, 0)); 394 - if(dev) { 395 - if(update_adapter_status(slot->hotplug_slot, 1)) { 396 - warn("failure to update adapter file"); 397 - } 398 - if(update_latch_status(slot->hotplug_slot, 1)) { 399 - warn("failure to update latch file"); 400 - } 401 - slot->dev = dev; 402 - } else { 403 - err("%s - no driver attached to device in slot %s", 404 - __FUNCTION__, slot->hotplug_slot->name); 405 - } 406 } 407 } 408 up_read(&list_rwsem); ··· 406 check_slots(void) 407 { 408 struct slot *slot; 409 - struct list_head *tmp; 410 int extracted; 411 int inserted; 412 u16 hs_csr; 413 414 down_read(&list_rwsem); 415 - if(!slots) { 416 up_read(&list_rwsem); 417 err("no slots registered, shutting down"); 418 return -1; 419 } 420 extracted = inserted = 0; 421 - list_for_each(tmp, &slot_list) { 422 - slot = list_entry(tmp, struct slot, slot_list); 423 dbg("%s - looking at slot %s", 424 __FUNCTION__, slot->hotplug_slot->name); 425 - if(cpci_check_and_clear_ins(slot)) { 426 - /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */ 427 - if(slot->dev) { 428 - warn("slot %s already inserted", slot->hotplug_slot->name); 429 inserted++; 430 continue; 431 } ··· 444 /* Configure device */ 445 dbg("%s - configuring slot %s", 446 __FUNCTION__, slot->hotplug_slot->name); 447 - if(cpci_configure_slot(slot)) { 448 err("%s - could not configure slot %s", 449 __FUNCTION__, slot->hotplug_slot->name); 450 continue; ··· 457 dbg("%s - slot %s HS_CSR (2) = %04x", 458 __FUNCTION__, slot->hotplug_slot->name, hs_csr); 459 460 - if(update_latch_status(slot->hotplug_slot, 1)) { 461 warn("failure to update latch file"); 462 - } 463 464 - if(update_adapter_status(slot->hotplug_slot, 1)) { 465 warn("failure to update adapter file"); 466 - } 467 468 cpci_led_off(slot); 469 ··· 471 __FUNCTION__, slot->hotplug_slot->name, hs_csr); 472 473 inserted++; 474 - } else if(cpci_check_ext(slot)) { 475 /* Process extraction request */ 476 dbg("%s - slot %s extracted", 477 __FUNCTION__, slot->hotplug_slot->name); ··· 481 dbg("%s - slot %s HS_CSR = %04x", 482 __FUNCTION__, slot->hotplug_slot->name, hs_csr); 483 484 - if(!slot->extracting) { 485 - if(update_latch_status(slot->hotplug_slot, 0)) { 486 warn("failure to update latch file"); 487 - 488 } 489 - atomic_inc(&extracting); 490 slot->extracting = 1; 491 } 492 extracted++; 493 - } else if(slot->extracting) { 494 hs_csr = cpci_get_hs_csr(slot); 495 - if(hs_csr == 0xffff) { 496 /* 497 * Hmmm, we're likely hosed at this point, should we 498 * bother trying to tell the driver or not? 499 */ 500 err("card in slot %s was improperly removed", 501 slot->hotplug_slot->name); 502 - if(update_adapter_status(slot->hotplug_slot, 0)) { 503 warn("failure to update adapter file"); 504 - } 505 slot->extracting = 0; 506 atomic_dec(&extracting); 507 } ··· 508 up_read(&list_rwsem); 509 dbg("inserted=%d, extracted=%d, extracting=%d", 510 inserted, extracted, atomic_read(&extracting)); 511 - if(inserted || extracted) { 512 return extracted; 513 - } 514 - else if(!atomic_read(&extracting)) { 515 err("cannot find ENUM# source, shutting down"); 516 return -1; 517 } ··· 528 unlock_kernel(); 529 530 dbg("%s - event thread started", __FUNCTION__); 531 - while(1) { 532 dbg("event thread sleeping"); 533 down_interruptible(&event_semaphore); 534 dbg("event thread woken, thread_finished = %d", 535 thread_finished); 536 - if(thread_finished || signal_pending(current)) 537 break; 538 do { 539 rc = check_slots(); ··· 545 thread_finished = 1; 546 break; 547 } 548 - } while(atomic_read(&extracting) != 0); 549 550 /* Re-enable ENUM# interrupt */ 551 dbg("%s - re-enabling irq", __FUNCTION__); ··· 568 daemonize("cpci_hp_polld"); 569 unlock_kernel(); 570 571 - while(1) { 572 - if(thread_finished || signal_pending(current)) 573 break; 574 - if(controller->ops->query_enum()) { 575 do { 576 rc = check_slots(); 577 - if(rc > 0) { 578 /* Give userspace a chance to handle extraction */ 579 msleep(500); 580 - } else if(rc < 0) { 581 dbg("%s - error checking slots", __FUNCTION__); 582 thread_finished = 1; 583 break; 584 } 585 - } while(atomic_read(&extracting) != 0); 586 } 587 msleep(100); 588 } ··· 601 init_MUTEX_LOCKED(&thread_exit); 602 thread_finished = 0; 603 604 - if(controller->irq) { 605 pid = kernel_thread(event_thread, NULL, 0); 606 - } else { 607 pid = kernel_thread(poll_thread, NULL, 0); 608 - } 609 - if(pid < 0) { 610 err("Can't start up our thread"); 611 return -1; 612 } ··· 618 { 619 thread_finished = 1; 620 dbg("thread finish command given"); 621 - if(controller->irq) { 622 up(&event_semaphore); 623 - } 624 dbg("wait for thread to exit"); 625 down(&thread_exit); 626 } ··· 629 { 630 int status = 0; 631 632 - if(!controller) { 633 - controller = new_controller; 634 - if(controller->irq) { 635 - if(request_irq(controller->irq, 636 - cpci_hp_intr, 637 - controller->irq_flags, 638 - MY_NAME, controller->dev_id)) { 639 - err("Can't get irq %d for the hotplug cPCI controller", controller->irq); 640 - status = -ENODEV; 641 - } 642 - dbg("%s - acquired controller irq %d", __FUNCTION__, 643 - controller->irq); 644 } 645 - } else { 646 - err("cPCI hotplug controller already registered"); 647 - status = -1; 648 } 649 return status; 650 } 651 652 int ··· 681 { 682 int status = 0; 683 684 - if(controller) { 685 - if(atomic_read(&extracting) != 0) { 686 - return -EBUSY; 687 - } 688 - if(!thread_finished) { 689 cpci_stop_thread(); 690 - } 691 - if(controller->irq) { 692 free_irq(controller->irq, controller->dev_id); 693 - } 694 controller = NULL; 695 - } else { 696 status = -ENODEV; 697 - } 698 return status; 699 } 700 ··· 700 int status; 701 702 dbg("%s - enter", __FUNCTION__); 703 - if(!controller) { 704 return -ENODEV; 705 - } 706 707 down_read(&list_rwsem); 708 - if(list_empty(&slot_list)) { 709 up_read(&list_rwsem); 710 return -ENODEV; 711 } 712 up_read(&list_rwsem); 713 714 - if(first) { 715 - status = init_slots(); 716 - if(status) { 717 - return status; 718 - } 719 first = 0; 720 - } 721 722 status = cpci_start_thread(); 723 - if(status) { 724 return status; 725 - } 726 dbg("%s - thread started", __FUNCTION__); 727 728 - if(controller->irq) { 729 /* Start enum interrupt processing */ 730 dbg("%s - enabling irq", __FUNCTION__); 731 controller->ops->enable_irq(); ··· 733 int 734 cpci_hp_stop(void) 735 { 736 - if(!controller) { 737 return -ENODEV; 738 - } 739 - if(atomic_read(&extracting) != 0) { 740 - return -EBUSY; 741 - } 742 - if(controller->irq) { 743 /* Stop enum interrupt processing */ 744 dbg("%s - disabling irq", __FUNCTION__); 745 controller->ops->disable_irq(); 746 } 747 cpci_stop_thread(); 748 return 0; 749 - } 750 - 751 - static void __exit 752 - cleanup_slots(void) 753 - { 754 - struct list_head *tmp; 755 - struct slot *slot; 756 - 757 - /* 758 - * Unregister all of our slots with the pci_hotplug subsystem, 759 - * and free up all memory that we had allocated. 760 - */ 761 - down_write(&list_rwsem); 762 - if(!slots) { 763 - goto null_cleanup; 764 - } 765 - list_for_each(tmp, &slot_list) { 766 - slot = list_entry(tmp, struct slot, slot_list); 767 - list_del(&slot->slot_list); 768 - pci_hp_deregister(slot->hotplug_slot); 769 - kfree(slot->hotplug_slot->info); 770 - kfree(slot->hotplug_slot->name); 771 - kfree(slot->hotplug_slot); 772 - kfree(slot); 773 - } 774 - null_cleanup: 775 - up_write(&list_rwsem); 776 - return; 777 } 778 779 int __init ··· 757 /* 758 * Clean everything up. 759 */ 760 - cleanup_slots(); 761 } 762 763 EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
··· 1 /* 2 * CompactPCI Hot Plug Driver 3 * 4 + * Copyright (C) 2002,2005 SOMA Networks, Inc. 5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 6 * Copyright (C) 2001 IBM Corp. 7 * ··· 45 46 #define dbg(format, arg...) \ 47 do { \ 48 + if (cpci_debug) \ 49 printk (KERN_DEBUG "%s: " format "\n", \ 50 MY_NAME , ## arg); \ 51 + } while (0) 52 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) 53 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) 54 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) ··· 111 112 dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); 113 114 + if (controller->ops->set_power) 115 retval = controller->ops->set_power(slot, 1); 116 return retval; 117 } 118 ··· 126 127 dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); 128 129 + down_write(&list_rwsem); 130 + 131 /* Unconfigure device */ 132 dbg("%s - unconfiguring slot %s", 133 __FUNCTION__, slot->hotplug_slot->name); 134 + if ((retval = cpci_unconfigure_slot(slot))) { 135 err("%s - could not unconfigure slot %s", 136 __FUNCTION__, slot->hotplug_slot->name); 137 + goto disable_error; 138 } 139 dbg("%s - finished unconfiguring slot %s", 140 __FUNCTION__, slot->hotplug_slot->name); 141 142 /* Clear EXT (by setting it) */ 143 + if (cpci_clear_ext(slot)) { 144 err("%s - could not clear EXT for slot %s", 145 __FUNCTION__, slot->hotplug_slot->name); 146 retval = -ENODEV; 147 + goto disable_error; 148 } 149 cpci_led_on(slot); 150 151 + if (controller->ops->set_power) 152 + if ((retval = controller->ops->set_power(slot, 0))) 153 + goto disable_error; 154 155 + if (update_adapter_status(slot->hotplug_slot, 0)) 156 warn("failure to update adapter file"); 157 158 + if (slot->extracting) { 159 slot->extracting = 0; 160 atomic_dec(&extracting); 161 } 162 + disable_error: 163 + up_write(&list_rwsem); 164 return retval; 165 } 166 ··· 165 { 166 u8 power = 1; 167 168 + if (controller->ops->get_power) 169 power = controller->ops->get_power(slot); 170 return power; 171 } 172 ··· 237 int status = -ENOMEM; 238 int i; 239 240 + if (!(controller && bus)) 241 return -ENODEV; 242 243 /* 244 * Create a structure for each slot, and register that slot ··· 316 cpci_hp_unregister_bus(struct pci_bus *bus) 317 { 318 struct slot *slot; 319 + struct slot *tmp; 320 + int status = 0; 321 322 down_write(&list_rwsem); 323 + if (!slots) { 324 up_write(&list_rwsem); 325 return -1; 326 } 327 + list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { 328 + if (slot->bus == bus) { 329 list_del(&slot->slot_list); 330 slots--; 331 + 332 + dbg("deregistering slot %s", slot->hotplug_slot->name); 333 + status = pci_hp_deregister(slot->hotplug_slot); 334 + if (status) { 335 + err("pci_hp_deregister failed with error %d", 336 + status); 337 + break; 338 + } 339 } 340 } 341 up_write(&list_rwsem); 342 + return status; 343 } 344 345 /* This is the interrupt mode interrupt handler */ ··· 351 dbg("entered cpci_hp_intr"); 352 353 /* Check to see if it was our interrupt */ 354 + if ((controller->irq_flags & SA_SHIRQ) && 355 !controller->ops->check_irq(controller->dev_id)) { 356 dbg("exited cpci_hp_intr, not our interrupt"); 357 return IRQ_NONE; ··· 373 * INS bits of the cold-inserted devices. 374 */ 375 static int 376 + init_slots(int clear_ins) 377 { 378 struct slot *slot; 379 struct pci_dev* dev; 380 381 dbg("%s - enter", __FUNCTION__); 382 down_read(&list_rwsem); 383 + if (!slots) { 384 up_read(&list_rwsem); 385 return -1; 386 } 387 + list_for_each_entry(slot, &slot_list, slot_list) { 388 dbg("%s - looking at slot %s", 389 __FUNCTION__, slot->hotplug_slot->name); 390 + if (clear_ins && cpci_check_and_clear_ins(slot)) 391 dbg("%s - cleared INS for slot %s", 392 __FUNCTION__, slot->hotplug_slot->name); 393 + dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0)); 394 + if (dev) { 395 + if (update_adapter_status(slot->hotplug_slot, 1)) 396 + warn("failure to update adapter file"); 397 + if (update_latch_status(slot->hotplug_slot, 1)) 398 + warn("failure to update latch file"); 399 + slot->dev = dev; 400 } 401 } 402 up_read(&list_rwsem); ··· 416 check_slots(void) 417 { 418 struct slot *slot; 419 int extracted; 420 int inserted; 421 u16 hs_csr; 422 423 down_read(&list_rwsem); 424 + if (!slots) { 425 up_read(&list_rwsem); 426 err("no slots registered, shutting down"); 427 return -1; 428 } 429 extracted = inserted = 0; 430 + list_for_each_entry(slot, &slot_list, slot_list) { 431 dbg("%s - looking at slot %s", 432 __FUNCTION__, slot->hotplug_slot->name); 433 + if (cpci_check_and_clear_ins(slot)) { 434 + /* 435 + * Some broken hardware (e.g. PLX 9054AB) asserts 436 + * ENUM# twice... 437 + */ 438 + if (slot->dev) { 439 + warn("slot %s already inserted", 440 + slot->hotplug_slot->name); 441 inserted++; 442 continue; 443 } ··· 452 /* Configure device */ 453 dbg("%s - configuring slot %s", 454 __FUNCTION__, slot->hotplug_slot->name); 455 + if (cpci_configure_slot(slot)) { 456 err("%s - could not configure slot %s", 457 __FUNCTION__, slot->hotplug_slot->name); 458 continue; ··· 465 dbg("%s - slot %s HS_CSR (2) = %04x", 466 __FUNCTION__, slot->hotplug_slot->name, hs_csr); 467 468 + if (update_latch_status(slot->hotplug_slot, 1)) 469 warn("failure to update latch file"); 470 471 + if (update_adapter_status(slot->hotplug_slot, 1)) 472 warn("failure to update adapter file"); 473 474 cpci_led_off(slot); 475 ··· 481 __FUNCTION__, slot->hotplug_slot->name, hs_csr); 482 483 inserted++; 484 + } else if (cpci_check_ext(slot)) { 485 /* Process extraction request */ 486 dbg("%s - slot %s extracted", 487 __FUNCTION__, slot->hotplug_slot->name); ··· 491 dbg("%s - slot %s HS_CSR = %04x", 492 __FUNCTION__, slot->hotplug_slot->name, hs_csr); 493 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 + atomic_inc(&extracting); 500 } 501 extracted++; 502 + } else if (slot->extracting) { 503 hs_csr = cpci_get_hs_csr(slot); 504 + if (hs_csr == 0xffff) { 505 /* 506 * Hmmm, we're likely hosed at this point, should we 507 * bother trying to tell the driver or not? 508 */ 509 err("card in slot %s was improperly removed", 510 slot->hotplug_slot->name); 511 + if (update_adapter_status(slot->hotplug_slot, 0)) 512 warn("failure to update adapter file"); 513 slot->extracting = 0; 514 atomic_dec(&extracting); 515 } ··· 520 up_read(&list_rwsem); 521 dbg("inserted=%d, extracted=%d, extracting=%d", 522 inserted, extracted, atomic_read(&extracting)); 523 + if (inserted || extracted) 524 return extracted; 525 + else if (!atomic_read(&extracting)) { 526 err("cannot find ENUM# source, shutting down"); 527 return -1; 528 } ··· 541 unlock_kernel(); 542 543 dbg("%s - event thread started", __FUNCTION__); 544 + while (1) { 545 dbg("event thread sleeping"); 546 down_interruptible(&event_semaphore); 547 dbg("event thread woken, thread_finished = %d", 548 thread_finished); 549 + if (thread_finished || signal_pending(current)) 550 break; 551 do { 552 rc = check_slots(); ··· 558 thread_finished = 1; 559 break; 560 } 561 + } while (atomic_read(&extracting) && !thread_finished); 562 + if (thread_finished) 563 + break; 564 565 /* Re-enable ENUM# interrupt */ 566 dbg("%s - re-enabling irq", __FUNCTION__); ··· 579 daemonize("cpci_hp_polld"); 580 unlock_kernel(); 581 582 + while (1) { 583 + if (thread_finished || signal_pending(current)) 584 break; 585 + if (controller->ops->query_enum()) { 586 do { 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 + } while (atomic_read(&extracting) && !thread_finished); 597 } 598 msleep(100); 599 } ··· 612 init_MUTEX_LOCKED(&thread_exit); 613 thread_finished = 0; 614 615 + if (controller->irq) 616 pid = kernel_thread(event_thread, NULL, 0); 617 + else 618 pid = kernel_thread(poll_thread, NULL, 0); 619 + if (pid < 0) { 620 err("Can't start up our thread"); 621 return -1; 622 } ··· 630 { 631 thread_finished = 1; 632 dbg("thread finish command given"); 633 + if (controller->irq) 634 up(&event_semaphore); 635 dbg("wait for thread to exit"); 636 down(&thread_exit); 637 } ··· 642 { 643 int status = 0; 644 645 + if (controller) 646 + return -1; 647 + if (!(new_controller && new_controller->ops)) 648 + return -EINVAL; 649 + if (new_controller->irq) { 650 + if (!(new_controller->ops->enable_irq && 651 + new_controller->ops->disable_irq)) 652 + status = -EINVAL; 653 + if (request_irq(new_controller->irq, 654 + cpci_hp_intr, 655 + new_controller->irq_flags, 656 + MY_NAME, 657 + new_controller->dev_id)) { 658 + err("Can't get irq %d for the hotplug cPCI controller", 659 + new_controller->irq); 660 + status = -ENODEV; 661 } 662 + dbg("%s - acquired controller irq %d", 663 + __FUNCTION__, new_controller->irq); 664 } 665 + if (!status) 666 + controller = new_controller; 667 return status; 668 + } 669 + 670 + static void 671 + cleanup_slots(void) 672 + { 673 + struct slot *slot; 674 + struct slot *tmp; 675 + 676 + /* 677 + * Unregister all of our slots with the pci_hotplug subsystem, 678 + * and free up all memory that we had allocated. 679 + */ 680 + down_write(&list_rwsem); 681 + if (!slots) 682 + goto cleanup_null; 683 + list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { 684 + list_del(&slot->slot_list); 685 + pci_hp_deregister(slot->hotplug_slot); 686 + } 687 + cleanup_null: 688 + up_write(&list_rwsem); 689 + return; 690 } 691 692 int ··· 667 { 668 int status = 0; 669 670 + if (controller) { 671 + if (!thread_finished) 672 cpci_stop_thread(); 673 + if (controller->irq) 674 free_irq(controller->irq, controller->dev_id); 675 controller = NULL; 676 + cleanup_slots(); 677 + } else 678 status = -ENODEV; 679 return status; 680 } 681 ··· 691 int status; 692 693 dbg("%s - enter", __FUNCTION__); 694 + if (!controller) 695 return -ENODEV; 696 697 down_read(&list_rwsem); 698 + if (list_empty(&slot_list)) { 699 up_read(&list_rwsem); 700 return -ENODEV; 701 } 702 up_read(&list_rwsem); 703 704 + status = init_slots(first); 705 + if (first) 706 first = 0; 707 + if (status) 708 + return status; 709 710 status = cpci_start_thread(); 711 + if (status) 712 return status; 713 dbg("%s - thread started", __FUNCTION__); 714 715 + if (controller->irq) { 716 /* Start enum interrupt processing */ 717 dbg("%s - enabling irq", __FUNCTION__); 718 controller->ops->enable_irq(); ··· 728 int 729 cpci_hp_stop(void) 730 { 731 + if (!controller) 732 return -ENODEV; 733 + if (controller->irq) { 734 /* Stop enum interrupt processing */ 735 dbg("%s - disabling irq", __FUNCTION__); 736 controller->ops->disable_irq(); 737 } 738 cpci_stop_thread(); 739 return 0; 740 } 741 742 int __init ··· 784 /* 785 * Clean everything up. 786 */ 787 + cpci_hp_stop(); 788 + cpci_hp_unregister_controller(controller); 789 } 790 791 EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
+54 -90
drivers/pci/hotplug/cpci_hotplug_pci.c
··· 1 /* 2 * CompactPCI Hot Plug Driver PCI functions 3 * 4 - * Copyright (C) 2002 by SOMA Networks, Inc. 5 * 6 * All rights reserved. 7 * ··· 38 39 #define dbg(format, arg...) \ 40 do { \ 41 - if(cpci_debug) \ 42 printk (KERN_DEBUG "%s: " format "\n", \ 43 MY_NAME , ## arg); \ 44 - } while(0) 45 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) 46 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) 47 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) ··· 57 hs_cap = pci_bus_find_capability(slot->bus, 58 slot->devfn, 59 PCI_CAP_ID_CHSWP); 60 - if(!hs_cap) { 61 return 0; 62 - } 63 64 - if(pci_bus_read_config_word(slot->bus, 65 slot->devfn, 66 hs_cap + 2, 67 - &hs_csr)) { 68 return 0; 69 - } 70 return hs_csr & 0x0008 ? 1 : 0; 71 } 72 ··· 77 hs_cap = pci_bus_find_capability(slot->bus, 78 slot->devfn, 79 PCI_CAP_ID_CHSWP); 80 - if(!hs_cap) { 81 return 0; 82 - } 83 - 84 - if(pci_bus_read_config_word(slot->bus, 85 slot->devfn, 86 hs_cap + 2, 87 - &hs_csr)) { 88 return 0; 89 - } 90 - if(status) { 91 hs_csr |= HS_CSR_LOO; 92 - } else { 93 hs_csr &= ~HS_CSR_LOO; 94 - } 95 - if(pci_bus_write_config_word(slot->bus, 96 slot->devfn, 97 hs_cap + 2, 98 - hs_csr)) { 99 return 0; 100 - } 101 return 1; 102 } 103 ··· 104 hs_cap = pci_bus_find_capability(slot->bus, 105 slot->devfn, 106 PCI_CAP_ID_CHSWP); 107 - if(!hs_cap) { 108 return 0xFFFF; 109 - } 110 - 111 - if(pci_bus_read_config_word(slot->bus, 112 slot->devfn, 113 hs_cap + 2, 114 - &hs_csr)) { 115 return 0xFFFF; 116 - } 117 return hs_csr; 118 } 119 ··· 123 hs_cap = pci_bus_find_capability(slot->bus, 124 slot->devfn, 125 PCI_CAP_ID_CHSWP); 126 - if(!hs_cap) { 127 return 0; 128 - } 129 - if(pci_bus_read_config_word(slot->bus, 130 slot->devfn, 131 hs_cap + 2, 132 - &hs_csr)) { 133 return 0; 134 - } 135 - if(hs_csr & HS_CSR_INS) { 136 /* Clear INS (by setting it) */ 137 - if(pci_bus_write_config_word(slot->bus, 138 slot->devfn, 139 hs_cap + 2, 140 - hs_csr)) { 141 ins = 0; 142 - } 143 - ins = 1; 144 } 145 return ins; 146 } ··· 152 hs_cap = pci_bus_find_capability(slot->bus, 153 slot->devfn, 154 PCI_CAP_ID_CHSWP); 155 - if(!hs_cap) { 156 return 0; 157 - } 158 - if(pci_bus_read_config_word(slot->bus, 159 slot->devfn, 160 hs_cap + 2, 161 - &hs_csr)) { 162 return 0; 163 - } 164 - if(hs_csr & HS_CSR_EXT) { 165 ext = 1; 166 - } 167 return ext; 168 } 169 ··· 172 hs_cap = pci_bus_find_capability(slot->bus, 173 slot->devfn, 174 PCI_CAP_ID_CHSWP); 175 - if(!hs_cap) { 176 return -ENODEV; 177 - } 178 - if(pci_bus_read_config_word(slot->bus, 179 slot->devfn, 180 hs_cap + 2, 181 - &hs_csr)) { 182 return -ENODEV; 183 - } 184 - if(hs_csr & HS_CSR_EXT) { 185 /* Clear EXT (by setting it) */ 186 - if(pci_bus_write_config_word(slot->bus, 187 slot->devfn, 188 hs_cap + 2, 189 - hs_csr)) { 190 return -ENODEV; 191 - } 192 } 193 return 0; 194 } ··· 198 hs_cap = pci_bus_find_capability(slot->bus, 199 slot->devfn, 200 PCI_CAP_ID_CHSWP); 201 - if(!hs_cap) { 202 return -ENODEV; 203 - } 204 - if(pci_bus_read_config_word(slot->bus, 205 slot->devfn, 206 hs_cap + 2, 207 - &hs_csr)) { 208 return -ENODEV; 209 - } 210 - if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) { 211 hs_csr |= HS_CSR_LOO; 212 - if(pci_bus_write_config_word(slot->bus, 213 slot->devfn, 214 hs_cap + 2, 215 hs_csr)) { ··· 227 hs_cap = pci_bus_find_capability(slot->bus, 228 slot->devfn, 229 PCI_CAP_ID_CHSWP); 230 - if(!hs_cap) { 231 return -ENODEV; 232 - } 233 - if(pci_bus_read_config_word(slot->bus, 234 slot->devfn, 235 hs_cap + 2, 236 - &hs_csr)) { 237 return -ENODEV; 238 - } 239 - if(hs_csr & HS_CSR_LOO) { 240 hs_csr &= ~HS_CSR_LOO; 241 - if(pci_bus_write_config_word(slot->bus, 242 slot->devfn, 243 hs_cap + 2, 244 hs_csr)) { ··· 253 * Device configuration functions 254 */ 255 256 - static void cpci_enable_device(struct pci_dev *dev) 257 - { 258 - struct pci_bus *bus; 259 - 260 - pci_enable_device(dev); 261 - if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 262 - bus = dev->subordinate; 263 - list_for_each_entry(dev, &bus->devices, bus_list) { 264 - cpci_enable_device(dev); 265 - } 266 - } 267 - } 268 - 269 int cpci_configure_slot(struct slot* slot) 270 { 271 unsigned char busnr; ··· 260 261 dbg("%s - enter", __FUNCTION__); 262 263 - if(slot->dev == NULL) { 264 dbg("pci_dev null, finding %02x:%02x:%x", 265 slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); 266 - slot->dev = pci_find_slot(slot->bus->number, slot->devfn); 267 } 268 269 /* Still NULL? Well then scan for it! */ 270 - if(slot->dev == NULL) { 271 int n; 272 dbg("pci_dev still null"); 273 ··· 277 */ 278 n = pci_scan_slot(slot->bus, slot->devfn); 279 dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n); 280 - if(n > 0) 281 pci_bus_add_devices(slot->bus); 282 - slot->dev = pci_find_slot(slot->bus->number, slot->devfn); 283 - if(slot->dev == NULL) { 284 err("Could not find PCI device for slot %02x", slot->number); 285 return 1; 286 } ··· 295 296 pci_bus_assign_resources(slot->dev->bus); 297 298 - cpci_enable_device(slot->dev); 299 - 300 dbg("%s - exit", __FUNCTION__); 301 return 0; 302 } ··· 305 struct pci_dev *dev; 306 307 dbg("%s - enter", __FUNCTION__); 308 - if(!slot->dev) { 309 err("No device for slot %02x\n", slot->number); 310 return -ENODEV; 311 } 312 313 for (i = 0; i < 8; i++) { 314 - dev = pci_find_slot(slot->bus->number, 315 PCI_DEVFN(PCI_SLOT(slot->devfn), i)); 316 - if(dev) { 317 pci_remove_bus_device(dev); 318 slot->dev = NULL; 319 }
··· 1 /* 2 * CompactPCI Hot Plug Driver PCI functions 3 * 4 + * Copyright (C) 2002,2005 by SOMA Networks, Inc. 5 * 6 * All rights reserved. 7 * ··· 38 39 #define dbg(format, arg...) \ 40 do { \ 41 + if (cpci_debug) \ 42 printk (KERN_DEBUG "%s: " format "\n", \ 43 MY_NAME , ## arg); \ 44 + } while (0) 45 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) 46 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) 47 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) ··· 57 hs_cap = pci_bus_find_capability(slot->bus, 58 slot->devfn, 59 PCI_CAP_ID_CHSWP); 60 + if (!hs_cap) 61 return 0; 62 63 + if (pci_bus_read_config_word(slot->bus, 64 slot->devfn, 65 hs_cap + 2, 66 + &hs_csr)) 67 return 0; 68 + 69 return hs_csr & 0x0008 ? 1 : 0; 70 } 71 ··· 78 hs_cap = pci_bus_find_capability(slot->bus, 79 slot->devfn, 80 PCI_CAP_ID_CHSWP); 81 + if (!hs_cap) 82 return 0; 83 + if (pci_bus_read_config_word(slot->bus, 84 slot->devfn, 85 hs_cap + 2, 86 + &hs_csr)) 87 return 0; 88 + if (status) 89 hs_csr |= HS_CSR_LOO; 90 + else 91 hs_csr &= ~HS_CSR_LOO; 92 + if (pci_bus_write_config_word(slot->bus, 93 slot->devfn, 94 hs_cap + 2, 95 + hs_csr)) 96 return 0; 97 return 1; 98 } 99 ··· 110 hs_cap = pci_bus_find_capability(slot->bus, 111 slot->devfn, 112 PCI_CAP_ID_CHSWP); 113 + if (!hs_cap) 114 return 0xFFFF; 115 + if (pci_bus_read_config_word(slot->bus, 116 slot->devfn, 117 hs_cap + 2, 118 + &hs_csr)) 119 return 0xFFFF; 120 return hs_csr; 121 } 122 ··· 132 hs_cap = pci_bus_find_capability(slot->bus, 133 slot->devfn, 134 PCI_CAP_ID_CHSWP); 135 + if (!hs_cap) 136 return 0; 137 + if (pci_bus_read_config_word(slot->bus, 138 slot->devfn, 139 hs_cap + 2, 140 + &hs_csr)) 141 return 0; 142 + if (hs_csr & HS_CSR_INS) { 143 /* Clear INS (by setting it) */ 144 + if (pci_bus_write_config_word(slot->bus, 145 slot->devfn, 146 hs_cap + 2, 147 + hs_csr)) 148 ins = 0; 149 + else 150 + ins = 1; 151 } 152 return ins; 153 } ··· 163 hs_cap = pci_bus_find_capability(slot->bus, 164 slot->devfn, 165 PCI_CAP_ID_CHSWP); 166 + if (!hs_cap) 167 return 0; 168 + if (pci_bus_read_config_word(slot->bus, 169 slot->devfn, 170 hs_cap + 2, 171 + &hs_csr)) 172 return 0; 173 + if (hs_csr & HS_CSR_EXT) 174 ext = 1; 175 return ext; 176 } 177 ··· 186 hs_cap = pci_bus_find_capability(slot->bus, 187 slot->devfn, 188 PCI_CAP_ID_CHSWP); 189 + if (!hs_cap) 190 return -ENODEV; 191 + if (pci_bus_read_config_word(slot->bus, 192 slot->devfn, 193 hs_cap + 2, 194 + &hs_csr)) 195 return -ENODEV; 196 + if (hs_csr & HS_CSR_EXT) { 197 /* Clear EXT (by setting it) */ 198 + if (pci_bus_write_config_word(slot->bus, 199 slot->devfn, 200 hs_cap + 2, 201 + hs_csr)) 202 return -ENODEV; 203 } 204 return 0; 205 } ··· 215 hs_cap = pci_bus_find_capability(slot->bus, 216 slot->devfn, 217 PCI_CAP_ID_CHSWP); 218 + if (!hs_cap) 219 return -ENODEV; 220 + if (pci_bus_read_config_word(slot->bus, 221 slot->devfn, 222 hs_cap + 2, 223 + &hs_csr)) 224 return -ENODEV; 225 + if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) { 226 hs_csr |= HS_CSR_LOO; 227 + if (pci_bus_write_config_word(slot->bus, 228 slot->devfn, 229 hs_cap + 2, 230 hs_csr)) { ··· 246 hs_cap = pci_bus_find_capability(slot->bus, 247 slot->devfn, 248 PCI_CAP_ID_CHSWP); 249 + if (!hs_cap) 250 return -ENODEV; 251 + if (pci_bus_read_config_word(slot->bus, 252 slot->devfn, 253 hs_cap + 2, 254 + &hs_csr)) 255 return -ENODEV; 256 + if (hs_csr & HS_CSR_LOO) { 257 hs_csr &= ~HS_CSR_LOO; 258 + if (pci_bus_write_config_word(slot->bus, 259 slot->devfn, 260 hs_cap + 2, 261 hs_csr)) { ··· 274 * Device configuration functions 275 */ 276 277 int cpci_configure_slot(struct slot* slot) 278 { 279 unsigned char busnr; ··· 294 295 dbg("%s - enter", __FUNCTION__); 296 297 + if (slot->dev == NULL) { 298 dbg("pci_dev null, finding %02x:%02x:%x", 299 slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); 300 + slot->dev = pci_get_slot(slot->bus, slot->devfn); 301 } 302 303 /* Still NULL? Well then scan for it! */ 304 + if (slot->dev == NULL) { 305 int n; 306 dbg("pci_dev still null"); 307 ··· 311 */ 312 n = pci_scan_slot(slot->bus, slot->devfn); 313 dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n); 314 + if (n > 0) 315 pci_bus_add_devices(slot->bus); 316 + slot->dev = pci_get_slot(slot->bus, slot->devfn); 317 + if (slot->dev == NULL) { 318 err("Could not find PCI device for slot %02x", slot->number); 319 return 1; 320 } ··· 329 330 pci_bus_assign_resources(slot->dev->bus); 331 332 dbg("%s - exit", __FUNCTION__); 333 return 0; 334 } ··· 341 struct pci_dev *dev; 342 343 dbg("%s - enter", __FUNCTION__); 344 + if (!slot->dev) { 345 err("No device for slot %02x\n", slot->number); 346 return -ENODEV; 347 } 348 349 for (i = 0; i < 8; i++) { 350 + dev = pci_get_slot(slot->bus, 351 PCI_DEVFN(PCI_SLOT(slot->devfn), i)); 352 + if (dev) { 353 pci_remove_bus_device(dev); 354 slot->dev = NULL; 355 }