Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/tj/wq

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq:
  workqueue: remove in_workqueue_context()
  workqueue: Clarify that schedule_on_each_cpu is synchronous
  memory_hotplug: drop spurious calls to flush_scheduled_work()
  shpchp: update workqueue usage
  pciehp: update workqueue usage
  isdn/eicon: don't call flush_scheduled_work() from diva_os_remove_soft_isr()
  workqueue: add and use WQ_MEM_RECLAIM flag
  workqueue: fix HIGHPRI handling in keep_working()
  workqueue: add queue_work and activate_work trace points
  workqueue: prepare for more tracepoints
  workqueue: implement flush[_delayed]_work_sync()
  workqueue: factor out start_flush_work()
  workqueue: cleanup flush/cancel functions
  workqueue: implement alloc_ordered_workqueue()

Fix up trivial conflict in fs/gfs2/main.c as per Tejun
  • Loading branch information
torvalds committed Oct 23, 2010
2 parents 04cc697 + daaae6b commit 91b7450
Show file tree
Hide file tree
Showing 17 changed files with 363 additions and 218 deletions.
29 changes: 15 additions & 14 deletions Documentation/workqueue.txt
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,11 @@ resources, scheduled and executed.
suspend operations. Work items on the wq are drained and no
new work item starts execution until thawed.

WQ_RESCUER
WQ_MEM_RECLAIM

All wq which might be used in the memory reclaim paths _MUST_
have this flag set. This reserves one worker exclusively for
the execution of this wq under memory pressure.
have this flag set. The wq is guaranteed to have at least one
execution context regardless of memory pressure.

WQ_HIGHPRI

Expand Down Expand Up @@ -356,24 +356,25 @@ If q1 has WQ_CPU_INTENSIVE set,

6. Guidelines

* Do not forget to use WQ_RESCUER if a wq may process work items which
are used during memory reclaim. Each wq with WQ_RESCUER set has one
rescuer thread reserved for it. If there is dependency among
multiple work items used during memory reclaim, they should be
queued to separate wq each with WQ_RESCUER.
* Do not forget to use WQ_MEM_RECLAIM if a wq may process work items
which are used during memory reclaim. Each wq with WQ_MEM_RECLAIM
set has an execution context reserved for it. If there is
dependency among multiple work items used during memory reclaim,
they should be queued to separate wq each with WQ_MEM_RECLAIM.

* Unless strict ordering is required, there is no need to use ST wq.

* Unless there is a specific need, using 0 for @max_active is
recommended. In most use cases, concurrency level usually stays
well under the default limit.

* A wq serves as a domain for forward progress guarantee (WQ_RESCUER),
flush and work item attributes. Work items which are not involved
in memory reclaim and don't need to be flushed as a part of a group
of work items, and don't require any special attribute, can use one
of the system wq. There is no difference in execution
characteristics between using a dedicated wq and a system wq.
* A wq serves as a domain for forward progress guarantee
(WQ_MEM_RECLAIM, flush and work item attributes. Work items which
are not involved in memory reclaim and don't need to be flushed as a
part of a group of work items, and don't require any special
attribute, can use one of the system wq. There is no difference in
execution characteristics between using a dedicated wq and a system
wq.

* Unless work items are expected to consume a huge amount of CPU
cycles, using a bound wq is usually beneficial due to the increased
Expand Down
2 changes: 1 addition & 1 deletion drivers/ata/libata-sff.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 0 additions & 2 deletions drivers/isdn/hardware/eicon/divasmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/list.h>
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions drivers/pci/hotplug/pciehp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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 { \
Expand Down
18 changes: 17 additions & 1 deletion drivers/pci/hotplug/pciehp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>, Greg Kroah-Hartman <[email protected]>, Dely Sy <[email protected]>"
Expand Down Expand Up @@ -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");
}
Expand Down
9 changes: 4 additions & 5 deletions drivers/pci/hotplug/pciehp_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down
20 changes: 1 addition & 19 deletions drivers/pci/hotplug/pciehp_hpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
2 changes: 2 additions & 0 deletions drivers/pci/hotplug/shpchp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 { \
Expand Down
20 changes: 18 additions & 2 deletions drivers/pci/hotplug/shpchp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/workqueue.h>
#include "shpchp.h"

/* Global variables */
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 <[email protected]>, Greg Kroah-Hartman <[email protected]>, Dely Sy <[email protected]>"
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -360,16 +360,32 @@ 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;
}

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");
}

Expand Down
7 changes: 3 additions & 4 deletions drivers/pci/hotplug/shpchp_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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:
Expand Down
26 changes: 2 additions & 24 deletions drivers/pci/hotplug/shpchp_hpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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
*/
Expand Down
Loading

0 comments on commit 91b7450

Please sign in to comment.