diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 80dbda84f1c3..fc7608a89d93 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -512,11 +512,8 @@ int mce_available(struct cpuinfo_x86 *c) static void mce_schedule_work(void) { - if (!mce_ring_empty()) { - struct work_struct *work = &__get_cpu_var(mce_work); - if (!work_pending(work)) - schedule_work(work); - } + if (!mce_ring_empty()) + schedule_work(&__get_cpu_var(mce_work)); } DEFINE_PER_CPU(struct irq_work, mce_irq_work); @@ -1351,12 +1348,7 @@ int mce_notify_irq(void) /* wake processes polling /dev/mcelog */ wake_up_interruptible(&mce_chrdev_wait); - /* - * There is no risk of missing notifications because - * work_pending is always cleared before the function is - * executed. - */ - if (mce_helper[0] && !work_pending(&mce_trigger_work)) + if (mce_helper[0]) schedule_work(&mce_trigger_work); if (__ratelimit(&ratelimit)) diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index d84888f03d92..600ac7226e5c 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -339,8 +339,7 @@ static void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s) */ static void peak_pciec_start_led_work(struct peak_pciec_card *card) { - if (!delayed_work_pending(&card->led_work)) - schedule_delayed_work(&card->led_work, HZ); + schedule_delayed_work(&card->led_work, HZ); } /* diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index 1d76ae855f07..530581ca0191 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c @@ -156,7 +156,7 @@ void i2400m_wake_tx_work(struct work_struct *ws) struct i2400m *i2400m = container_of(ws, struct i2400m, wake_tx_ws); struct net_device *net_dev = i2400m->wimax_dev.net_dev; struct device *dev = i2400m_dev(i2400m); - struct sk_buff *skb = i2400m->wake_tx_skb; + struct sk_buff *skb; unsigned long flags; spin_lock_irqsave(&i2400m->tx_lock, flags); @@ -236,23 +236,26 @@ void i2400m_tx_prep_header(struct sk_buff *skb) void i2400m_net_wake_stop(struct i2400m *i2400m) { struct device *dev = i2400m_dev(i2400m); + struct sk_buff *wake_tx_skb; + unsigned long flags; d_fnstart(3, dev, "(i2400m %p)\n", i2400m); - /* See i2400m_hard_start_xmit(), references are taken there - * and here we release them if the work was still - * pending. Note we can't differentiate work not pending vs - * never scheduled, so the NULL check does that. */ - if (cancel_work_sync(&i2400m->wake_tx_ws) == 0 - && i2400m->wake_tx_skb != NULL) { - unsigned long flags; - struct sk_buff *wake_tx_skb; - spin_lock_irqsave(&i2400m->tx_lock, flags); - wake_tx_skb = i2400m->wake_tx_skb; /* compat help */ - i2400m->wake_tx_skb = NULL; /* compat help */ - spin_unlock_irqrestore(&i2400m->tx_lock, flags); + /* + * See i2400m_hard_start_xmit(), references are taken there and + * here we release them if the packet was still pending. + */ + cancel_work_sync(&i2400m->wake_tx_ws); + + spin_lock_irqsave(&i2400m->tx_lock, flags); + wake_tx_skb = i2400m->wake_tx_skb; + i2400m->wake_tx_skb = NULL; + spin_unlock_irqrestore(&i2400m->tx_lock, flags); + + if (wake_tx_skb) { i2400m_put(i2400m); kfree_skb(wake_tx_skb); } + d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); } @@ -288,7 +291,7 @@ int i2400m_net_wake_tx(struct i2400m *i2400m, struct net_device *net_dev, * and if pending, release those resources. */ result = 0; spin_lock_irqsave(&i2400m->tx_lock, flags); - if (!work_pending(&i2400m->wake_tx_ws)) { + if (!i2400m->wake_tx_skb) { netif_stop_queue(net_dev); i2400m_get(i2400m); i2400m->wake_tx_skb = skb_get(skb); /* transfer ref count */ diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index d92b21a8e597..b3ab7b7becae 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -2181,9 +2181,10 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) mod_delayed_work(system_wq, &priv->rf_kill, round_jiffies_relative(HZ)); } -static void send_scan_event(void *data) +static void ipw2100_scan_event(struct work_struct *work) { - struct ipw2100_priv *priv = data; + struct ipw2100_priv *priv = container_of(work, struct ipw2100_priv, + scan_event.work); union iwreq_data wrqu; wrqu.data.length = 0; @@ -2191,18 +2192,6 @@ static void send_scan_event(void *data) wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); } -static void ipw2100_scan_event_later(struct work_struct *work) -{ - send_scan_event(container_of(work, struct ipw2100_priv, - scan_event_later.work)); -} - -static void ipw2100_scan_event_now(struct work_struct *work) -{ - send_scan_event(container_of(work, struct ipw2100_priv, - scan_event_now)); -} - static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) { IPW_DEBUG_SCAN("scan complete\n"); @@ -2212,13 +2201,11 @@ static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) /* Only userspace-requested scan completion events go out immediately */ if (!priv->user_requested_scan) { - if (!delayed_work_pending(&priv->scan_event_later)) - schedule_delayed_work(&priv->scan_event_later, - round_jiffies_relative(msecs_to_jiffies(4000))); + schedule_delayed_work(&priv->scan_event, + round_jiffies_relative(msecs_to_jiffies(4000))); } else { priv->user_requested_scan = 0; - cancel_delayed_work(&priv->scan_event_later); - schedule_work(&priv->scan_event_now); + mod_delayed_work(system_wq, &priv->scan_event, 0); } } @@ -4459,8 +4446,7 @@ static void ipw2100_kill_works(struct ipw2100_priv *priv) cancel_delayed_work_sync(&priv->wx_event_work); cancel_delayed_work_sync(&priv->hang_check); cancel_delayed_work_sync(&priv->rf_kill); - cancel_work_sync(&priv->scan_event_now); - cancel_delayed_work_sync(&priv->scan_event_later); + cancel_delayed_work_sync(&priv->scan_event); } static int ipw2100_tx_allocate(struct ipw2100_priv *priv) @@ -6195,8 +6181,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); - INIT_WORK(&priv->scan_event_now, ipw2100_scan_event_now); - INIT_DELAYED_WORK(&priv->scan_event_later, ipw2100_scan_event_later); + INIT_DELAYED_WORK(&priv->scan_event, ipw2100_scan_event); tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) ipw2100_irq_tasklet, (unsigned long)priv); diff --git a/drivers/net/wireless/ipw2x00/ipw2100.h b/drivers/net/wireless/ipw2x00/ipw2100.h index 5fe17cbab1f3..c6d78790cb0d 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.h +++ b/drivers/net/wireless/ipw2x00/ipw2100.h @@ -577,8 +577,7 @@ struct ipw2100_priv { struct delayed_work wx_event_work; struct delayed_work hang_check; struct delayed_work rf_kill; - struct work_struct scan_event_now; - struct delayed_work scan_event_later; + struct delayed_work scan_event; int user_requested_scan; diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 844f201b7b70..2c2d6db0536c 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -4480,18 +4480,11 @@ static void handle_scan_event(struct ipw_priv *priv) { /* Only userspace-requested scan completion events go out immediately */ if (!priv->user_requested_scan) { - if (!delayed_work_pending(&priv->scan_event)) - schedule_delayed_work(&priv->scan_event, - round_jiffies_relative(msecs_to_jiffies(4000))); + schedule_delayed_work(&priv->scan_event, + round_jiffies_relative(msecs_to_jiffies(4000))); } else { - union iwreq_data wrqu; - priv->user_requested_scan = 0; - cancel_delayed_work(&priv->scan_event); - - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); + mod_delayed_work(system_wq, &priv->scan_event, 0); } } diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 5a1c1d0e5599..f2874c3392b4 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -1752,6 +1752,8 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) static struct mmc_host *reset_host; static void sdio_card_reset_worker(struct work_struct *work) { + struct mmc_host *target = reset_host; + /* The actual reset operation must be run outside of driver thread. * This is because mmc_remove_host() will cause the device to be * instantly destroyed, and the driver then needs to end its thread, @@ -1761,10 +1763,10 @@ static void sdio_card_reset_worker(struct work_struct *work) */ pr_err("Resetting card...\n"); - mmc_remove_host(reset_host); + mmc_remove_host(target); /* 20ms delay is based on experiment with sdhci controller */ mdelay(20); - mmc_add_host(reset_host); + mmc_add_host(target); } static DECLARE_WORK(card_reset_work, sdio_card_reset_worker); @@ -1773,9 +1775,6 @@ static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter) { struct sdio_mmc_card *card = adapter->card; - if (work_pending(&card_reset_work)) - return; - reset_host = card->func->card->host; schedule_work(&card_reset_work); } diff --git a/drivers/net/wireless/ti/wl1251/ps.c b/drivers/net/wireless/ti/wl1251/ps.c index db719f7d2692..b9e27b98bbc9 100644 --- a/drivers/net/wireless/ti/wl1251/ps.c +++ b/drivers/net/wireless/ti/wl1251/ps.c @@ -68,8 +68,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) unsigned long timeout, start; u32 elp_reg; - if (delayed_work_pending(&wl->elp_work)) - cancel_delayed_work(&wl->elp_work); + cancel_delayed_work(&wl->elp_work); if (!wl->elp) return 0; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index f946ca7cb762..ebcb461bb2b0 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -4877,8 +4877,7 @@ static int __init light_init(struct ibm_init_struct *iibm) static void light_exit(void) { led_classdev_unregister(&tpacpi_led_thinklight.led_classdev); - if (work_pending(&tpacpi_led_thinklight.work)) - flush_workqueue(tpacpi_wq); + flush_workqueue(tpacpi_wq); } static int light_read(struct seq_file *m) diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index 7ce3197087bb..dd6277eb5a38 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c @@ -179,8 +179,7 @@ static void max3100_work(struct work_struct *w); static void max3100_dowork(struct max3100_port *s) { - if (!s->force_end_work && !work_pending(&s->work) && - !freezing(current) && !s->suspending) + if (!s->force_end_work && !freezing(current) && !s->suspending) queue_work(s->workqueue, &s->work); } diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index 4ef18e2e90cc..2d0d144add1b 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c @@ -1121,8 +1121,7 @@ static int exynos_dp_remove(struct platform_device *pdev) disable_irq(dp->irq); - if (work_pending(&dp->hotplug_work)) - flush_work(&dp->hotplug_work); + flush_work(&dp->hotplug_work); if (pdev->dev.of_node) { if (dp->phy_addr) @@ -1144,8 +1143,7 @@ static int exynos_dp_suspend(struct device *dev) struct exynos_dp_platdata *pdata = dev->platform_data; struct exynos_dp_device *dp = dev_get_drvdata(dev); - if (work_pending(&dp->hotplug_work)) - flush_work(&dp->hotplug_work); + flush_work(&dp->hotplug_work); if (dev->of_node) { if (dp->phy_addr) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index f423c3ef4a82..550294d58a02 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -471,7 +471,6 @@ static LIST_HEAD(unoptimizing_list); static void kprobe_optimizer(struct work_struct *work); static DECLARE_DELAYED_WORK(optimizing_work, kprobe_optimizer); -static DECLARE_COMPLETION(optimizer_comp); #define OPTIMIZE_DELAY 5 /* @@ -552,8 +551,7 @@ static __kprobes void do_free_cleaned_kprobes(struct list_head *free_list) /* Start optimizer after OPTIMIZE_DELAY passed */ static __kprobes void kick_kprobe_optimizer(void) { - if (!delayed_work_pending(&optimizing_work)) - schedule_delayed_work(&optimizing_work, OPTIMIZE_DELAY); + schedule_delayed_work(&optimizing_work, OPTIMIZE_DELAY); } /* Kprobe jump optimizer */ @@ -592,16 +590,25 @@ static __kprobes void kprobe_optimizer(struct work_struct *work) /* Step 5: Kick optimizer again if needed */ if (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list)) kick_kprobe_optimizer(); - else - /* Wake up all waiters */ - complete_all(&optimizer_comp); } /* Wait for completing optimization and unoptimization */ static __kprobes void wait_for_kprobe_optimizer(void) { - if (delayed_work_pending(&optimizing_work)) - wait_for_completion(&optimizer_comp); + mutex_lock(&kprobe_mutex); + + while (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list)) { + mutex_unlock(&kprobe_mutex); + + /* this will also make optimizing_work execute immmediately */ + flush_delayed_work(&optimizing_work); + /* @optimizing_work might not have been queued yet, relax */ + cpu_relax(); + + mutex_lock(&kprobe_mutex); + } + + mutex_unlock(&kprobe_mutex); } /* Optimize kprobe if p is ready to be optimized */ diff --git a/net/rfkill/input.c b/net/rfkill/input.c index c9d931e7ffec..b85107b5ef62 100644 --- a/net/rfkill/input.c +++ b/net/rfkill/input.c @@ -148,11 +148,9 @@ static unsigned long rfkill_ratelimit(const unsigned long last) static void rfkill_schedule_ratelimited(void) { - if (delayed_work_pending(&rfkill_op_work)) - return; - schedule_delayed_work(&rfkill_op_work, - rfkill_ratelimit(rfkill_last_scheduled)); - rfkill_last_scheduled = jiffies; + if (schedule_delayed_work(&rfkill_op_work, + rfkill_ratelimit(rfkill_last_scheduled))) + rfkill_last_scheduled = jiffies; } static void rfkill_schedule_global_op(enum rfkill_sched_op op)