Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '3.8-pci-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci

Pull PCI updates from Bjorn Helgaas:
"The most important is a fix for a pciehp deadlock that occurs when
unplugging a Thunderbolt adapter. We also applied the same fix to
shpchp, removed CONFIG_EXPERIMENTAL dependencies, fixed a
pcie_aspm=force problem, and fixed a refcount leak.

Details:

- Hotplug
PCI: pciehp: Use per-slot workqueues to avoid deadlock
PCI: shpchp: Make shpchp_wq non-ordered
PCI: shpchp: Handle push button event asynchronously
PCI: shpchp: Use per-slot workqueues to avoid deadlock

- Power management
PCI: Allow pcie_aspm=force even when FADT indicates it is unsupported

- Misc
PCI/AER: pci_get_domain_bus_and_slot() call missing required pci_dev_put()
PCI: remove depends on CONFIG_EXPERIMENTAL"

* tag '3.8-pci-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
PCI: remove depends on CONFIG_EXPERIMENTAL
PCI: Allow pcie_aspm=force even when FADT indicates it is unsupported
PCI: shpchp: Use per-slot workqueues to avoid deadlock
PCI: shpchp: Handle push button event asynchronously
PCI: shpchp: Make shpchp_wq non-ordered
PCI/AER: pci_get_domain_bus_and_slot() call missing required pci_dev_put()
PCI: pciehp: Use per-slot workqueues to avoid deadlock

+40 -43
+1 -1
drivers/pci/hotplug/pciehp.h
··· 44 44 extern int pciehp_poll_time; 45 45 extern bool pciehp_debug; 46 46 extern bool pciehp_force; 47 - extern struct workqueue_struct *pciehp_wq; 48 47 49 48 #define dbg(format, arg...) \ 50 49 do { \ ··· 77 78 struct hotplug_slot *hotplug_slot; 78 79 struct delayed_work work; /* work for button event */ 79 80 struct mutex lock; 81 + struct workqueue_struct *wq; 80 82 }; 81 83 82 84 struct event_info {
+2 -9
drivers/pci/hotplug/pciehp_core.c
··· 42 42 bool pciehp_poll_mode; 43 43 int pciehp_poll_time; 44 44 bool pciehp_force; 45 - struct workqueue_struct *pciehp_wq; 46 45 47 46 #define DRIVER_VERSION "0.4" 48 47 #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" ··· 339 340 { 340 341 int retval = 0; 341 342 342 - pciehp_wq = alloc_workqueue("pciehp", 0, 0); 343 - if (!pciehp_wq) 344 - return -ENOMEM; 345 - 346 343 pciehp_firmware_init(); 347 344 retval = pcie_port_service_register(&hpdriver_portdrv); 348 345 dbg("pcie_port_service_register = %d\n", retval); 349 346 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 350 - if (retval) { 351 - destroy_workqueue(pciehp_wq); 347 + if (retval) 352 348 dbg("Failure to register service\n"); 353 - } 349 + 354 350 return retval; 355 351 } 356 352 ··· 353 359 { 354 360 dbg("unload_pciehpd()\n"); 355 361 pcie_port_service_unregister(&hpdriver_portdrv); 356 - destroy_workqueue(pciehp_wq); 357 362 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); 358 363 } 359 364
+4 -4
drivers/pci/hotplug/pciehp_ctrl.c
··· 49 49 info->p_slot = p_slot; 50 50 INIT_WORK(&info->work, interrupt_event_handler); 51 51 52 - queue_work(pciehp_wq, &info->work); 52 + queue_work(p_slot->wq, &info->work); 53 53 54 54 return 0; 55 55 } ··· 344 344 kfree(info); 345 345 goto out; 346 346 } 347 - queue_work(pciehp_wq, &info->work); 347 + queue_work(p_slot->wq, &info->work); 348 348 out: 349 349 mutex_unlock(&p_slot->lock); 350 350 } ··· 377 377 if (ATTN_LED(ctrl)) 378 378 pciehp_set_attention_status(p_slot, 0); 379 379 380 - queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ); 380 + queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); 381 381 break; 382 382 case BLINKINGOFF_STATE: 383 383 case BLINKINGON_STATE: ··· 439 439 else 440 440 p_slot->state = POWERON_STATE; 441 441 442 - queue_work(pciehp_wq, &info->work); 442 + queue_work(p_slot->wq, &info->work); 443 443 } 444 444 445 445 static void interrupt_event_handler(struct work_struct *work)
+10 -1
drivers/pci/hotplug/pciehp_hpc.c
··· 773 773 static int pcie_init_slot(struct controller *ctrl) 774 774 { 775 775 struct slot *slot; 776 + char name[32]; 776 777 777 778 slot = kzalloc(sizeof(*slot), GFP_KERNEL); 778 779 if (!slot) 779 780 return -ENOMEM; 781 + 782 + snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl)); 783 + slot->wq = alloc_workqueue(name, 0, 0); 784 + if (!slot->wq) 785 + goto abort; 780 786 781 787 slot->ctrl = ctrl; 782 788 mutex_init(&slot->lock); 783 789 INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); 784 790 ctrl->slot = slot; 785 791 return 0; 792 + abort: 793 + kfree(slot); 794 + return -ENOMEM; 786 795 } 787 796 788 797 static void pcie_cleanup_slot(struct controller *ctrl) 789 798 { 790 799 struct slot *slot = ctrl->slot; 791 800 cancel_delayed_work(&slot->work); 792 - flush_workqueue(pciehp_wq); 801 + destroy_workqueue(slot->wq); 793 802 kfree(slot); 794 803 } 795 804
+1 -2
drivers/pci/hotplug/shpchp.h
··· 46 46 extern bool shpchp_poll_mode; 47 47 extern int shpchp_poll_time; 48 48 extern bool shpchp_debug; 49 - extern struct workqueue_struct *shpchp_wq; 50 - extern struct workqueue_struct *shpchp_ordered_wq; 51 49 52 50 #define dbg(format, arg...) \ 53 51 do { \ ··· 89 91 struct list_head slot_list; 90 92 struct delayed_work work; /* work for button event */ 91 93 struct mutex lock; 94 + struct workqueue_struct *wq; 92 95 u8 hp_slot; 93 96 }; 94 97
+14 -22
drivers/pci/hotplug/shpchp_core.c
··· 39 39 bool shpchp_debug; 40 40 bool shpchp_poll_mode; 41 41 int shpchp_poll_time; 42 - struct workqueue_struct *shpchp_wq; 43 - struct workqueue_struct *shpchp_ordered_wq; 44 42 45 43 #define DRIVER_VERSION "0.4" 46 44 #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" ··· 127 129 slot->device = ctrl->slot_device_offset + i; 128 130 slot->hpc_ops = ctrl->hpc_ops; 129 131 slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); 132 + 133 + snprintf(name, sizeof(name), "shpchp-%d", slot->number); 134 + slot->wq = alloc_workqueue(name, 0, 0); 135 + if (!slot->wq) { 136 + retval = -ENOMEM; 137 + goto error_info; 138 + } 139 + 130 140 mutex_init(&slot->lock); 131 141 INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work); 132 142 ··· 154 148 if (retval) { 155 149 ctrl_err(ctrl, "pci_hp_register failed with error %d\n", 156 150 retval); 157 - goto error_info; 151 + goto error_slotwq; 158 152 } 159 153 160 154 get_power_status(hotplug_slot, &info->power_status); ··· 166 160 } 167 161 168 162 return 0; 163 + error_slotwq: 164 + destroy_workqueue(slot->wq); 169 165 error_info: 170 166 kfree(info); 171 167 error_hpslot: ··· 188 180 slot = list_entry(tmp, struct slot, slot_list); 189 181 list_del(&slot->slot_list); 190 182 cancel_delayed_work(&slot->work); 191 - flush_workqueue(shpchp_wq); 192 - flush_workqueue(shpchp_ordered_wq); 183 + destroy_workqueue(slot->wq); 193 184 pci_hp_deregister(slot->hotplug_slot); 194 185 } 195 186 } ··· 371 364 372 365 static int __init shpcd_init(void) 373 366 { 374 - int retval = 0; 375 - 376 - shpchp_wq = alloc_ordered_workqueue("shpchp", 0); 377 - if (!shpchp_wq) 378 - return -ENOMEM; 379 - 380 - shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0); 381 - if (!shpchp_ordered_wq) { 382 - destroy_workqueue(shpchp_wq); 383 - return -ENOMEM; 384 - } 367 + int retval; 385 368 386 369 retval = pci_register_driver(&shpc_driver); 387 370 dbg("%s: pci_register_driver = %d\n", __func__, retval); 388 371 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 389 - if (retval) { 390 - destroy_workqueue(shpchp_ordered_wq); 391 - destroy_workqueue(shpchp_wq); 392 - } 372 + 393 373 return retval; 394 374 } 395 375 ··· 384 390 { 385 391 dbg("unload_shpchpd()\n"); 386 392 pci_unregister_driver(&shpc_driver); 387 - destroy_workqueue(shpchp_ordered_wq); 388 - destroy_workqueue(shpchp_wq); 389 393 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); 390 394 } 391 395
+3 -3
drivers/pci/hotplug/shpchp_ctrl.c
··· 51 51 info->p_slot = p_slot; 52 52 INIT_WORK(&info->work, interrupt_event_handler); 53 53 54 - queue_work(shpchp_wq, &info->work); 54 + queue_work(p_slot->wq, &info->work); 55 55 56 56 return 0; 57 57 } ··· 453 453 kfree(info); 454 454 goto out; 455 455 } 456 - queue_work(shpchp_ordered_wq, &info->work); 456 + queue_work(p_slot->wq, &info->work); 457 457 out: 458 458 mutex_unlock(&p_slot->lock); 459 459 } ··· 501 501 p_slot->hpc_ops->green_led_blink(p_slot); 502 502 p_slot->hpc_ops->set_attention_status(p_slot, 0); 503 503 504 - queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); 504 + queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); 505 505 break; 506 506 case BLINKINGOFF_STATE: 507 507 case BLINKINGON_STATE:
+1 -1
drivers/pci/pcie/Kconfig
··· 82 82 83 83 config PCIE_PME 84 84 def_bool y 85 - depends on PCIEPORTBUS && PM_RUNTIME && EXPERIMENTAL && ACPI 85 + depends on PCIEPORTBUS && PM_RUNTIME && ACPI
+1
drivers/pci/pcie/aer/aerdrv_core.c
··· 630 630 continue; 631 631 } 632 632 do_recovery(pdev, entry.severity); 633 + pci_dev_put(pdev); 633 634 } 634 635 } 635 636 #endif
+3
drivers/pci/pcie/aspm.c
··· 771 771 { 772 772 struct pci_dev *child; 773 773 774 + if (aspm_force) 775 + return; 776 + 774 777 /* 775 778 * Clear any ASPM setup that the firmware has carried out on this bus 776 779 */