aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c2
-rw-r--r--drivers/pci/hotplug/acpiphp.h1
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c10
-rw-r--r--drivers/pci/hotplug/cpqphp_sysfs.c13
-rw-r--r--drivers/pci/hotplug/ibmphp_ebda.c6
-rw-r--r--drivers/pci/hotplug/ibmphp_hpc.c4
-rw-r--r--drivers/pci/hotplug/pciehp.h2
-rw-r--r--drivers/pci/hotplug/pciehp_acpi.c3
-rw-r--r--drivers/pci/hotplug/pciehp_core.c18
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c9
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c20
-rw-r--r--drivers/pci/hotplug/pcihp_slot.c45
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c2
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c1
-rw-r--r--drivers/pci/hotplug/shpchp.h2
-rw-r--r--drivers/pci/hotplug/shpchp_core.c20
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c7
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c26
18 files changed, 122 insertions, 69 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 3bc72d18b121..8f3faf343f75 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -351,7 +351,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
351 * To handle different BIOS behavior, we look for _OSC on a root 351 * To handle different BIOS behavior, we look for _OSC on a root
352 * bridge preferentially (according to PCI fw spec). Later for 352 * bridge preferentially (according to PCI fw spec). Later for
353 * OSHP within the scope of the hotplug controller and its parents, 353 * OSHP within the scope of the hotplug controller and its parents,
354 * upto the host bridge under which this controller exists. 354 * up to the host bridge under which this controller exists.
355 */ 355 */
356 handle = acpi_find_root_bridge_handle(pdev); 356 handle = acpi_find_root_bridge_handle(pdev);
357 if (handle) { 357 if (handle) {
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index bab52047baa8..7722108e78df 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -36,7 +36,6 @@
36#define _ACPIPHP_H 36#define _ACPIPHP_H
37 37
38#include <linux/acpi.h> 38#include <linux/acpi.h>
39#include <linux/kobject.h>
40#include <linux/mutex.h> 39#include <linux/mutex.h>
41#include <linux/pci_hotplug.h> 40#include <linux/pci_hotplug.h>
42 41
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index cb23aa2ebf96..a70fa89f76fd 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -212,6 +212,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
212 212
213 pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); 213 pdev = pci_get_slot(pbus, PCI_DEVFN(device, function));
214 if (pdev) { 214 if (pdev) {
215 pdev->current_state = PCI_D0;
215 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); 216 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
216 pci_dev_put(pdev); 217 pci_dev_put(pdev);
217 } 218 }
@@ -584,7 +585,7 @@ static void remove_bridge(acpi_handle handle)
584 585
585 /* 586 /*
586 * On root bridges with hotplug slots directly underneath (ie, 587 * On root bridges with hotplug slots directly underneath (ie,
587 * no p2p bridge inbetween), we call cleanup_bridge(). 588 * no p2p bridge between), we call cleanup_bridge().
588 * 589 *
589 * The else clause cleans up root bridges that either had no 590 * The else clause cleans up root bridges that either had no
590 * hotplug slots at all, or had a p2p bridge underneath. 591 * hotplug slots at all, or had a p2p bridge underneath.
@@ -826,6 +827,13 @@ static int __ref enable_device(struct acpiphp_slot *slot)
826 acpiphp_set_hpp_values(bus); 827 acpiphp_set_hpp_values(bus);
827 acpiphp_set_acpi_region(slot); 828 acpiphp_set_acpi_region(slot);
828 pci_enable_bridges(bus); 829 pci_enable_bridges(bus);
830
831 list_for_each_entry(dev, &bus->devices, bus_list) {
832 /* Assume that newly added devices are powered on already. */
833 if (!dev->is_added)
834 dev->current_state = PCI_D0;
835 }
836
829 pci_bus_add_devices(bus); 837 pci_bus_add_devices(bus);
830 838
831 list_for_each_entry(func, &slot->funcs, sibling) { 839 list_for_each_entry(func, &slot->funcs, sibling) {
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 56215322930a..4cb30447a486 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -34,10 +34,11 @@
34#include <linux/workqueue.h> 34#include <linux/workqueue.h>
35#include <linux/pci.h> 35#include <linux/pci.h>
36#include <linux/pci_hotplug.h> 36#include <linux/pci_hotplug.h>
37#include <linux/smp_lock.h> 37#include <linux/mutex.h>
38#include <linux/debugfs.h> 38#include <linux/debugfs.h>
39#include "cpqphp.h" 39#include "cpqphp.h"
40 40
41static DEFINE_MUTEX(cpqphp_mutex);
41static int show_ctrl (struct controller *ctrl, char *buf) 42static int show_ctrl (struct controller *ctrl, char *buf)
42{ 43{
43 char *out = buf; 44 char *out = buf;
@@ -147,7 +148,7 @@ static int open(struct inode *inode, struct file *file)
147 struct ctrl_dbg *dbg; 148 struct ctrl_dbg *dbg;
148 int retval = -ENOMEM; 149 int retval = -ENOMEM;
149 150
150 lock_kernel(); 151 mutex_lock(&cpqphp_mutex);
151 dbg = kmalloc(sizeof(*dbg), GFP_KERNEL); 152 dbg = kmalloc(sizeof(*dbg), GFP_KERNEL);
152 if (!dbg) 153 if (!dbg)
153 goto exit; 154 goto exit;
@@ -160,7 +161,7 @@ static int open(struct inode *inode, struct file *file)
160 file->private_data = dbg; 161 file->private_data = dbg;
161 retval = 0; 162 retval = 0;
162exit: 163exit:
163 unlock_kernel(); 164 mutex_unlock(&cpqphp_mutex);
164 return retval; 165 return retval;
165} 166}
166 167
@@ -169,7 +170,7 @@ static loff_t lseek(struct file *file, loff_t off, int whence)
169 struct ctrl_dbg *dbg; 170 struct ctrl_dbg *dbg;
170 loff_t new = -1; 171 loff_t new = -1;
171 172
172 lock_kernel(); 173 mutex_lock(&cpqphp_mutex);
173 dbg = file->private_data; 174 dbg = file->private_data;
174 175
175 switch (whence) { 176 switch (whence) {
@@ -181,10 +182,10 @@ static loff_t lseek(struct file *file, loff_t off, int whence)
181 break; 182 break;
182 } 183 }
183 if (new < 0 || new > dbg->size) { 184 if (new < 0 || new > dbg->size) {
184 unlock_kernel(); 185 mutex_unlock(&cpqphp_mutex);
185 return -EINVAL; 186 return -EINVAL;
186 } 187 }
187 unlock_kernel(); 188 mutex_unlock(&cpqphp_mutex);
188 return (file->f_pos = new); 189 return (file->f_pos = new);
189} 190}
190 191
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
index 5becbdee4027..2850e64dedae 100644
--- a/drivers/pci/hotplug/ibmphp_ebda.c
+++ b/drivers/pci/hotplug/ibmphp_ebda.c
@@ -276,6 +276,12 @@ int __init ibmphp_access_ebda (void)
276 276
277 for (;;) { 277 for (;;) {
278 offset = next_offset; 278 offset = next_offset;
279
280 /* Make sure what we read is still in the mapped section */
281 if (WARN(offset > (ebda_sz * 1024 - 4),
282 "ibmphp_ebda: next read is beyond ebda_sz\n"))
283 break;
284
279 next_offset = readw (io_mem + offset); /* offset of next blk */ 285 next_offset = readw (io_mem + offset); /* offset of next blk */
280 286
281 offset += 2; 287 offset += 2;
diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c
index 1aaf3f32d3cd..f59ed30512b5 100644
--- a/drivers/pci/hotplug/ibmphp_hpc.c
+++ b/drivers/pci/hotplug/ibmphp_hpc.c
@@ -133,8 +133,8 @@ void __init ibmphp_hpc_initvars (void)
133 debug ("%s - Entry\n", __func__); 133 debug ("%s - Entry\n", __func__);
134 134
135 mutex_init(&sem_hpcaccess); 135 mutex_init(&sem_hpcaccess);
136 init_MUTEX (&semOperations); 136 sema_init(&semOperations, 1);
137 init_MUTEX_LOCKED (&sem_exit); 137 sema_init(&sem_exit, 0);
138 to_debug = 0; 138 to_debug = 0;
139 139
140 debug ("%s - Exit\n", __func__); 140 debug ("%s - Exit\n", __func__);
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 73d513989263..838f571027b7 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -36,6 +36,7 @@
36#include <linux/sched.h> /* signal_pending() */ 36#include <linux/sched.h> /* signal_pending() */
37#include <linux/pcieport_if.h> 37#include <linux/pcieport_if.h>
38#include <linux/mutex.h> 38#include <linux/mutex.h>
39#include <linux/workqueue.h>
39 40
40#define MY_NAME "pciehp" 41#define MY_NAME "pciehp"
41 42
@@ -44,6 +45,7 @@ extern int pciehp_poll_time;
44extern int pciehp_debug; 45extern int pciehp_debug;
45extern int pciehp_force; 46extern int pciehp_force;
46extern struct workqueue_struct *pciehp_wq; 47extern struct workqueue_struct *pciehp_wq;
48extern struct workqueue_struct *pciehp_ordered_wq;
47 49
48#define dbg(format, arg...) \ 50#define dbg(format, arg...) \
49do { \ 51do { \
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c
index 2574700db461..5f7226223a62 100644
--- a/drivers/pci/hotplug/pciehp_acpi.c
+++ b/drivers/pci/hotplug/pciehp_acpi.c
@@ -115,7 +115,8 @@ static struct pcie_port_service_driver __initdata dummy_driver = {
115static int __init select_detection_mode(void) 115static int __init select_detection_mode(void)
116{ 116{
117 struct dummy_slot *slot, *tmp; 117 struct dummy_slot *slot, *tmp;
118 pcie_port_service_register(&dummy_driver); 118 if (pcie_port_service_register(&dummy_driver))
119 return PCIEHP_DETECT_ACPI;
119 pcie_port_service_unregister(&dummy_driver); 120 pcie_port_service_unregister(&dummy_driver);
120 list_for_each_entry_safe(slot, tmp, &dummy_slots, list) { 121 list_for_each_entry_safe(slot, tmp, &dummy_slots, list) {
121 list_del(&slot->list); 122 list_del(&slot->list);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index aa5f3ff629ff..7ac8358df8fd 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -43,6 +43,7 @@ int pciehp_poll_mode;
43int pciehp_poll_time; 43int pciehp_poll_time;
44int pciehp_force; 44int pciehp_force;
45struct workqueue_struct *pciehp_wq; 45struct workqueue_struct *pciehp_wq;
46struct workqueue_struct *pciehp_ordered_wq;
46 47
47#define DRIVER_VERSION "0.4" 48#define DRIVER_VERSION "0.4"
48#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" 49#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -340,18 +341,33 @@ static int __init pcied_init(void)
340{ 341{
341 int retval = 0; 342 int retval = 0;
342 343
344 pciehp_wq = alloc_workqueue("pciehp", 0, 0);
345 if (!pciehp_wq)
346 return -ENOMEM;
347
348 pciehp_ordered_wq = alloc_ordered_workqueue("pciehp_ordered", 0);
349 if (!pciehp_ordered_wq) {
350 destroy_workqueue(pciehp_wq);
351 return -ENOMEM;
352 }
353
343 pciehp_firmware_init(); 354 pciehp_firmware_init();
344 retval = pcie_port_service_register(&hpdriver_portdrv); 355 retval = pcie_port_service_register(&hpdriver_portdrv);
345 dbg("pcie_port_service_register = %d\n", retval); 356 dbg("pcie_port_service_register = %d\n", retval);
346 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 357 info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
347 if (retval) 358 if (retval) {
359 destroy_workqueue(pciehp_ordered_wq);
360 destroy_workqueue(pciehp_wq);
348 dbg("Failure to register service\n"); 361 dbg("Failure to register service\n");
362 }
349 return retval; 363 return retval;
350} 364}
351 365
352static void __exit pcied_cleanup(void) 366static void __exit pcied_cleanup(void)
353{ 367{
354 dbg("unload_pciehpd()\n"); 368 dbg("unload_pciehpd()\n");
369 destroy_workqueue(pciehp_ordered_wq);
370 destroy_workqueue(pciehp_wq);
355 pcie_port_service_unregister(&hpdriver_portdrv); 371 pcie_port_service_unregister(&hpdriver_portdrv);
356 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); 372 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
357} 373}
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 8f58148be044..085dbb5fc168 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -32,7 +32,6 @@
32#include <linux/types.h> 32#include <linux/types.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/pci.h> 34#include <linux/pci.h>
35#include <linux/workqueue.h>
36#include "../pci.h" 35#include "../pci.h"
37#include "pciehp.h" 36#include "pciehp.h"
38 37
@@ -50,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
50 info->p_slot = p_slot; 49 info->p_slot = p_slot;
51 INIT_WORK(&info->work, interrupt_event_handler); 50 INIT_WORK(&info->work, interrupt_event_handler);
52 51
53 schedule_work(&info->work); 52 queue_work(pciehp_wq, &info->work);
54 53
55 return 0; 54 return 0;
56} 55}
@@ -345,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
345 kfree(info); 344 kfree(info);
346 goto out; 345 goto out;
347 } 346 }
348 queue_work(pciehp_wq, &info->work); 347 queue_work(pciehp_ordered_wq, &info->work);
349 out: 348 out:
350 mutex_unlock(&p_slot->lock); 349 mutex_unlock(&p_slot->lock);
351} 350}
@@ -378,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot)
378 if (ATTN_LED(ctrl)) 377 if (ATTN_LED(ctrl))
379 pciehp_set_attention_status(p_slot, 0); 378 pciehp_set_attention_status(p_slot, 0);
380 379
381 schedule_delayed_work(&p_slot->work, 5*HZ); 380 queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ);
382 break; 381 break;
383 case BLINKINGOFF_STATE: 382 case BLINKINGOFF_STATE:
384 case BLINKINGON_STATE: 383 case BLINKINGON_STATE:
@@ -440,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot)
440 else 439 else
441 p_slot->state = POWERON_STATE; 440 p_slot->state = POWERON_STATE;
442 441
443 queue_work(pciehp_wq, &info->work); 442 queue_work(pciehp_ordered_wq, &info->work);
444} 443}
445 444
446static void interrupt_event_handler(struct work_struct *work) 445static void interrupt_event_handler(struct work_struct *work)
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 0cd42047d89b..50a23da5d24d 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -41,8 +41,6 @@
41#include "../pci.h" 41#include "../pci.h"
42#include "pciehp.h" 42#include "pciehp.h"
43 43
44static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
45
46static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) 44static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value)
47{ 45{
48 struct pci_dev *dev = ctrl->pcie->port; 46 struct pci_dev *dev = ctrl->pcie->port;
@@ -805,8 +803,8 @@ static void pcie_cleanup_slot(struct controller *ctrl)
805{ 803{
806 struct slot *slot = ctrl->slot; 804 struct slot *slot = ctrl->slot;
807 cancel_delayed_work(&slot->work); 805 cancel_delayed_work(&slot->work);
808 flush_scheduled_work();
809 flush_workqueue(pciehp_wq); 806 flush_workqueue(pciehp_wq);
807 flush_workqueue(pciehp_ordered_wq);
810 kfree(slot); 808 kfree(slot);
811} 809}
812 810
@@ -912,16 +910,6 @@ struct controller *pcie_init(struct pcie_device *dev)
912 /* Disable sotfware notification */ 910 /* Disable sotfware notification */
913 pcie_disable_notification(ctrl); 911 pcie_disable_notification(ctrl);
914 912
915 /*
916 * If this is the first controller to be initialized,
917 * initialize the pciehp work queue
918 */
919 if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
920 pciehp_wq = create_singlethread_workqueue("pciehpd");
921 if (!pciehp_wq)
922 goto abort_ctrl;
923 }
924
925 ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", 913 ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
926 pdev->vendor, pdev->device, pdev->subsystem_vendor, 914 pdev->vendor, pdev->device, pdev->subsystem_vendor,
927 pdev->subsystem_device); 915 pdev->subsystem_device);
@@ -941,11 +929,5 @@ void pciehp_release_ctrl(struct controller *ctrl)
941{ 929{
942 pcie_shutdown_notification(ctrl); 930 pcie_shutdown_notification(ctrl);
943 pcie_cleanup_slot(ctrl); 931 pcie_cleanup_slot(ctrl);
944 /*
945 * If this is the last controller to be released, destroy the
946 * pciehp work queue
947 */
948 if (atomic_dec_and_test(&pciehp_num_controllers))
949 destroy_workqueue(pciehp_wq);
950 kfree(ctrl); 932 kfree(ctrl);
951} 933}
diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c
index 80b461c98557..749fdf070319 100644
--- a/drivers/pci/hotplug/pcihp_slot.c
+++ b/drivers/pci/hotplug/pcihp_slot.c
@@ -158,6 +158,47 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
158 */ 158 */
159} 159}
160 160
161/* Program PCIE MaxPayload setting on device: ensure parent maxpayload <= device */
162static int pci_set_payload(struct pci_dev *dev)
163{
164 int pos, ppos;
165 u16 pctl, psz;
166 u16 dctl, dsz, dcap, dmax;
167 struct pci_dev *parent;
168
169 parent = dev->bus->self;
170 pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
171 if (!pos)
172 return 0;
173
174 /* Read Device MaxPayload capability and setting */
175 pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &dctl);
176 pci_read_config_word(dev, pos + PCI_EXP_DEVCAP, &dcap);
177 dsz = (dctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
178 dmax = (dcap & PCI_EXP_DEVCAP_PAYLOAD);
179
180 /* Read Parent MaxPayload setting */
181 ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
182 if (!ppos)
183 return 0;
184 pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
185 psz = (pctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
186
187 /* If parent payload > device max payload -> error
188 * If parent payload > device payload -> set speed
189 * If parent payload <= device payload -> do nothing
190 */
191 if (psz > dmax)
192 return -1;
193 else if (psz > dsz) {
194 dev_info(&dev->dev, "Setting MaxPayload to %d\n", 128 << psz);
195 pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
196 (dctl & ~PCI_EXP_DEVCTL_PAYLOAD) +
197 (psz << 5));
198 }
199 return 0;
200}
201
161void pci_configure_slot(struct pci_dev *dev) 202void pci_configure_slot(struct pci_dev *dev)
162{ 203{
163 struct pci_dev *cdev; 204 struct pci_dev *cdev;
@@ -169,6 +210,10 @@ void pci_configure_slot(struct pci_dev *dev)
169 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) 210 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
170 return; 211 return;
171 212
213 ret = pci_set_payload(dev);
214 if (ret)
215 dev_warn(&dev->dev, "could not set device max payload\n");
216
172 memset(&hpp, 0, sizeof(hpp)); 217 memset(&hpp, 0, sizeof(hpp));
173 ret = pci_get_hp_params(dev, &hpp); 218 ret = pci_get_hp_params(dev, &hpp);
174 if (ret) 219 if (ret)
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index ef7411c660b9..758adb5f47fd 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -290,7 +290,7 @@ static int is_php_dn(struct device_node *dn, const int **indexes,
290 * @dn: device node of slot 290 * @dn: device node of slot
291 * 291 *
292 * This subroutine will register a hotplugable slot with the 292 * This subroutine will register a hotplugable slot with the
293 * PCI hotplug infrastructure. This routine is typicaly called 293 * PCI hotplug infrastructure. This routine is typically called
294 * during boot time, if the hotplug slots are present at boot time, 294 * during boot time, if the hotplug slots are present at boot time,
295 * or is called later, by the dlpar add code, if the slot is 295 * or is called later, by the dlpar add code, if the slot is
296 * being dynamically added during runtime. 296 * being dynamically added during runtime.
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index 2ea9cf1a8d02..b283bbea6d24 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -24,7 +24,6 @@
24 */ 24 */
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/kobject.h>
28#include <linux/sysfs.h> 27#include <linux/sysfs.h>
29#include <linux/pci.h> 28#include <linux/pci.h>
30#include <linux/string.h> 29#include <linux/string.h>
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index d2627e1c3ac1..e0c90e643b5f 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -35,6 +35,7 @@
35#include <linux/delay.h> 35#include <linux/delay.h>
36#include <linux/sched.h> /* signal_pending(), struct timer_list */ 36#include <linux/sched.h> /* signal_pending(), struct timer_list */
37#include <linux/mutex.h> 37#include <linux/mutex.h>
38#include <linux/workqueue.h>
38 39
39#if !defined(MODULE) 40#if !defined(MODULE)
40 #define MY_NAME "shpchp" 41 #define MY_NAME "shpchp"
@@ -46,6 +47,7 @@ extern int shpchp_poll_mode;
46extern int shpchp_poll_time; 47extern int shpchp_poll_time;
47extern int shpchp_debug; 48extern int shpchp_debug;
48extern struct workqueue_struct *shpchp_wq; 49extern struct workqueue_struct *shpchp_wq;
50extern struct workqueue_struct *shpchp_ordered_wq;
49 51
50#define dbg(format, arg...) \ 52#define dbg(format, arg...) \
51do { \ 53do { \
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index a7bd5048396e..aca972bbfb4c 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -33,7 +33,6 @@
33#include <linux/types.h> 33#include <linux/types.h>
34#include <linux/slab.h> 34#include <linux/slab.h>
35#include <linux/pci.h> 35#include <linux/pci.h>
36#include <linux/workqueue.h>
37#include "shpchp.h" 36#include "shpchp.h"
38 37
39/* Global variables */ 38/* Global variables */
@@ -41,6 +40,7 @@ int shpchp_debug;
41int shpchp_poll_mode; 40int shpchp_poll_mode;
42int shpchp_poll_time; 41int shpchp_poll_time;
43struct workqueue_struct *shpchp_wq; 42struct workqueue_struct *shpchp_wq;
43struct workqueue_struct *shpchp_ordered_wq;
44 44
45#define DRIVER_VERSION "0.4" 45#define DRIVER_VERSION "0.4"
46#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" 46#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -174,8 +174,8 @@ void cleanup_slots(struct controller *ctrl)
174 slot = list_entry(tmp, struct slot, slot_list); 174 slot = list_entry(tmp, struct slot, slot_list);
175 list_del(&slot->slot_list); 175 list_del(&slot->slot_list);
176 cancel_delayed_work(&slot->work); 176 cancel_delayed_work(&slot->work);
177 flush_scheduled_work();
178 flush_workqueue(shpchp_wq); 177 flush_workqueue(shpchp_wq);
178 flush_workqueue(shpchp_ordered_wq);
179 pci_hp_deregister(slot->hotplug_slot); 179 pci_hp_deregister(slot->hotplug_slot);
180 } 180 }
181} 181}
@@ -360,9 +360,23 @@ static int __init shpcd_init(void)
360{ 360{
361 int retval = 0; 361 int retval = 0;
362 362
363 shpchp_wq = alloc_ordered_workqueue("shpchp", 0);
364 if (!shpchp_wq)
365 return -ENOMEM;
366
367 shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0);
368 if (!shpchp_ordered_wq) {
369 destroy_workqueue(shpchp_wq);
370 return -ENOMEM;
371 }
372
363 retval = pci_register_driver(&shpc_driver); 373 retval = pci_register_driver(&shpc_driver);
364 dbg("%s: pci_register_driver = %d\n", __func__, retval); 374 dbg("%s: pci_register_driver = %d\n", __func__, retval);
365 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 375 info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
376 if (retval) {
377 destroy_workqueue(shpchp_ordered_wq);
378 destroy_workqueue(shpchp_wq);
379 }
366 return retval; 380 return retval;
367} 381}
368 382
@@ -370,6 +384,8 @@ static void __exit shpcd_cleanup(void)
370{ 384{
371 dbg("unload_shpchpd()\n"); 385 dbg("unload_shpchpd()\n");
372 pci_unregister_driver(&shpc_driver); 386 pci_unregister_driver(&shpc_driver);
387 destroy_workqueue(shpchp_ordered_wq);
388 destroy_workqueue(shpchp_wq);
373 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); 389 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
374} 390}
375 391
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 3387fbfb0c54..b00b09bdd38a 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -32,7 +32,6 @@
32#include <linux/types.h> 32#include <linux/types.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/pci.h> 34#include <linux/pci.h>
35#include <linux/workqueue.h>
36#include "../pci.h" 35#include "../pci.h"
37#include "shpchp.h" 36#include "shpchp.h"
38 37
@@ -52,7 +51,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
52 info->p_slot = p_slot; 51 info->p_slot = p_slot;
53 INIT_WORK(&info->work, interrupt_event_handler); 52 INIT_WORK(&info->work, interrupt_event_handler);
54 53
55 schedule_work(&info->work); 54 queue_work(shpchp_wq, &info->work);
56 55
57 return 0; 56 return 0;
58} 57}
@@ -457,7 +456,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work)
457 kfree(info); 456 kfree(info);
458 goto out; 457 goto out;
459 } 458 }
460 queue_work(shpchp_wq, &info->work); 459 queue_work(shpchp_ordered_wq, &info->work);
461 out: 460 out:
462 mutex_unlock(&p_slot->lock); 461 mutex_unlock(&p_slot->lock);
463} 462}
@@ -505,7 +504,7 @@ static void handle_button_press_event(struct slot *p_slot)
505 p_slot->hpc_ops->green_led_blink(p_slot); 504 p_slot->hpc_ops->green_led_blink(p_slot);
506 p_slot->hpc_ops->set_attention_status(p_slot, 0); 505 p_slot->hpc_ops->set_attention_status(p_slot, 0);
507 506
508 schedule_delayed_work(&p_slot->work, 5*HZ); 507 queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ);
509 break; 508 break;
510 case BLINKINGOFF_STATE: 509 case BLINKINGOFF_STATE:
511 case BLINKINGON_STATE: 510 case BLINKINGON_STATE:
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index d3985e7deab7..36547f0ce305 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -179,8 +179,6 @@
179#define SLOT_EVENT_LATCH 0x2 179#define SLOT_EVENT_LATCH 0x2
180#define SLOT_SERR_INT_MASK 0x3 180#define SLOT_SERR_INT_MASK 0x3
181 181
182static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
183
184static irqreturn_t shpc_isr(int irq, void *dev_id); 182static irqreturn_t shpc_isr(int irq, void *dev_id);
185static void start_int_poll_timer(struct controller *ctrl, int sec); 183static void start_int_poll_timer(struct controller *ctrl, int sec);
186static int hpc_check_cmd_status(struct controller *ctrl); 184static int hpc_check_cmd_status(struct controller *ctrl);
@@ -614,13 +612,6 @@ static void hpc_release_ctlr(struct controller *ctrl)
614 612
615 iounmap(ctrl->creg); 613 iounmap(ctrl->creg);
616 release_mem_region(ctrl->mmio_base, ctrl->mmio_size); 614 release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
617
618 /*
619 * If this is the last controller to be released, destroy the
620 * shpchpd work queue
621 */
622 if (atomic_dec_and_test(&shpchp_num_controllers))
623 destroy_workqueue(shpchp_wq);
624} 615}
625 616
626static int hpc_power_on_slot(struct slot * slot) 617static int hpc_power_on_slot(struct slot * slot)
@@ -1077,9 +1068,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
1077 1068
1078 rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, 1069 rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
1079 MY_NAME, (void *)ctrl); 1070 MY_NAME, (void *)ctrl);
1080 ctrl_dbg(ctrl, "request_irq %d for hpc%d (returns %d)\n", 1071 ctrl_dbg(ctrl, "request_irq %d (returns %d)\n",
1081 ctrl->pci_dev->irq, 1072 ctrl->pci_dev->irq, rc);
1082 atomic_read(&shpchp_num_controllers), rc);
1083 if (rc) { 1073 if (rc) {
1084 ctrl_err(ctrl, "Can't get irq %d for the hotplug " 1074 ctrl_err(ctrl, "Can't get irq %d for the hotplug "
1085 "controller\n", ctrl->pci_dev->irq); 1075 "controller\n", ctrl->pci_dev->irq);
@@ -1092,18 +1082,6 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
1092 shpc_get_cur_bus_speed(ctrl); 1082 shpc_get_cur_bus_speed(ctrl);
1093 1083
1094 /* 1084 /*
1095 * If this is the first controller to be initialized,
1096 * initialize the shpchpd work queue
1097 */
1098 if (atomic_add_return(1, &shpchp_num_controllers) == 1) {
1099 shpchp_wq = create_singlethread_workqueue("shpchpd");
1100 if (!shpchp_wq) {
1101 rc = -ENOMEM;
1102 goto abort_iounmap;
1103 }
1104 }
1105
1106 /*
1107 * Unmask all event interrupts of all slots 1085 * Unmask all event interrupts of all slots
1108 */ 1086 */
1109 for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 1087 for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {