diff options
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r-- | drivers/pci/hotplug/cpqphp_sysfs.c | 13 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 18 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 9 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 20 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp.h | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_core.c | 20 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_ctrl.c | 7 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_hpc.c | 26 |
9 files changed, 56 insertions, 61 deletions
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index 56215322930..4cb30447a48 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c @@ -34,10 +34,11 @@ #include <linux/workqueue.h> #include <linux/pci.h> #include <linux/pci_hotplug.h> -#include <linux/smp_lock.h> +#include <linux/mutex.h> #include <linux/debugfs.h> #include "cpqphp.h" +static DEFINE_MUTEX(cpqphp_mutex); static int show_ctrl (struct controller *ctrl, char *buf) { char *out = buf; @@ -147,7 +148,7 @@ static int open(struct inode *inode, struct file *file) struct ctrl_dbg *dbg; int retval = -ENOMEM; - lock_kernel(); + mutex_lock(&cpqphp_mutex); dbg = kmalloc(sizeof(*dbg), GFP_KERNEL); if (!dbg) goto exit; @@ -160,7 +161,7 @@ static int open(struct inode *inode, struct file *file) file->private_data = dbg; retval = 0; exit: - unlock_kernel(); + mutex_unlock(&cpqphp_mutex); return retval; } @@ -169,7 +170,7 @@ static loff_t lseek(struct file *file, loff_t off, int whence) struct ctrl_dbg *dbg; loff_t new = -1; - lock_kernel(); + mutex_lock(&cpqphp_mutex); dbg = file->private_data; switch (whence) { @@ -181,10 +182,10 @@ static loff_t lseek(struct file *file, loff_t off, int whence) break; } if (new < 0 || new > dbg->size) { - unlock_kernel(); + mutex_unlock(&cpqphp_mutex); return -EINVAL; } - unlock_kernel(); + mutex_unlock(&cpqphp_mutex); return (file->f_pos = new); } diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 73d51398926..838f571027b 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -36,6 +36,7 @@ #include <linux/sched.h> /* signal_pending() */ #include <linux/pcieport_if.h> #include <linux/mutex.h> +#include <linux/workqueue.h> #define MY_NAME "pciehp" @@ -44,6 +45,7 @@ extern int pciehp_poll_time; extern int pciehp_debug; extern int pciehp_force; extern struct workqueue_struct *pciehp_wq; +extern struct workqueue_struct *pciehp_ordered_wq; #define dbg(format, arg...) \ do { \ diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index aa5f3ff629f..7ac8358df8f 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -43,6 +43,7 @@ int pciehp_poll_mode; int pciehp_poll_time; int pciehp_force; struct workqueue_struct *pciehp_wq; +struct workqueue_struct *pciehp_ordered_wq; #define DRIVER_VERSION "0.4" #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) { int retval = 0; + pciehp_wq = alloc_workqueue("pciehp", 0, 0); + if (!pciehp_wq) + return -ENOMEM; + + pciehp_ordered_wq = alloc_ordered_workqueue("pciehp_ordered", 0); + if (!pciehp_ordered_wq) { + destroy_workqueue(pciehp_wq); + return -ENOMEM; + } + pciehp_firmware_init(); retval = pcie_port_service_register(&hpdriver_portdrv); dbg("pcie_port_service_register = %d\n", retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - if (retval) + if (retval) { + destroy_workqueue(pciehp_ordered_wq); + destroy_workqueue(pciehp_wq); dbg("Failure to register service\n"); + } return retval; } static void __exit pcied_cleanup(void) { dbg("unload_pciehpd()\n"); + destroy_workqueue(pciehp_ordered_wq); + destroy_workqueue(pciehp_wq); pcie_port_service_unregister(&hpdriver_portdrv); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 8f58148be04..085dbb5fc16 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -32,7 +32,6 @@ #include <linux/types.h> #include <linux/slab.h> #include <linux/pci.h> -#include <linux/workqueue.h> #include "../pci.h" #include "pciehp.h" @@ -50,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->p_slot = p_slot; INIT_WORK(&info->work, interrupt_event_handler); - schedule_work(&info->work); + queue_work(pciehp_wq, &info->work); return 0; } @@ -345,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) kfree(info); goto out; } - queue_work(pciehp_wq, &info->work); + queue_work(pciehp_ordered_wq, &info->work); out: mutex_unlock(&p_slot->lock); } @@ -378,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot) if (ATTN_LED(ctrl)) pciehp_set_attention_status(p_slot, 0); - schedule_delayed_work(&p_slot->work, 5*HZ); + queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ); break; case BLINKINGOFF_STATE: case BLINKINGON_STATE: @@ -440,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot) else p_slot->state = POWERON_STATE; - queue_work(pciehp_wq, &info->work); + queue_work(pciehp_ordered_wq, &info->work); } static 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 0cd42047d89..50a23da5d24 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -41,8 +41,6 @@ #include "../pci.h" #include "pciehp.h" -static atomic_t pciehp_num_controllers = ATOMIC_INIT(0); - static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) { struct pci_dev *dev = ctrl->pcie->port; @@ -805,8 +803,8 @@ static void pcie_cleanup_slot(struct controller *ctrl) { struct slot *slot = ctrl->slot; cancel_delayed_work(&slot->work); - flush_scheduled_work(); flush_workqueue(pciehp_wq); + flush_workqueue(pciehp_ordered_wq); kfree(slot); } @@ -912,16 +910,6 @@ struct controller *pcie_init(struct pcie_device *dev) /* Disable sotfware notification */ pcie_disable_notification(ctrl); - /* - * If this is the first controller to be initialized, - * initialize the pciehp work queue - */ - if (atomic_add_return(1, &pciehp_num_controllers) == 1) { - pciehp_wq = create_singlethread_workqueue("pciehpd"); - if (!pciehp_wq) - goto abort_ctrl; - } - ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device); @@ -941,11 +929,5 @@ void pciehp_release_ctrl(struct controller *ctrl) { pcie_shutdown_notification(ctrl); pcie_cleanup_slot(ctrl); - /* - * If this is the last controller to be released, destroy the - * pciehp work queue - */ - if (atomic_dec_and_test(&pciehp_num_controllers)) - destroy_workqueue(pciehp_wq); kfree(ctrl); } diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index d2627e1c3ac..e0c90e643b5 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -35,6 +35,7 @@ #include <linux/delay.h> #include <linux/sched.h> /* signal_pending(), struct timer_list */ #include <linux/mutex.h> +#include <linux/workqueue.h> #if !defined(MODULE) #define MY_NAME "shpchp" @@ -46,6 +47,7 @@ extern int shpchp_poll_mode; extern int shpchp_poll_time; extern int shpchp_debug; extern struct workqueue_struct *shpchp_wq; +extern struct workqueue_struct *shpchp_ordered_wq; #define dbg(format, arg...) \ do { \ diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index a7bd5048396..aca972bbfb4 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -33,7 +33,6 @@ #include <linux/types.h> #include <linux/slab.h> #include <linux/pci.h> -#include <linux/workqueue.h> #include "shpchp.h" /* Global variables */ @@ -41,6 +40,7 @@ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; struct workqueue_struct *shpchp_wq; +struct workqueue_struct *shpchp_ordered_wq; #define DRIVER_VERSION "0.4" #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) slot = list_entry(tmp, struct slot, slot_list); list_del(&slot->slot_list); cancel_delayed_work(&slot->work); - flush_scheduled_work(); flush_workqueue(shpchp_wq); + flush_workqueue(shpchp_ordered_wq); pci_hp_deregister(slot->hotplug_slot); } } @@ -360,9 +360,23 @@ static int __init shpcd_init(void) { int retval = 0; + shpchp_wq = alloc_ordered_workqueue("shpchp", 0); + if (!shpchp_wq) + return -ENOMEM; + + shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0); + if (!shpchp_ordered_wq) { + destroy_workqueue(shpchp_wq); + return -ENOMEM; + } + retval = pci_register_driver(&shpc_driver); dbg("%s: pci_register_driver = %d\n", __func__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + if (retval) { + destroy_workqueue(shpchp_ordered_wq); + destroy_workqueue(shpchp_wq); + } return retval; } @@ -370,6 +384,8 @@ static void __exit shpcd_cleanup(void) { dbg("unload_shpchpd()\n"); pci_unregister_driver(&shpc_driver); + destroy_workqueue(shpchp_ordered_wq); + destroy_workqueue(shpchp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 3387fbfb0c5..b00b09bdd38 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -32,7 +32,6 @@ #include <linux/types.h> #include <linux/slab.h> #include <linux/pci.h> -#include <linux/workqueue.h> #include "../pci.h" #include "shpchp.h" @@ -52,7 +51,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->p_slot = p_slot; INIT_WORK(&info->work, interrupt_event_handler); - schedule_work(&info->work); + queue_work(shpchp_wq, &info->work); return 0; } @@ -457,7 +456,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work) kfree(info); goto out; } - queue_work(shpchp_wq, &info->work); + queue_work(shpchp_ordered_wq, &info->work); out: mutex_unlock(&p_slot->lock); } @@ -505,7 +504,7 @@ static void handle_button_press_event(struct slot *p_slot) p_slot->hpc_ops->green_led_blink(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); - schedule_delayed_work(&p_slot->work, 5*HZ); + queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); break; case BLINKINGOFF_STATE: case BLINKINGON_STATE: diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index d3985e7deab..36547f0ce30 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -179,8 +179,6 @@ #define SLOT_EVENT_LATCH 0x2 #define SLOT_SERR_INT_MASK 0x3 -static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); - static irqreturn_t shpc_isr(int irq, void *dev_id); static void start_int_poll_timer(struct controller *ctrl, int sec); static int hpc_check_cmd_status(struct controller *ctrl); @@ -614,13 +612,6 @@ static void hpc_release_ctlr(struct controller *ctrl) iounmap(ctrl->creg); release_mem_region(ctrl->mmio_base, ctrl->mmio_size); - - /* - * If this is the last controller to be released, destroy the - * shpchpd work queue - */ - if (atomic_dec_and_test(&shpchp_num_controllers)) - destroy_workqueue(shpchp_wq); } static int hpc_power_on_slot(struct slot * slot) @@ -1077,9 +1068,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, MY_NAME, (void *)ctrl); - ctrl_dbg(ctrl, "request_irq %d for hpc%d (returns %d)\n", - ctrl->pci_dev->irq, - atomic_read(&shpchp_num_controllers), rc); + ctrl_dbg(ctrl, "request_irq %d (returns %d)\n", + ctrl->pci_dev->irq, rc); if (rc) { ctrl_err(ctrl, "Can't get irq %d for the hotplug " "controller\n", ctrl->pci_dev->irq); @@ -1092,18 +1082,6 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) shpc_get_cur_bus_speed(ctrl); /* - * If this is the first controller to be initialized, - * initialize the shpchpd work queue - */ - if (atomic_add_return(1, &shpchp_num_controllers) == 1) { - shpchp_wq = create_singlethread_workqueue("shpchpd"); - if (!shpchp_wq) { - rc = -ENOMEM; - goto abort_iounmap; - } - } - - /* * Unmask all event interrupts of all slots */ for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { |