From afe2c511fb2d75f1515081ff1be15bd79cfe722d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 Dec 2010 16:21:17 +0100 Subject: workqueue: convert cancel_rearming_delayed_work[queue]() users to cancel_delayed_work_sync() cancel_rearming_delayed_work[queue]() has been superceded by cancel_delayed_work_sync() quite some time ago. Convert all the in-kernel users. The conversions are completely equivalent and trivial. Signed-off-by: Tejun Heo Acked-by: "David S. Miller" Acked-by: Greg Kroah-Hartman Acked-by: Evgeniy Polyakov Cc: Jeff Garzik Cc: Benjamin Herrenschmidt Cc: Mauro Carvalho Chehab Cc: netdev@vger.kernel.org Cc: Anton Vorontsov Cc: David Woodhouse Cc: "J. Bruce Fields" Cc: Neil Brown Cc: Alex Elder Cc: xfs-masters@oss.sgi.com Cc: Christoph Lameter Cc: Pekka Enberg Cc: Andrew Morton Cc: netfilter-devel@vger.kernel.org Cc: Trond Myklebust Cc: linux-nfs@vger.kernel.org --- drivers/ata/libata-core.c | 2 +- drivers/ata/libata-sff.c | 2 +- drivers/macintosh/rack-meter.c | 4 ++-- drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 2 +- drivers/media/video/em28xx/em28xx-input.c | 2 +- drivers/net/chelsio/my3126.c | 2 +- drivers/net/ibm_newemac/core.c | 4 ++-- drivers/net/wireless/zd1211rw/zd_mac.c | 3 +-- drivers/power/ds2760_battery.c | 6 ++---- drivers/power/intel_mid_battery.c | 6 ++---- drivers/staging/pohmelfs/inode.c | 4 ++-- drivers/usb/atm/cxacru.c | 2 +- drivers/video/fb_defio.c | 2 +- drivers/video/omap/lcd_mipid.c | 2 +- fs/nfsd/nfs4state.c | 2 +- fs/xfs/xfs_mru_cache.c | 2 +- mm/slab.c | 2 +- mm/vmstat.c | 2 +- net/atm/lec.c | 2 +- net/core/netpoll.c | 2 +- net/netfilter/ipvs/ip_vs_ctl.c | 2 +- net/sunrpc/xprtsock.c | 2 +- 22 files changed, 27 insertions(+), 32 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 7f77c67d267c..6669b44044fb 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6122,7 +6122,7 @@ static void ata_port_detach(struct ata_port *ap) /* it better be dead now */ WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED)); - cancel_rearming_delayed_work(&ap->hotplug_task); + cancel_delayed_work_sync(&ap->hotplug_task); skip_eh: if (ap->pmp_link) { diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index d05387d1e14b..8660a70f164a 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1320,7 +1320,7 @@ void ata_sff_flush_pio_task(struct ata_port *ap) { DPRINTK("ENTER\n"); - cancel_rearming_delayed_work(&ap->sff_pio_task); + cancel_delayed_work_sync(&ap->sff_pio_task); ap->hsm_task_state = HSM_ST_IDLE; if (ata_msg_ctl(ap)) diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c index 53cce3a5da23..39f660b2a60d 100644 --- a/drivers/macintosh/rack-meter.c +++ b/drivers/macintosh/rack-meter.c @@ -285,8 +285,8 @@ static void __devinit rackmeter_init_cpu_sniffer(struct rackmeter *rm) static void __devexit rackmeter_stop_cpu_sniffer(struct rackmeter *rm) { - cancel_rearming_delayed_work(&rm->cpu[0].sniffer); - cancel_rearming_delayed_work(&rm->cpu[1].sniffer); + cancel_delayed_work_sync(&rm->cpu[0].sniffer); + cancel_delayed_work_sync(&rm->cpu[1].sniffer); } static int __devinit rackmeter_setup(struct rackmeter *rm) diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index b579fed3ab3f..0831469af69f 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -298,7 +298,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) int dvb_usb_remote_exit(struct dvb_usb_device *d) { if (d->state & DVB_USB_STATE_REMOTE) { - cancel_rearming_delayed_work(&d->rc_query_work); + cancel_delayed_work_sync(&d->rc_query_work); flush_scheduled_work(); if (d->props.rc.mode == DVB_RC_LEGACY) input_unregister_device(d->rc_input_dev); diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 6759cd5570dd..99403c720e3a 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -557,7 +557,7 @@ void em28xx_deregister_snapshot_button(struct em28xx *dev) { if (dev->sbutton_input_dev != NULL) { em28xx_info("Deregistering snapshot button\n"); - cancel_rearming_delayed_work(&dev->sbutton_query_work); + cancel_delayed_work_sync(&dev->sbutton_query_work); input_unregister_device(dev->sbutton_input_dev); dev->sbutton_input_dev = NULL; } diff --git a/drivers/net/chelsio/my3126.c b/drivers/net/chelsio/my3126.c index 4c6028512d10..a683fd3bb624 100644 --- a/drivers/net/chelsio/my3126.c +++ b/drivers/net/chelsio/my3126.c @@ -22,7 +22,7 @@ static int my3126_interrupt_enable(struct cphy *cphy) static int my3126_interrupt_disable(struct cphy *cphy) { - cancel_rearming_delayed_work(&cphy->phy_update); + cancel_delayed_work_sync(&cphy->phy_update); return 0; } diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 06bb9b799458..e209efaa01b9 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -1279,7 +1279,7 @@ static void emac_force_link_update(struct emac_instance *dev) netif_carrier_off(dev->ndev); smp_rmb(); if (dev->link_polling) { - cancel_rearming_delayed_work(&dev->link_work); + cancel_delayed_work_sync(&dev->link_work); if (dev->link_polling) schedule_delayed_work(&dev->link_work, PHY_POLL_LINK_OFF); } @@ -1294,7 +1294,7 @@ static int emac_close(struct net_device *ndev) if (dev->phy.address >= 0) { dev->link_polling = 0; - cancel_rearming_delayed_work(&dev->link_work); + cancel_delayed_work_sync(&dev->link_work); } mutex_lock(&dev->link_lock); emac_netif_stop(dev); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 43307bd42a69..6107304cb94c 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -1207,7 +1207,6 @@ static void housekeeping_enable(struct zd_mac *mac) static void housekeeping_disable(struct zd_mac *mac) { dev_dbg_f(zd_mac_dev(mac), "\n"); - cancel_rearming_delayed_workqueue(zd_workqueue, - &mac->housekeeping.link_led_work); + cancel_delayed_work_sync(&mac->housekeeping.link_led_work); zd_chip_control_leds(&mac->chip, ZD_LED_OFF); } diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c index b3c01c16a164..e7f89785beef 100644 --- a/drivers/power/ds2760_battery.c +++ b/drivers/power/ds2760_battery.c @@ -580,10 +580,8 @@ static int ds2760_battery_remove(struct platform_device *pdev) { struct ds2760_device_info *di = platform_get_drvdata(pdev); - cancel_rearming_delayed_workqueue(di->monitor_wqueue, - &di->monitor_work); - cancel_rearming_delayed_workqueue(di->monitor_wqueue, - &di->set_charged_work); + cancel_delayed_work_sync(&di->monitor_work); + cancel_delayed_work_sync(&di->set_charged_work); destroy_workqueue(di->monitor_wqueue); power_supply_unregister(&di->bat); kfree(di); diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c index 2a10cd361181..36cf402c0677 100644 --- a/drivers/power/intel_mid_battery.c +++ b/drivers/power/intel_mid_battery.c @@ -730,8 +730,7 @@ static __devinit int probe(int irq, struct device *dev) power_reg_failed_1: power_supply_unregister(&pbi->batt); power_reg_failed: - cancel_rearming_delayed_workqueue(pbi->monitor_wqueue, - &pbi->monitor_battery); + cancel_delayed_work_sync(&pbi->monitor_battery); requestirq_failed: destroy_workqueue(pbi->monitor_wqueue); wqueue_failed: @@ -760,8 +759,7 @@ static int __devexit platform_pmic_battery_remove(struct platform_device *pdev) struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev); free_irq(pbi->irq, pbi); - cancel_rearming_delayed_workqueue(pbi->monitor_wqueue, - &pbi->monitor_battery); + cancel_delayed_work_sync(&pbi->monitor_battery); destroy_workqueue(pbi->monitor_wqueue); power_supply_unregister(&pbi->usb); diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c index 61685ccceda8..d4a1f204b9d5 100644 --- a/drivers/staging/pohmelfs/inode.c +++ b/drivers/staging/pohmelfs/inode.c @@ -1318,8 +1318,8 @@ static void pohmelfs_put_super(struct super_block *sb) } psb->trans_scan_timeout = psb->drop_scan_timeout = 0; - cancel_rearming_delayed_work(&psb->dwork); - cancel_rearming_delayed_work(&psb->drop_dwork); + cancel_delayed_work_sync(&psb->dwork); + cancel_delayed_work_sync(&psb->drop_dwork); flush_scheduled_work(); dprintk("%s: stopped workqueues.\n", __func__); diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index f383cb42b1d7..a845f8b8382f 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -1247,7 +1247,7 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance, mutex_unlock(&instance->poll_state_serialize); if (is_polling) - cancel_rearming_delayed_work(&instance->poll_work); + cancel_delayed_work_sync(&instance->poll_work); usb_kill_urb(instance->snd_urb); usb_kill_urb(instance->rcv_urb); diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 6b93ef93cb12..804000183c5e 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c @@ -75,7 +75,7 @@ int fb_deferred_io_fsync(struct file *file, int datasync) return 0; /* Kill off the delayed work */ - cancel_rearming_delayed_work(&info->deferred_work); + cancel_delayed_work_sync(&info->deferred_work); /* Run it immediately */ return schedule_delayed_work(&info->deferred_work, 0); diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c index 64dcc7439c99..90e3bdd1b7ab 100644 --- a/drivers/video/omap/lcd_mipid.c +++ b/drivers/video/omap/lcd_mipid.c @@ -396,7 +396,7 @@ static void mipid_esd_start_check(struct mipid_device *md) static void mipid_esd_stop_check(struct mipid_device *md) { if (md->esd_check != NULL) - cancel_rearming_delayed_workqueue(md->esd_wq, &md->esd_work); + cancel_delayed_work_sync(&md->esd_work); } static void mipid_esd_work(struct work_struct *work) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 116cab970e0f..fbd18c3074bb 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4336,7 +4336,7 @@ __nfs4_state_shutdown(void) void nfs4_state_shutdown(void) { - cancel_rearming_delayed_workqueue(laundry_wq, &laundromat_work); + cancel_delayed_work_sync(&laundromat_work); destroy_workqueue(laundry_wq); locks_end_grace(&nfsd4_manager); nfs4_lock_state(); diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c index 45ce15dc5b2b..edfa178bafb6 100644 --- a/fs/xfs/xfs_mru_cache.c +++ b/fs/xfs/xfs_mru_cache.c @@ -408,7 +408,7 @@ xfs_mru_cache_flush( spin_lock(&mru->lock); if (mru->queued) { spin_unlock(&mru->lock); - cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work); + cancel_delayed_work_sync(&mru->work); spin_lock(&mru->lock); } diff --git a/mm/slab.c b/mm/slab.c index b1e40dafbab3..dc983867682b 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1293,7 +1293,7 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb, * anything expensive but will only modify reap_work * and reschedule the timer. */ - cancel_rearming_delayed_work(&per_cpu(slab_reap_work, cpu)); + cancel_delayed_work_sync(&per_cpu(slab_reap_work, cpu)); /* Now the cache_reaper is guaranteed to be not running. */ per_cpu(slab_reap_work, cpu).work.func = NULL; break; diff --git a/mm/vmstat.c b/mm/vmstat.c index 42eac4d33216..d1f3cb63a8a9 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1033,7 +1033,7 @@ static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb, break; case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: - cancel_rearming_delayed_work(&per_cpu(vmstat_work, cpu)); + cancel_delayed_work_sync(&per_cpu(vmstat_work, cpu)); per_cpu(vmstat_work, cpu).work.func = NULL; break; case CPU_DOWN_FAILED: diff --git a/net/atm/lec.c b/net/atm/lec.c index 181d70c73d70..96a4a4bd2304 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -1608,7 +1608,7 @@ static void lec_arp_destroy(struct lec_priv *priv) struct lec_arp_table *entry; int i; - cancel_rearming_delayed_work(&priv->lec_arp_work); + cancel_delayed_work_sync(&priv->lec_arp_work); /* * Remove all entries diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 4e98ffac3af0..d2910947a3ac 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -925,7 +925,7 @@ void __netpoll_cleanup(struct netpoll *np) skb_queue_purge(&npinfo->arp_tx); skb_queue_purge(&npinfo->txq); - cancel_rearming_delayed_work(&npinfo->tx_work); + cancel_delayed_work_sync(&npinfo->tx_work); /* clean after last, unfinished work */ __skb_queue_purge(&npinfo->txq); diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 5f5daa30b0af..96334e0fd04e 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -3432,7 +3432,7 @@ void ip_vs_control_cleanup(void) { EnterFunction(2); ip_vs_trash_cleanup(); - cancel_rearming_delayed_work(&defense_work); + cancel_delayed_work_sync(&defense_work); cancel_work_sync(&defense_work.work); ip_vs_kill_estimator(&ip_vs_stats); unregister_sysctl_table(sysctl_header); diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index dfcab5ac65af..96549df836ee 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -770,7 +770,7 @@ static void xs_destroy(struct rpc_xprt *xprt) dprintk("RPC: xs_destroy xprt %p\n", xprt); - cancel_rearming_delayed_work(&transport->connect_worker); + cancel_delayed_work_sync(&transport->connect_worker); xs_close(xprt); xs_free_peer_addresses(xprt); -- cgit v1.2.3 From ed41390fa57a21d06e6e3a3c4bc238bab8957fbb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 Dec 2010 16:23:10 +0100 Subject: workqueue: deprecate cancel_rearming_delayed_work[queue]() There's no in-kernel user left for these two obsolete functions. Mark them deprecated and schedule for removal during 2.6.39 cycle. Signed-off-by: Tejun Heo Acked-by: David S. Miller --- Documentation/feature-removal-schedule.txt | 10 ++++++++++ include/linux/workqueue.h | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 6c2f55e05f13..4ff47deb86da 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -564,3 +564,13 @@ Why: This field is deprecated. I2C device drivers shouldn't change their Who: Jean Delvare ---------------------------- + +What: cancel_rearming_delayed_work[queue]() +When: 2.6.39 + +Why: The functions have been superceded by cancel_delayed_work_sync() + quite some time ago. The conversion is trivial and there is no + in-kernel user left. +Who: Tejun Heo + +---------------------------- diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 0c0771f06bfa..6b5193d70268 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -401,7 +401,7 @@ static inline bool __cancel_delayed_work(struct delayed_work *work) } /* Obsolete. use cancel_delayed_work_sync() */ -static inline +static inline __deprecated void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq, struct delayed_work *work) { @@ -409,7 +409,7 @@ void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq, } /* Obsolete. use cancel_delayed_work_sync() */ -static inline +static inline __deprecated void cancel_rearming_delayed_work(struct delayed_work *work) { cancel_delayed_work_sync(work); -- cgit v1.2.3 From c8efcc2589464ac70255bb83e10cad61c7c6d295 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 20 Dec 2010 19:32:04 +0100 Subject: workqueue: allow chained queueing during destruction Currently, destroy_workqueue() makes the workqueue deny all new queueing by setting WQ_DYING and flushes the workqueue once before proceeding with destruction; however, there are cases where work items queue more related work items. Currently, such users need to explicitly flush the workqueue multiple times depending on the possible depth of such chained queueing. This patch updates the queueing path such that a work item can queue further work items on the same workqueue even when WQ_DYING is set. The flush on destruction is automatically retried until the workqueue is empty. This guarantees that the workqueue is empty on destruction while allowing chained queueing. The flush retry logic whines if it takes too many retries to drain the workqueue. Signed-off-by: Tejun Heo Cc: James Bottomley --- kernel/workqueue.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index e785b0f2aea5..8ee6ec82f88a 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -932,6 +932,38 @@ static void insert_work(struct cpu_workqueue_struct *cwq, wake_up_worker(gcwq); } +/* + * Test whether @work is being queued from another work executing on the + * same workqueue. This is rather expensive and should only be used from + * cold paths. + */ +static bool is_chained_work(struct workqueue_struct *wq) +{ + unsigned long flags; + unsigned int cpu; + + for_each_gcwq_cpu(cpu) { + struct global_cwq *gcwq = get_gcwq(cpu); + struct worker *worker; + struct hlist_node *pos; + int i; + + spin_lock_irqsave(&gcwq->lock, flags); + for_each_busy_worker(worker, i, pos, gcwq) { + if (worker->task != current) + continue; + spin_unlock_irqrestore(&gcwq->lock, flags); + /* + * I'm @worker, no locking necessary. See if @work + * is headed to the same workqueue. + */ + return worker->current_cwq->wq == wq; + } + spin_unlock_irqrestore(&gcwq->lock, flags); + } + return false; +} + static void __queue_work(unsigned int cpu, struct workqueue_struct *wq, struct work_struct *work) { @@ -943,7 +975,9 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq, debug_work_activate(work); - if (WARN_ON_ONCE(wq->flags & WQ_DYING)) + /* if dying, only works from the same workqueue are allowed */ + if (unlikely(wq->flags & WQ_DYING) && + WARN_ON_ONCE(!is_chained_work(wq))) return; /* determine gcwq to use */ @@ -2936,11 +2970,35 @@ EXPORT_SYMBOL_GPL(__alloc_workqueue_key); */ void destroy_workqueue(struct workqueue_struct *wq) { + unsigned int flush_cnt = 0; unsigned int cpu; + /* + * Mark @wq dying and drain all pending works. Once WQ_DYING is + * set, only chain queueing is allowed. IOW, only currently + * pending or running work items on @wq can queue further work + * items on it. @wq is flushed repeatedly until it becomes empty. + * The number of flushing is detemined by the depth of chaining and + * should be relatively short. Whine if it takes too long. + */ wq->flags |= WQ_DYING; +reflush: flush_workqueue(wq); + for_each_cwq_cpu(cpu, wq) { + struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); + + if (!cwq->nr_active && list_empty(&cwq->delayed_works)) + continue; + + if (++flush_cnt == 10 || + (flush_cnt % 100 == 0 && flush_cnt <= 1000)) + printk(KERN_WARNING "workqueue %s: flush on " + "destruction isn't complete after %u tries\n", + wq->name, flush_cnt); + goto reflush; + } + /* * wq list is used to freeze wq, remove from list after * flushing is complete in case freeze races us. -- cgit v1.2.3 From 7fa5e85a0ab9ed5d2d8b77eec7976c88a5911bda Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:05 +0100 Subject: isdn/capi: unregister capictr notifier after init failure capidrv_init() could leave capictr notifier dangling after init failure. Fix it. Signed-off-by: Tejun Heo Acked-by: Jan Kiszka --- drivers/isdn/capi/capidrv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index e54e79d4e2c1..92607ed25e2e 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -2297,6 +2297,7 @@ static int __init capidrv_init(void) errcode = capi20_get_profile(0, &profile); if (errcode != CAPI_NOERROR) { + unregister_capictr_notifier(&capictr_nb); capi20_release(&global.ap); return -EIO; } -- cgit v1.2.3 From 158fa67753e1eb3edfa5a2d1868666d89d1cf09f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:06 +0100 Subject: isdn/capi: make kcapi use a separate workqueue flush_scheduled_work() is deprecated and will be removed. Because kcapi uses fire-and-forget type works, it's impossible to flush each work explicitly. Create and use a dedicated workqueue instead. Please note that with recent workqueue changes, each workqueue doesn't reserve a lot of resources and using it as a flush domain is fine. Signed-off-by: Tejun Heo Acked-by: Jan Kiszka --- drivers/isdn/capi/kcapi.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 3acf94cc5acd..2b33b2627fce 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -38,6 +38,7 @@ #include static int showcapimsgs = 0; +static struct workqueue_struct *kcapi_wq; MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer"); MODULE_AUTHOR("Carsten Paeth"); @@ -291,7 +292,7 @@ static int notify_push(unsigned int event_type, u32 controller) event->type = event_type; event->controller = controller; - schedule_work(&event->work); + queue_work(kcapi_wq, &event->work); return 0; } @@ -408,7 +409,7 @@ void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl, goto error; } skb_queue_tail(&ap->recv_queue, skb); - schedule_work(&ap->recv_work); + queue_work(kcapi_wq, &ap->recv_work); rcu_read_unlock(); return; @@ -743,7 +744,7 @@ u16 capi20_release(struct capi20_appl *ap) mutex_unlock(&capi_controller_lock); - flush_scheduled_work(); + flush_workqueue(kcapi_wq); skb_queue_purge(&ap->recv_queue); if (showcapimsgs & 1) { @@ -1285,21 +1286,30 @@ static int __init kcapi_init(void) { int err; + kcapi_wq = alloc_workqueue("kcapi", 0, 0); + if (!kcapi_wq) + return -ENOMEM; + register_capictr_notifier(&capictr_nb); err = cdebug_init(); - if (!err) - kcapi_proc_init(); - return err; + if (err) { + unregister_capictr_notifier(&capictr_nb); + destroy_workqueue(kcapi_wq); + return err; + } + + kcapi_proc_init(); + return 0; } static void __exit kcapi_exit(void) { kcapi_proc_exit(); - /* make sure all notifiers are finished */ - flush_scheduled_work(); + unregister_capictr_notifier(&capictr_nb); cdebug_exit(); + destroy_workqueue(kcapi_wq); } module_init(kcapi_init); -- cgit v1.2.3 From 7f6b0db9f63ba423d989e29f6318fe7e68760421 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:06 +0100 Subject: net/dsa: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush dst->link_poll_work on remove instead. Signed-off-by: Tejun Heo Acked-by: Lennert Buytenhek --- net/dsa/dsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 6112a12578b2..0c877a74e1f4 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -390,7 +390,7 @@ static int dsa_remove(struct platform_device *pdev) if (dst->link_poll_needed) del_timer_sync(&dst->link_poll_timer); - flush_scheduled_work(); + flush_work_sync(&dst->link_poll_work); for (i = 0; i < dst->pd->nr_chips; i++) { struct dsa_switch *ds = dst->ds[i]; -- cgit v1.2.3 From 9b00a8182987e8b7028d97c2bee3319ef383b57a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:06 +0100 Subject: ocfs2: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. * cancel_delayed_work() + flush_schedule_work() -> cancel_delayed_work_sync(). * flush qs->qs_work directly on exit instead. Signed-off-by: Tejun Heo Acked-by: Joel Becker Cc: Mark Fasheh --- fs/ocfs2/cluster/heartbeat.c | 3 +-- fs/ocfs2/cluster/quorum.c | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 52c7557f3e25..892e2de49903 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -307,8 +307,7 @@ static void o2hb_arm_write_timeout(struct o2hb_region *reg) static void o2hb_disarm_write_timeout(struct o2hb_region *reg) { - cancel_delayed_work(®->hr_write_timeout_work); - flush_scheduled_work(); + cancel_delayed_work_sync(®->hr_write_timeout_work); } static inline void o2hb_bio_wait_init(struct o2hb_bio_wait_ctxt *wc) diff --git a/fs/ocfs2/cluster/quorum.c b/fs/ocfs2/cluster/quorum.c index cf3e16696216..a87366750f23 100644 --- a/fs/ocfs2/cluster/quorum.c +++ b/fs/ocfs2/cluster/quorum.c @@ -325,5 +325,7 @@ void o2quo_init(void) void o2quo_exit(void) { - flush_scheduled_work(); + struct o2quo_state *qs = &o2quo_state; + + flush_work_sync(&qs->qs_work); } -- cgit v1.2.3 From 404437efc713b6c6fc8e2dc02978624bf4586e2d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:06 +0100 Subject: pcmcia/ipwireless: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush the used works instead. Signed-off-by: Tejun Heo Acked-by: Jiri Kosina Acked-by: David Sterba --- drivers/char/pcmcia/ipwireless/hardware.c | 2 +- drivers/char/pcmcia/ipwireless/network.c | 3 ++- drivers/char/pcmcia/ipwireless/tty.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index 99cffdab1056..0aeb5a38d296 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ b/drivers/char/pcmcia/ipwireless/hardware.c @@ -1729,7 +1729,7 @@ void ipwireless_hardware_free(struct ipw_hardware *hw) ipwireless_stop_interrupts(hw); - flush_scheduled_work(); + flush_work_sync(&hw->work_rx); for (i = 0; i < NL_NUM_OF_ADDRESSES; i++) if (hw->packet_assembler[i] != NULL) diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c index 9fe538347932..f7daeea598e4 100644 --- a/drivers/char/pcmcia/ipwireless/network.c +++ b/drivers/char/pcmcia/ipwireless/network.c @@ -430,7 +430,8 @@ void ipwireless_network_free(struct ipw_network *network) network->shutting_down = 1; ipwireless_ppp_close(network); - flush_scheduled_work(); + flush_work_sync(&network->work_go_online); + flush_work_sync(&network->work_go_offline); ipwireless_stop_interrupts(network->hardware); ipwireless_associate_network(network->hardware, NULL); diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 1a2c2c3b068f..f5eb28b6cb0f 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c @@ -577,7 +577,7 @@ void ipwireless_tty_free(struct ipw_tty *tty) mutex_unlock(&ttyj->ipw_tty_mutex); tty_hangup(ttyj->linux_tty); /* Wait till the tty_hangup has completed */ - flush_scheduled_work(); + flush_work_sync(&ttyj->linux_tty->hangup_work); /* FIXME: Exactly how is the tty object locked here against a parallel ioctl etc */ mutex_lock(&ttyj->ipw_tty_mutex); -- cgit v1.2.3 From f094cfc6c382cec7b2c77dd7798576684153acbb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:06 +0100 Subject: drm/ttm: use cancel_delayed_work_sync() in ttm_bo Make ttm_bo::ttm_bo_device_release call cancel_delayed_work_sync() instead of calling cancel_delayed_work() followed by flush_scheduled_work(). This is to prepare for the deprecation and removal of flush_scheduled_work(). Signed-off-by: Tejun Heo Cc:: Thomas Hellstrom Cc:: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 148a322d8f5d..934a96a78540 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1472,8 +1472,7 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev) list_del(&bdev->device_list); mutex_unlock(&glob->device_list_mutex); - if (!cancel_delayed_work(&bdev->wq)) - flush_scheduled_work(); + cancel_delayed_work_sync(&bdev->wq); while (ttm_bo_delayed_delete(bdev, true)) ; -- cgit v1.2.3 From 5d8e4bddc635dd61ab8b3bcb75c59934e9c1e19f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:06 +0100 Subject: ncpfs: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush the used works on stop instead. Signed-off-by: Tejun Heo Cc: Petr Vandrovec --- fs/ncpfs/inode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 8fb93b604e73..31532330d016 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -309,7 +309,12 @@ static void ncp_stop_tasks(struct ncp_server *server) { sk->sk_write_space = server->write_space; release_sock(sk); del_timer_sync(&server->timeout_tm); - flush_scheduled_work(); + + flush_work_sync(&server->rcv.tq); + if (sk->sk_socket->type == SOCK_STREAM) + flush_work_sync(&server->tx.tq); + else + flush_work_sync(&server->timeout_tq); } static int ncp_show_options(struct seq_file *seq, struct vfsmount *mnt) -- cgit v1.2.3 From fe413ec322e26179c788c678f24434b94cca34f0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:06 +0100 Subject: arm/sharpsl: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush toggle_charger and sharpsl_bat works on suspend instead. Signed-off-by: Tejun Heo Cc: Russell King --- arch/arm/mach-pxa/sharpsl_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 8fed027b12dc..e68d46d415f3 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -579,7 +579,8 @@ static int sharpsl_ac_check(void) static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state) { sharpsl_pm.flags |= SHARPSL_SUSPENDED; - flush_scheduled_work(); + flush_delayed_work_sync(&toggle_charger); + flush_delayed_work_sync(&sharpsl_bat); if (sharpsl_pm.charge_mode == CHRG_ON) sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; -- cgit v1.2.3 From 539253f6e13feedfa7bb6a3112c6707ebdf11e74 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:06 +0100 Subject: sh: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush psw->work on removal instead. Signed-off-by: Tejun Heo Cc: Paul Mundt Cc: linux-sh@vger.kernel.org --- arch/sh/drivers/push-switch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c index 7b42c247316c..afc24556572b 100644 --- a/arch/sh/drivers/push-switch.c +++ b/arch/sh/drivers/push-switch.c @@ -107,7 +107,7 @@ static int switch_drv_remove(struct platform_device *pdev) device_remove_file(&pdev->dev, &dev_attr_switch); platform_set_drvdata(pdev, NULL); - flush_scheduled_work(); + flush_work_sync(&psw->work); del_timer_sync(&psw->debounce); free_irq(irq, pdev); -- cgit v1.2.3 From 8aa0f413848708bca329c52358ae7a1a0e395b4e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:06 +0100 Subject: floppy: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush floppy_work instead. Signed-off-by: Tejun Heo Cc: Jens Axboe --- drivers/block/floppy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 3951020e494a..25e4dffa0aad 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4352,7 +4352,7 @@ static int __init floppy_init(void) out_unreg_platform_dev: platform_device_unregister(&floppy_device[drive]); out_flush_work: - flush_scheduled_work(); + flush_work_sync(&floppy_work); if (atomic_read(&usage_count)) floppy_release_irq_and_dma(); out_unreg_region: @@ -4422,7 +4422,7 @@ static int floppy_grab_irq_and_dma(void) * We might have scheduled a free_irq(), wait it to * drain first: */ - flush_scheduled_work(); + flush_work_sync(&floppy_work); if (fd_request_irq()) { DPRINT("Unable to grab IRQ%d for the floppy driver\n", -- cgit v1.2.3 From 0ead5c86ac4c9903da93c76716135bc29d9cd83b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:06 +0100 Subject: gdrom: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush work on removal instead. Signed-off-by: Tejun Heo Cc: Jens Axboe --- drivers/cdrom/gdrom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index de65915308fb..64a21461c408 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -837,7 +837,7 @@ probe_fail_no_mem: static int __devexit remove_gdrom(struct platform_device *devptr) { - flush_scheduled_work(); + flush_work_sync(&work); blk_cleanup_queue(gd.gdrom_rq); free_irq(HW_EVENT_GDROM_CMD, &gd); free_irq(HW_EVENT_GDROM_DMA, &gd); -- cgit v1.2.3 From 30d65030fd14fd3696d927c5e452bee84c589b09 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:06 +0100 Subject: xen: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush info->work instead. Signed-off-by: Tejun Heo Cc: Jeremy Fitzhardinge Cc: Konrad Rzeszutek Wilk --- drivers/block/xen-blkfront.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 255035cfc88a..c30c18ea48b8 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -538,7 +538,7 @@ static void xlvbd_release_gendisk(struct blkfront_info *info) spin_unlock_irqrestore(&blkif_io_lock, flags); /* Flush gnttab callback work. Must be done with no locks held. */ - flush_scheduled_work(); + flush_work_sync(&info->work); del_gendisk(info->gd); @@ -587,7 +587,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) spin_unlock_irq(&blkif_io_lock); /* Flush gnttab callback work. Must be done with no locks held. */ - flush_scheduled_work(); + flush_work_sync(&info->work); /* Free resources associated with old device channel. */ if (info->ring_ref != GRANT_INVALID_REF) { -- cgit v1.2.3 From 42565999d1e0b8a0c5b4a0d475c26cf3d567e85e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:07 +0100 Subject: hvsi: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly cancel hp->writer and flush hp->handshaker instead. Signed-off-by: Tejun Heo Cc: Benjamin Herrenschmidt Cc: Paul Mackerras --- drivers/char/hvsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index a2bc885ce60a..67a75a502c01 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -850,8 +850,8 @@ static void hvsi_flush_output(struct hvsi_struct *hp) wait_event_timeout(hp->emptyq, (hp->n_outbuf <= 0), HVSI_TIMEOUT); /* 'writer' could still be pending if it didn't see n_outbuf = 0 yet */ - cancel_delayed_work(&hp->writer); - flush_scheduled_work(); + cancel_delayed_work_sync(&hp->writer); + flush_work_sync(&hp->handshaker); /* * it's also possible that our timeout expired and hvsi_write_worker -- cgit v1.2.3 From 3514870f06a7907bc46361aebc3daf5ea4e97eeb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:07 +0100 Subject: sonypi: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush sonypi_device.input_work on removal instead. Signed-off-by: Tejun Heo Cc: Mattia Dongili --- drivers/char/sonypi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 73f66d03624d..79e36c878a4c 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1434,7 +1434,7 @@ static int __devexit sonypi_remove(struct platform_device *dev) sonypi_disable(); synchronize_irq(sonypi_device.irq); - flush_scheduled_work(); + flush_work_sync(&sonypi_device.input_work); if (useinput) { input_unregister_device(sonypi_device.input_key_dev); -- cgit v1.2.3 From 2e5c44c92046c41607794666ffc0d6945945acb0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:07 +0100 Subject: tpm: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush chip->work instead. Signed-off-by: Tejun Heo Cc: Debora Velarde Cc: Rajiv Andrade --- drivers/char/tpm/tpm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 7c4133582dba..0b3af3fe6766 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -986,7 +986,7 @@ int tpm_release(struct inode *inode, struct file *file) struct tpm_chip *chip = file->private_data; del_singleshot_timer_sync(&chip->user_read_timer); - flush_scheduled_work(); + flush_work_sync(&chip->work); file->private_data = NULL; atomic_set(&chip->data_pending, 0); kfree(chip->data_buffer); @@ -1038,7 +1038,7 @@ ssize_t tpm_read(struct file *file, char __user *buf, ssize_t ret_size; del_singleshot_timer_sync(&chip->user_read_timer); - flush_scheduled_work(); + flush_work_sync(&chip->work); ret_size = atomic_read(&chip->data_pending); atomic_set(&chip->data_pending, 0); if (ret_size > 0) { /* relay data */ -- cgit v1.2.3 From a6665944ef83b6a2db8fc5b323c9fca92375a643 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:07 +0100 Subject: vmwgfx: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush info->deferred_work on removal instead. Signed-off-by: Tejun Heo Cc: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 41d9a5b73c03..fe096a7cc0d7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -659,7 +659,7 @@ int vmw_fb_off(struct vmw_private *vmw_priv) par->dirty.active = false; spin_unlock_irqrestore(&par->dirty.lock, flags); - flush_scheduled_work(); + flush_delayed_work_sync(&info->deferred_work); par->bo_ptr = NULL; ttm_bo_kunmap(&par->map); -- cgit v1.2.3 From d9c612eb6e9ccb8192e6c4d609dbbf178020c672 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:07 +0100 Subject: macintosh/ams: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush ams_info.worker on detach instead. Signed-off-by: Tejun Heo --- drivers/macintosh/ams/ams-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/macintosh/ams/ams-core.c b/drivers/macintosh/ams/ams-core.c index 2ad62c339cd2..399beb1638d1 100644 --- a/drivers/macintosh/ams/ams-core.c +++ b/drivers/macintosh/ams/ams-core.c @@ -226,7 +226,7 @@ void ams_sensor_detach(void) * We do this after ams_info.exit(), because an interrupt might * have arrived before disabling them. */ - flush_scheduled_work(); + flush_work_sync(&ams_info.worker); /* Remove device */ of_device_unregister(ams_info.of_dev); -- cgit v1.2.3 From 0d26aa704e5bbca5a1ee9fdf0d02277ceb507eee Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:07 +0100 Subject: mISDN: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush ch->workq when freeing channel and cancel it on release. Signed-off-by: Tejun Heo Cc: Karsten Keil Cc: netdev@vger.kernel.org --- drivers/isdn/mISDN/hwchannel.c | 4 ++-- drivers/isdn/mISDN/l1oip_core.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c index 307bd6e8988b..199f374cf9da 100644 --- a/drivers/isdn/mISDN/hwchannel.c +++ b/drivers/isdn/mISDN/hwchannel.c @@ -110,7 +110,7 @@ mISDN_freedchannel(struct dchannel *ch) } skb_queue_purge(&ch->squeue); skb_queue_purge(&ch->rqueue); - flush_scheduled_work(); + flush_work_sync(&ch->workq); return 0; } EXPORT_SYMBOL(mISDN_freedchannel); @@ -143,7 +143,7 @@ mISDN_freebchannel(struct bchannel *ch) mISDN_clear_bchannel(ch); skb_queue_purge(&ch->rqueue); ch->rcount = 0; - flush_scheduled_work(); + flush_work_sync(&ch->workq); return 0; } EXPORT_SYMBOL(mISDN_freebchannel); diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 5b59796ed250..bd526f664a39 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -1269,6 +1269,8 @@ release_card(struct l1oip *hc) if (timer_pending(&hc->timeout_tl)) del_timer(&hc->timeout_tl); + cancel_work_sync(&hc->workq); + if (hc->socket_thread) l1oip_socket_close(hc); -- cgit v1.2.3 From 99ef21216b4f85c56392ed41500d2f07f58cc360 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 15:59:07 +0100 Subject: leds-wm8350: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. Directly flush led->work on removal instead. Signed-off-by: Tejun Heo Cc: Richard Purdie --- drivers/leds/leds-wm8350.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c index 5aab32ce4f4d..a04523273282 100644 --- a/drivers/leds/leds-wm8350.c +++ b/drivers/leds/leds-wm8350.c @@ -276,7 +276,7 @@ static int wm8350_led_remove(struct platform_device *pdev) struct wm8350_led *led = platform_get_drvdata(pdev); led_classdev_unregister(&led->cdev); - flush_scheduled_work(); + flush_work_sync(&led->work); wm8350_led_disable(led); regulator_put(led->dcdc); regulator_put(led->isink); -- cgit v1.2.3 From 0d9c76aedbac3ad8ac4e99a2b441bc3f91dd6679 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 16:00:17 +0100 Subject: dvb: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. * Flush the used works directly. * Replace the deprecated cancel_rearming_delayed_work() + flush_scheduled_work() -> cancel_delayed_work_sync(). * Make sure mantis->uart_work isn't running on exit. Signed-off-by: Tejun Heo Cc: Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org --- drivers/media/dvb/dvb-core/dvb_net.c | 3 ++- drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 1 - drivers/media/dvb/mantis/mantis_evm.c | 2 +- drivers/media/dvb/mantis/mantis_uart.c | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 4df42aaae7f7..51752a9ef7a4 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -1329,7 +1329,8 @@ static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num) return -EBUSY; dvb_net_stop(net); - flush_scheduled_work(); + flush_work_sync(&priv->set_multicast_list_wq); + flush_work_sync(&priv->restart_net_feed_wq); printk("dvb_net: removed network interface %s\n", net->name); unregister_netdev(net); dvbnet->state[num]=0; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 0831469af69f..d5f3d3c7463e 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -299,7 +299,6 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d) { if (d->state & DVB_USB_STATE_REMOTE) { cancel_delayed_work_sync(&d->rc_query_work); - flush_scheduled_work(); if (d->props.rc.mode == DVB_RC_LEGACY) input_unregister_device(d->rc_input_dev); else diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index a7b369a439d6..9f73c2cfc9ea 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -111,7 +111,7 @@ void mantis_evmgr_exit(struct mantis_ca *ca) struct mantis_pci *mantis = ca->ca_priv; dprintk(MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); - flush_scheduled_work(); + flush_work_sync(&ca->hif_evm_work); mantis_hif_exit(ca); mantis_pcmcia_exit(ca); } diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c index 7d2f2398fa8b..97b889e8a341 100644 --- a/drivers/media/dvb/mantis/mantis_uart.c +++ b/drivers/media/dvb/mantis/mantis_uart.c @@ -182,5 +182,6 @@ void mantis_uart_exit(struct mantis_pci *mantis) { /* disable interrupt */ mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL); + flush_work_sync(&mantis->uart_work); } EXPORT_SYMBOL_GPL(mantis_uart_exit); -- cgit v1.2.3 From afdb32f2e463a195c104555ac9a8cdd39a2b6561 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 16:00:17 +0100 Subject: mfd: update workqueue usages flush_scheduled_work() is deprecated and scheduled to be removed. * In menelaus, flush menelaus->work directly on probe failure. Also, make sure the work isn't running on removal. * In tps65010, cancel_delayed_work() + flush_scheduled_work() -> cancel_delayed_work_sync(). While at it, remove unnecessary (void) casts on return value, and use schedule_delayed_work() and to_delayed_work() instead of using delayed_work's internal work field. Signed-off-by: Tejun Heo Cc: Samuel Ortiz --- drivers/mfd/menelaus.c | 3 ++- drivers/mfd/tps65010.c | 13 ++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index 4ba85bbdb4c1..9cee8e7f0bcb 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c @@ -1259,7 +1259,7 @@ static int menelaus_probe(struct i2c_client *client, return 0; fail2: free_irq(client->irq, menelaus); - flush_scheduled_work(); + flush_work_sync(&menelaus->work); fail1: kfree(menelaus); return err; @@ -1270,6 +1270,7 @@ static int __exit menelaus_remove(struct i2c_client *client) struct menelaus_chip *menelaus = i2c_get_clientdata(client); free_irq(client->irq, menelaus); + flush_work_sync(&menelaus->work); kfree(menelaus); the_menelaus = NULL; return 0; diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index d0016b67d125..90187fe33e04 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c @@ -242,7 +242,7 @@ static int dbg_show(struct seq_file *s, void *_) seq_printf(s, "mask2 %s\n", buf); /* ignore ackint2 */ - (void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY); + schedule_delayed_work(&tps->work, POWER_POLL_DELAY); /* VMAIN voltage, enable lowpower, etc */ @@ -400,7 +400,7 @@ static void tps65010_interrupt(struct tps65010 *tps) && (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))) poll = 1; if (poll) - (void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY); + schedule_delayed_work(&tps->work, POWER_POLL_DELAY); /* also potentially gpio-in rise or fall */ } @@ -410,7 +410,7 @@ static void tps65010_work(struct work_struct *work) { struct tps65010 *tps; - tps = container_of(work, struct tps65010, work.work); + tps = container_of(to_delayed_work(work), struct tps65010, work); mutex_lock(&tps->lock); tps65010_interrupt(tps); @@ -448,7 +448,7 @@ static irqreturn_t tps65010_irq(int irq, void *_tps) disable_irq_nosync(irq); set_bit(FLAG_IRQ_ENABLE, &tps->flags); - (void) schedule_work(&tps->work.work); + schedule_delayed_work(&tps->work, 0); return IRQ_HANDLED; } @@ -527,8 +527,7 @@ static int __exit tps65010_remove(struct i2c_client *client) } if (client->irq > 0) free_irq(client->irq, tps); - cancel_delayed_work(&tps->work); - flush_scheduled_work(); + cancel_delayed_work_sync(&tps->work); debugfs_remove(tps->file); kfree(tps); the_tps = NULL; @@ -720,7 +719,7 @@ int tps65010_set_vbus_draw(unsigned mA) && test_and_set_bit( FLAG_VBUS_CHANGED, &the_tps->flags)) { /* gadget drivers call this in_irq() */ - (void) schedule_work(&the_tps->work.work); + schedule_delayed_work(&the_tps->work, 0); } local_irq_restore(flags); -- cgit v1.2.3 From 0d9ee5b2e9aac981fa063339daf04320eac610d1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 16:00:17 +0100 Subject: mmc: update workqueue usages Workqueue creation API has been updated and flush_scheduled_work() is deprecated and scheduled to be removed. * core/core.c: Use alloc_ordered_workqueue() instead of create_singlethread_workqueue(). This removes an unnecessary rescuer. * host/omap.c: Create, use and flush mmc_omap_wq instead of the system_wq. * Flush host->mmc_carddetect_work directly on removal instead of using flush_scheduled_work(). Signed-off-by: Tejun Heo Cc: Chris Ball Cc: linux-mmc@vger.kernel.org --- drivers/mmc/core/core.c | 2 +- drivers/mmc/host/omap.c | 24 ++++++++++++++++++------ drivers/mmc/host/omap_hsmmc.c | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 8f86d702e46e..55b545fb60b4 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1789,7 +1789,7 @@ static int __init mmc_init(void) { int ret; - workqueue = create_singlethread_workqueue("kmmcd"); + workqueue = alloc_ordered_workqueue("kmmcd", 0); if (!workqueue) return -ENOMEM; diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 0c7e37f496ef..379d2ffe4c87 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -173,6 +173,8 @@ struct mmc_omap_host { struct omap_mmc_platform_data *pdata; }; +static struct workqueue_struct *mmc_omap_wq; + static void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot) { unsigned long tick_ns; @@ -289,7 +291,7 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled) host->next_slot = new_slot; host->mmc = new_slot->mmc; spin_unlock_irqrestore(&host->slot_lock, flags); - schedule_work(&host->slot_release_work); + queue_work(mmc_omap_wq, &host->slot_release_work); return; } @@ -457,7 +459,7 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) } host->stop_data = data; - schedule_work(&host->send_stop_work); + queue_work(mmc_omap_wq, &host->send_stop_work); } static void @@ -637,7 +639,7 @@ mmc_omap_cmd_timer(unsigned long data) OMAP_MMC_WRITE(host, IE, 0); disable_irq(host->irq); host->abort = 1; - schedule_work(&host->cmd_abort_work); + queue_work(mmc_omap_wq, &host->cmd_abort_work); } spin_unlock_irqrestore(&host->slot_lock, flags); } @@ -826,7 +828,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) host->abort = 1; OMAP_MMC_WRITE(host, IE, 0); disable_irq_nosync(host->irq); - schedule_work(&host->cmd_abort_work); + queue_work(mmc_omap_wq, &host->cmd_abort_work); return IRQ_HANDLED; } @@ -1387,7 +1389,7 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot) tasklet_kill(&slot->cover_tasklet); del_timer_sync(&slot->cover_timer); - flush_scheduled_work(); + flush_workqueue(mmc_omap_wq); mmc_remove_host(mmc); mmc_free_host(mmc); @@ -1608,12 +1610,22 @@ static struct platform_driver mmc_omap_driver = { static int __init mmc_omap_init(void) { - return platform_driver_probe(&mmc_omap_driver, mmc_omap_probe); + int ret; + + mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0); + if (!mmc_omap_wq) + return -ENOMEM; + + ret = platform_driver_probe(&mmc_omap_driver, mmc_omap_probe); + if (ret) + destroy_workqueue(mmc_omap_wq); + return ret; } static void __exit mmc_omap_exit(void) { platform_driver_unregister(&mmc_omap_driver); + destroy_workqueue(mmc_omap_wq); } module_init(mmc_omap_init); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 82a1079bbdc7..9e136bbd2b61 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2290,7 +2290,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) free_irq(host->irq, host); if (mmc_slot(host).card_detect_irq) free_irq(mmc_slot(host).card_detect_irq, host); - flush_scheduled_work(); + flush_work_sync(&host->mmc_carddetect_work); mmc_host_disable(host->mmc); clk_disable(host->iclk); -- cgit v1.2.3 From 9db8995be5e1869b5effa117909bc285e06fc09b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 16:00:17 +0100 Subject: rtc: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. On removal, directly cancel the work, and flush the uie_task in rtc-dev.c::clear_uie(). Signed-off-by: Tejun Heo Cc: Alessandro Zummo Cc: rtc-linux@googlegroups.com --- drivers/rtc/rtc-dev.c | 2 +- drivers/rtc/rtc-ds1305.c | 2 +- drivers/rtc/rtc-ds1374.c | 2 +- drivers/rtc/rtc-ds3232.c | 2 +- drivers/rtc/rtc-rx8025.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 62227cd52410..0cc0984d155b 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -104,7 +104,7 @@ static int clear_uie(struct rtc_device *rtc) } if (rtc->uie_task_active) { spin_unlock_irq(&rtc->irq_lock); - flush_scheduled_work(); + flush_work_sync(&rtc->uie_task); spin_lock_irq(&rtc->irq_lock); } rtc->uie_irq_active = 0; diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 48da85e97ca4..077af1d7b9e4 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -813,7 +813,7 @@ static int __devexit ds1305_remove(struct spi_device *spi) if (spi->irq) { set_bit(FLAG_EXITING, &ds1305->flags); free_irq(spi->irq, ds1305); - flush_scheduled_work(); + cancel_work_sync(&ds1305->work); } rtc_device_unregister(ds1305->rtc); diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 1f0007fd4431..47fb6357c346 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -417,7 +417,7 @@ static int __devexit ds1374_remove(struct i2c_client *client) mutex_unlock(&ds1374->mutex); free_irq(client->irq, client); - flush_scheduled_work(); + cancel_work_sync(&ds1374->work); } rtc_device_unregister(ds1374->rtc); diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 57063552d3b7..23a9ee19764c 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -463,7 +463,7 @@ static int __devexit ds3232_remove(struct i2c_client *client) mutex_unlock(&ds3232->mutex); free_irq(client->irq, client); - flush_scheduled_work(); + cancel_work_sync(&ds3232->work); } rtc_device_unregister(ds3232->rtc); diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index 1146e3522d3c..af32a62e12a8 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -650,7 +650,7 @@ static int __devexit rx8025_remove(struct i2c_client *client) mutex_unlock(lock); free_irq(client->irq, client); - flush_scheduled_work(); + cancel_work_sync(&rx8025->work); } rx8025_sysfs_unregister(&client->dev); -- cgit v1.2.3 From 6dca467a76bb0ed71d65143b235e0ef80e44436f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 16:00:18 +0100 Subject: s390: don't use flush_scheduled_work() flush_scheduled_work() is deprecated and scheduled to be removed. * tape_3590: Create and use tape_3590_wq instead of the system_wq. * tape_block: Directly flush requeue_task on cleanup instead of using flush_scheduled_work(). Signed-off-by: Tejun Heo Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org --- drivers/s390/char/tape_3590.c | 18 +++++++++++++----- drivers/s390/char/tape_block.c | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index deff2c3361e4..fbe361fcd2c0 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -24,6 +24,8 @@ #include "tape_std.h" #include "tape_3590.h" +static struct workqueue_struct *tape_3590_wq; + /* * Pointer to debug area. */ @@ -613,7 +615,7 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op) p->device = tape_get_device(device); p->op = op; - schedule_work(&p->work); + queue_work(tape_3590_wq, &p->work); return 0; } @@ -1629,7 +1631,7 @@ fail_kmalloc: static void tape_3590_cleanup_device(struct tape_device *device) { - flush_scheduled_work(); + flush_workqueue(tape_3590_wq); tape_std_unassign(device); kfree(device->discdata); @@ -1733,11 +1735,17 @@ tape_3590_init(void) #endif DBF_EVENT(3, "3590 init\n"); + + tape_3590_wq = alloc_workqueue("tape_3590", 0, 0); + if (!tape_3590_wq) + return -ENOMEM; + /* Register driver for 3590 tapes. */ rc = ccw_driver_register(&tape_3590_driver); - if (rc) + if (rc) { + destroy_workqueue(tape_3590_wq); DBF_EVENT(3, "3590 init failed\n"); - else + } else DBF_EVENT(3, "3590 registered\n"); return rc; } @@ -1746,7 +1754,7 @@ static void tape_3590_exit(void) { ccw_driver_unregister(&tape_3590_driver); - + destroy_workqueue(tape_3590_wq); debug_unregister(TAPE_DBF_AREA); } diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index f0fa9ca5cb2c..55d2d0f4eabc 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -264,7 +264,7 @@ cleanup_queue: void tapeblock_cleanup_device(struct tape_device *device) { - flush_scheduled_work(); + flush_work_sync(&device->blk_data.requeue_task); tape_put_device(device); if (!device->blk_data.disk) { -- cgit v1.2.3 From ee4569a3a75e1a5ed53b0c4ff4d9fc456aa98ef1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 16:14:20 +0100 Subject: init: don't call flush_scheduled_work() from do_initcalls() The call to flush_scheduled_work() in do_initcalls() is there to make sure all works queued to system_wq by initcalls finish before the init sections are dropped. However, the call doesn't make much sense at this point - there already are multiple different workqueues and different subsystems are free to create and use their own. Ordering requirements are and should be expressed explicitly. Drop the call to prepare for the deprecation and removal of flush_scheduled_work(). Andrew suggested adding sanity check where the workqueue code checks whether any pending or running work has the work function in the init text section. However, checking this for running works requires the worker to keep track of the current function being executed, and checking only the pending works will miss most cases. As a violation will almost always be caught by the usual page fault mechanism, I don't think it would be worthwhile to make the workqueue code track extra state just for this. Signed-off-by: Tejun Heo Cc: Andrew Morton --- init/main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/init/main.c b/init/main.c index 8646401f7a0e..5421e8f16280 100644 --- a/init/main.c +++ b/init/main.c @@ -775,9 +775,6 @@ static void __init do_initcalls(void) for (fn = __early_initcall_end; fn < __initcall_end; fn++) do_one_initcall(*fn); - - /* Make sure there is no pending stuff from the initcall sequence */ - flush_scheduled_work(); } /* -- cgit v1.2.3 From 883624a08cb4144343e7362d9fff0e2c69613ebf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 16:14:20 +0100 Subject: ioc4: use static work_struct for ioc4_load_modules() There is no reason to dynamically allocate work_struct for ioc4_load_modules(). It makes the code more complex and makes it impossible to flush the work directly. Use static work ioc4_load_modules_work instead and flush it directly on exit. This removes the use of flush_scheduled_work() which is being deprecated. Signed-off-by: Tejun Heo Cc: Brent Casavant --- drivers/misc/ioc4.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 193206602d88..668d41e594a9 100644 --- a/drivers/misc/ioc4.c +++ b/drivers/misc/ioc4.c @@ -273,13 +273,11 @@ ioc4_variant(struct ioc4_driver_data *idd) static void __devinit ioc4_load_modules(struct work_struct *work) { - /* arg just has to be freed */ - request_module("sgiioc4"); - - kfree(work); } +static DECLARE_WORK(ioc4_load_modules_work, ioc4_load_modules); + /* Adds a new instance of an IOC4 card */ static int __devinit ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) @@ -396,21 +394,12 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) * PCI device. */ if (idd->idd_variant != IOC4_VARIANT_PCI_RT) { - struct work_struct *work; - work = kzalloc(sizeof(struct work_struct), GFP_KERNEL); - if (!work) { - printk(KERN_WARNING - "%s: IOC4 unable to allocate memory for " - "load of sub-modules.\n", __func__); - } else { - /* Request the module from a work procedure as the - * modprobe goes out to a userland helper and that - * will hang if done directly from ioc4_probe(). - */ - printk(KERN_INFO "IOC4 loading sgiioc4 submodule\n"); - INIT_WORK(work, ioc4_load_modules); - schedule_work(work); - } + /* Request the module from a work procedure as the modprobe + * goes out to a userland helper and that will hang if done + * directly from ioc4_probe(). + */ + printk(KERN_INFO "IOC4 loading sgiioc4 submodule\n"); + schedule_work(&ioc4_load_modules_work); } return 0; @@ -498,7 +487,7 @@ static void __exit ioc4_exit(void) { /* Ensure ioc4_load_modules() has completed before exiting */ - flush_scheduled_work(); + flush_work_sync(&ioc4_load_modules_work); pci_unregister_driver(&ioc4_driver); } -- cgit v1.2.3 From 707bcf326bd50c875d82bd2e7c31dcfb92b7e813 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 16:14:20 +0100 Subject: media/video: explicitly flush request_module work Video drivers request submodules using a work during probe and calls flush_scheduled_work() on exit to make sure the work is complete before being unloaded. This patch makes these drivers flush the work directly instead of using flush_scheduled_work(). While at it, relocate request_submodules() call in saa7134_initdev() right right before successful return as in other drivers to avoid failing after the work is scheduled and returning failure without the work still active. This is in preparation for the deprecation of flush_scheduled_work(). Signed-off-by: Tejun Heo Cc: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 9 +++++++++ drivers/media/video/cx18/cx18-driver.c | 8 ++++++++ drivers/media/video/cx231xx/cx231xx-cards.c | 8 ++++++++ drivers/media/video/cx88/cx88-mpeg.c | 8 ++++++++ drivers/media/video/em28xx/em28xx-cards.c | 8 ++++++++ drivers/media/video/saa7134/saa7134-core.c | 11 +++++++++-- 6 files changed, 50 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index a529619e51f6..53285aa6e72c 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -189,8 +189,14 @@ static void request_modules(struct bttv *dev) INIT_WORK(&dev->request_module_wk, request_module_async); schedule_work(&dev->request_module_wk); } + +static void flush_request_modules(struct bttv *dev) +{ + flush_work_sync(&dev->request_module_wk); +} #else #define request_modules(dev) +#define flush_request_modules(dev) #endif /* CONFIG_MODULES */ @@ -4573,6 +4579,9 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) if (bttv_verbose) printk("bttv%d: unloading\n",btv->c.nr); + if (bttv_tvcards[btv->c.type].has_dvb) + flush_request_modules(btv); + /* shutdown everything (DMA+IRQs) */ btand(~15, BT848_GPIO_DMA_CTL); btwrite(0, BT848_INT_MASK); diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index df60f27337cf..f6fdcfb1084b 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -266,8 +266,14 @@ static void request_modules(struct cx18 *dev) INIT_WORK(&dev->request_module_wk, request_module_async); schedule_work(&dev->request_module_wk); } + +static void flush_request_modules(struct cx18 *dev) +{ + flush_work_sync(&dev->request_module_wk); +} #else #define request_modules(dev) +#define flush_request_modules(dev) #endif /* CONFIG_MODULES */ /* Generic utility functions */ @@ -1226,6 +1232,8 @@ static void cx18_remove(struct pci_dev *pci_dev) CX18_DEBUG_INFO("Removing Card\n"); + flush_request_modules(cx); + /* Stop all captures */ CX18_DEBUG_INFO("Stopping all streams\n"); if (atomic_read(&cx->tot_capturing) > 0) diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 56c2d8195ac6..05b65057b8a7 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -762,8 +762,14 @@ static void request_modules(struct cx231xx *dev) INIT_WORK(&dev->request_module_wk, request_module_async); schedule_work(&dev->request_module_wk); } + +static void flush_request_modules(struct cx231xx *dev) +{ + flush_work_sync(&dev->request_module_wk); +} #else #define request_modules(dev) +#define flush_request_modules(dev) #endif /* CONFIG_MODULES */ /* @@ -1096,6 +1102,8 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) if (!dev->udev) return; + flush_request_modules(dev); + /* delete v4l2 device */ v4l2_device_unregister(&dev->v4l2_dev); diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index f7d71acbb078..addf9545e9bf 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -66,8 +66,14 @@ static void request_modules(struct cx8802_dev *dev) INIT_WORK(&dev->request_module_wk, request_module_async); schedule_work(&dev->request_module_wk); } + +static void flush_request_modules(struct cx8802_dev *dev) +{ + flush_work_sync(&dev->request_module_wk); +} #else #define request_modules(dev) +#define flush_request_modules(dev) #endif /* CONFIG_MODULES */ @@ -819,6 +825,8 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) dprintk( 1, "%s\n", __func__); + flush_request_modules(dev); + if (!list_empty(&dev->drvlist)) { struct cx8802_driver *drv, *tmp; int err; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 54859233f311..d60538bb22b3 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2632,8 +2632,14 @@ static void request_modules(struct em28xx *dev) INIT_WORK(&dev->request_module_wk, request_module_async); schedule_work(&dev->request_module_wk); } + +static void flush_request_modules(struct em28xx *dev) +{ + flush_work_sync(&dev->request_module_wk); +} #else #define request_modules(dev) +#define flush_request_modules(dev) #endif /* CONFIG_MODULES */ /* @@ -3060,6 +3066,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) em28xx_info("disconnecting %s\n", dev->vdev->name); + flush_request_modules(dev); + /* wait until all current v4l2 io is finished then deallocate resources */ mutex_lock(&dev->lock); diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 764d7d219fed..2ceeac7ae34d 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -166,8 +166,14 @@ static void request_submodules(struct saa7134_dev *dev) schedule_work(&dev->request_module_wk); } +static void flush_request_submodules(struct saa7134_dev *dev) +{ + flush_work_sync(&dev->request_module_wk); +} + #else #define request_submodules(dev) +#define flush_request_submodules(dev) #endif /* CONFIG_MODULES */ /* ------------------------------------------------------------------ */ @@ -1010,8 +1016,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, } } - request_submodules(dev); - v4l2_prio_init(&dev->prio); mutex_lock(&saa7134_devlist_lock); @@ -1066,6 +1070,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (saa7134_dmasound_init && !dev->dmasound.priv_data) saa7134_dmasound_init(dev); + request_submodules(dev); return 0; fail4: @@ -1091,6 +1096,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev); struct saa7134_mpeg_ops *mops; + flush_request_submodules(dev); + /* Release DMA sound modules if present */ if (saa7134_dmasound_exit && dev->dmasound.priv_data) { saa7134_dmasound_exit(dev); -- cgit v1.2.3 From 8c71778cbf2c8beaefaa2dee5478aa0622d96682 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 16:14:20 +0100 Subject: media/video: don't use flush_scheduled_work() This patch converts the remaining users of flush_scheduled_work() in media/video. * bttv-input.c and cx23885-input.c don't use workqueue at all. No need to flush. * Make omap24xxcam.c and saa7134-empress.c flush the used work directly. * In fd_defio.c, replace cancel_delayed_work() + flush_scheduled_work() with cancel_delayed_work_sync(). While at it, replace the deprecated cancel_rearming_delayed_work() with cancel_delayed_work_sync(). Signed-off-by: Tejun Heo Cc: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-input.c | 5 +---- drivers/media/video/cx23885/cx23885-input.c | 2 -- drivers/media/video/omap24xxcam.c | 6 +++--- drivers/media/video/saa7134/saa7134-empress.c | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 6bf05a7dc5f9..1989f002898b 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -229,16 +229,13 @@ static void bttv_ir_start(struct bttv *btv, struct card_ir *ir) static void bttv_ir_stop(struct bttv *btv) { - if (btv->remote->polling) { + if (btv->remote->polling) del_timer_sync(&btv->remote->timer); - flush_scheduled_work(); - } if (btv->remote->rc5_gpio) { u32 gpio; del_timer_sync(&btv->remote->timer_end); - flush_scheduled_work(); gpio = bttv_gpio_read(&btv->c); bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index bb61870b8d6e..4a326fe0b01c 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -230,8 +230,6 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev) v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); } - - flush_scheduled_work(); } static void cx23885_input_ir_close(void *priv) diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 378b094aff16..017552762902 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -1198,7 +1198,7 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) atomic_inc(&cam->reset_disable); - flush_scheduled_work(); + flush_work_sync(&cam->sensor_reset_work); rval = videobuf_streamoff(q); if (!rval) { @@ -1512,7 +1512,7 @@ static int omap24xxcam_release(struct file *file) atomic_inc(&cam->reset_disable); - flush_scheduled_work(); + flush_work_sync(&cam->sensor_reset_work); /* stop streaming capture */ videobuf_streamoff(&fh->vbq); @@ -1536,7 +1536,7 @@ static int omap24xxcam_release(struct file *file) * not be scheduled anymore since streaming is already * disabled.) */ - flush_scheduled_work(); + flush_work_sync(&cam->sensor_reset_work); mutex_lock(&cam->mutex); if (atomic_dec_return(&cam->users) == 0) { diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index b890aafe7d64..6b8459c7728e 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -553,7 +553,7 @@ static int empress_fini(struct saa7134_dev *dev) if (NULL == dev->empress_dev) return 0; - flush_scheduled_work(); + flush_work_sync(&dev->empress_workqueue); video_unregister_device(dev->empress_dev); dev->empress_dev = NULL; return 0; -- cgit v1.2.3 From 37c95bfe944babae817bfcf02c996729c9a3335d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 16:14:20 +0100 Subject: speedtch: don't abuse struct delayed_work speedtch directly uses the internal timer and work members of a struct delayed_work. Use a separate work item and timer instead. * Nicolas Kaiser discovered that timer init was missing. Fixed. Signed-off-by: Tejun Heo Acked-by: Greg Kroah-Hartman Tested-by: Nicolas Kaiser Cc: Duncan Sands Cc: linux-usb@vger.kernel.org --- drivers/usb/atm/speedtch.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 4716e707de59..9046eba112af 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -139,7 +139,8 @@ struct speedtch_instance_data { struct speedtch_params params; /* set in probe, constant afterwards */ - struct delayed_work status_checker; + struct timer_list status_check_timer; + struct work_struct status_check_work; unsigned char last_status; @@ -498,7 +499,7 @@ static void speedtch_check_status(struct work_struct *work) { struct speedtch_instance_data *instance = container_of(work, struct speedtch_instance_data, - status_checker.work); + status_check_work); struct usbatm_data *usbatm = instance->usbatm; struct atm_dev *atm_dev = usbatm->atm_dev; unsigned char *buf = instance->scratch_buffer; @@ -575,11 +576,11 @@ static void speedtch_status_poll(unsigned long data) { struct speedtch_instance_data *instance = (void *)data; - schedule_delayed_work(&instance->status_checker, 0); + schedule_work(&instance->status_check_work); /* The following check is racy, but the race is harmless */ if (instance->poll_delay < MAX_POLL_DELAY) - mod_timer(&instance->status_checker.timer, jiffies + msecs_to_jiffies(instance->poll_delay)); + mod_timer(&instance->status_check_timer, jiffies + msecs_to_jiffies(instance->poll_delay)); else atm_warn(instance->usbatm, "Too many failures - disabling line status polling\n"); } @@ -595,7 +596,7 @@ static void speedtch_resubmit_int(unsigned long data) if (int_urb) { ret = usb_submit_urb(int_urb, GFP_ATOMIC); if (!ret) - schedule_delayed_work(&instance->status_checker, 0); + schedule_work(&instance->status_check_work); else { atm_dbg(instance->usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY)); @@ -624,7 +625,7 @@ static void speedtch_handle_int(struct urb *int_urb) } if ((count == 6) && !memcmp(up_int, instance->int_data, 6)) { - del_timer(&instance->status_checker.timer); + del_timer(&instance->status_check_timer); atm_info(usbatm, "DSL line goes up\n"); } else if ((count == 6) && !memcmp(down_int, instance->int_data, 6)) { atm_info(usbatm, "DSL line goes down\n"); @@ -640,7 +641,7 @@ static void speedtch_handle_int(struct urb *int_urb) if ((int_urb = instance->int_urb)) { ret = usb_submit_urb(int_urb, GFP_ATOMIC); - schedule_delayed_work(&instance->status_checker, 0); + schedule_work(&instance->status_check_work); if (ret < 0) { atm_dbg(usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); goto fail; @@ -686,7 +687,7 @@ static int speedtch_atm_start(struct usbatm_data *usbatm, struct atm_dev *atm_de } /* Start status polling */ - mod_timer(&instance->status_checker.timer, jiffies + msecs_to_jiffies(1000)); + mod_timer(&instance->status_check_timer, jiffies + msecs_to_jiffies(1000)); return 0; } @@ -698,7 +699,7 @@ static void speedtch_atm_stop(struct usbatm_data *usbatm, struct atm_dev *atm_de atm_dbg(usbatm, "%s entered\n", __func__); - del_timer_sync(&instance->status_checker.timer); + del_timer_sync(&instance->status_check_timer); /* * Since resubmit_timer and int_urb can schedule themselves and @@ -869,10 +870,11 @@ static int speedtch_bind(struct usbatm_data *usbatm, usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0); - INIT_DELAYED_WORK(&instance->status_checker, speedtch_check_status); + INIT_WORK(&instance->status_check_work, speedtch_check_status); + init_timer(&instance->status_check_timer); - instance->status_checker.timer.function = speedtch_status_poll; - instance->status_checker.timer.data = (unsigned long)instance; + instance->status_check_timer.function = speedtch_status_poll; + instance->status_check_timer.data = (unsigned long)instance; instance->last_status = 0xff; instance->poll_delay = MIN_POLL_DELAY; -- cgit v1.2.3 From 569ff2de2e1c8ac67c8df3a7367d46d0d9460a35 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Dec 2010 16:14:20 +0100 Subject: usb: don't use flush_scheduled_work() flush_scheduled_work() is being deprecated. Directly flush or cancel work items instead. * u_ether, isp1301_omap, speedtch conversions are straight-forward. * ochi-hcd should only flush when quirk_nec() is true as otherwise the work wouldn't have been initialized. * In oti6858, cancel_delayed_work() + flush_scheduled_work() -> cancel_delayed_work_sync(). Signed-off-by: Tejun Heo Acked-by: Greg Kroah-Hartman Cc: David Brownell Cc: Duncan Sands Cc: linux-usb@vger.kernel.org --- drivers/usb/atm/speedtch.c | 2 +- drivers/usb/gadget/u_ether.c | 4 +--- drivers/usb/host/ohci-hcd.c | 3 ++- drivers/usb/otg/isp1301_omap.c | 2 +- drivers/usb/serial/oti6858.c | 5 ++--- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 9046eba112af..0842cfbf60cf 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -718,7 +718,7 @@ static void speedtch_atm_stop(struct usbatm_data *usbatm, struct atm_dev *atm_de del_timer_sync(&instance->resubmit_timer); usb_free_urb(int_urb); - flush_scheduled_work(); + flush_work_sync(&instance->status_check_work); } static int speedtch_pre_reset(struct usb_interface *intf) diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index fbe86ca95802..00a78248d764 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -829,11 +829,9 @@ void gether_cleanup(void) return; unregister_netdev(the_dev->net); + flush_work_sync(&the_dev->work); free_netdev(the_dev->net); - /* assuming we used keventd, it must quiesce too */ - flush_scheduled_work(); - the_dev = NULL; } diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 5179acb7aa2f..bd5eff77d0cc 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -901,7 +901,8 @@ static void ohci_stop (struct usb_hcd *hcd) ohci_dump (ohci, 1); - flush_scheduled_work(); + if (quirk_nec(ohci)) + flush_work_sync(&ohci->nec_work); ohci_usb_reset (ohci); ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index 456969492410..e00fa1b22ecd 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c @@ -1247,7 +1247,7 @@ static int __exit isp1301_remove(struct i2c_client *i2c) isp->timer.data = 0; set_bit(WORK_STOP, &isp->todo); del_timer_sync(&isp->timer); - flush_scheduled_work(); + flush_work_sync(&isp->work); put_device(&i2c->dev); the_transceiver = NULL; diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index e199b0f4f99c..5be866bb7a41 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -613,9 +613,8 @@ static void oti6858_close(struct usb_serial_port *port) dbg("%s(): after buf_clear()", __func__); /* cancel scheduled setup */ - cancel_delayed_work(&priv->delayed_setup_work); - cancel_delayed_work(&priv->delayed_write_work); - flush_scheduled_work(); + cancel_delayed_work_sync(&priv->delayed_setup_work); + cancel_delayed_work_sync(&priv->delayed_write_work); /* shutdown our urbs */ dbg("%s(): shutting down urbs", __func__); -- cgit v1.2.3