From 6370a6ad3b53df90b4700977f7718118a2cd524a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 11 Oct 2010 15:12:27 +0200 Subject: workqueue: add and use WQ_MEM_RECLAIM flag Add WQ_MEM_RECLAIM flag which currently maps to WQ_RESCUER, mark WQ_RESCUER as internal and replace all external WQ_RESCUER usages to WQ_MEM_RECLAIM. This makes the API users express the intent of the workqueue instead of indicating the internal mechanism used to guarantee forward progress. This is also to make it cleaner to add more semantics to WQ_MEM_RECLAIM. For example, if deemed necessary, memory reclaim workqueues can be made highpri. This patch doesn't introduce any functional change. Signed-off-by: Tejun Heo Cc: Jeff Garzik Cc: Dave Chinner Cc: Steven Whitehouse --- drivers/ata/libata-sff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index e30c537cce3..f5296bb19ec 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -3335,7 +3335,7 @@ void ata_sff_port_init(struct ata_port *ap) int __init ata_sff_init(void) { - ata_sff_wq = alloc_workqueue("ata_sff", WQ_RESCUER, WQ_MAX_ACTIVE); + ata_sff_wq = alloc_workqueue("ata_sff", WQ_MEM_RECLAIM, WQ_MAX_ACTIVE); if (!ata_sff_wq) return -ENOMEM; -- cgit v1.2.3 From 7bf4a5ddc9fbff52855cad8d4d74bf5344fe8093 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 17 Oct 2010 11:25:03 +0200 Subject: isdn/eicon: don't call flush_scheduled_work() from diva_os_remove_soft_isr() diva doesn't use workqueue and there is no reason to flush the system workqueue from diva_os_remove_soft_isr(). Remove it. This is to prepare for the deprecation and removal of flush_scheduled_work(). Signed-off-by: Tejun Heo Acked-by: Armin Schindler --- drivers/isdn/hardware/eicon/divasmain.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c index ed9c5550679..f332b60eff6 100644 --- a/drivers/isdn/hardware/eicon/divasmain.c +++ b/drivers/isdn/hardware/eicon/divasmain.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -546,7 +545,6 @@ void diva_os_remove_soft_isr(diva_os_soft_isr_t * psoft_isr) void *mem; tasklet_kill(&pdpc->divas_task); - flush_scheduled_work(); mem = psoft_isr->object; psoft_isr->object = NULL; diva_os_free(0, mem); -- cgit v1.2.3 From a827ea307b147aeb050803433b3f6842582c6ced Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 18 Oct 2010 08:31:02 +0200 Subject: pciehp: update workqueue usage * Rename pciehp_wq to pciehp_ordered_wq and add non-ordered pciehp_wq which is used instead of the system workqueue. This is to remove the use of flush_scheduled_work() which is deprecated and scheduled for removal. * With cmwq in place, there's no point in creating workqueues lazily. Create both pciehp_wq and pciehp_ordered_wq upfront. * Include workqueue.h from pciehp.h. Signed-off-by: Tejun Heo Acked-by: Jesse Barnes --- drivers/pci/hotplug/pciehp.h | 2 ++ drivers/pci/hotplug/pciehp_core.c | 18 +++++++++++++++++- drivers/pci/hotplug/pciehp_ctrl.c | 9 ++++----- drivers/pci/hotplug/pciehp_hpc.c | 20 +------------------- 4 files changed, 24 insertions(+), 25 deletions(-) (limited to 'drivers') 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 /* signal_pending() */ #include #include +#include #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 , Greg Kroah-Hartman , Dely Sy " @@ -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 #include #include -#include #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); } -- cgit v1.2.3 From e24dcbef93dbbf529fbedfc6ce8ab22d2cef35f0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 18 Oct 2010 08:33:02 +0200 Subject: shpchp: update workqueue usage * Rename shpchp_wq to shpchp_ordered_wq and add non-ordered shpchp_wq which is used instead of the system workqueue. This is to remove the use of flush_scheduled_work() which is deprecated and scheduled for removal. * With cmwq in place, there's no point in creating workqueues lazily. Create both shpchp_wq and shpchp_ordered_wq upfront. * Include workqueue.h from shpchp.h. Signed-off-by: Tejun Heo Acked-by: Jesse Barnes --- drivers/pci/hotplug/shpchp.h | 2 ++ drivers/pci/hotplug/shpchp_core.c | 20 ++++++++++++++++++-- drivers/pci/hotplug/shpchp_ctrl.c | 7 +++---- drivers/pci/hotplug/shpchp_hpc.c | 26 ++------------------------ 4 files changed, 25 insertions(+), 30 deletions(-) (limited to 'drivers') 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 #include /* signal_pending(), struct timer_list */ #include +#include #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 #include #include -#include #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 , Greg Kroah-Hartman , Dely Sy " @@ -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 #include #include -#include #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); @@ -1091,18 +1081,6 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) shpc_get_max_bus_speed(ctrl); 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 */ -- cgit v1.2.3