Merge branch 'for-2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 8 Jan 2011 00:58:04 +0000 (16:58 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 8 Jan 2011 00:58:04 +0000 (16:58 -0800)
* 'for-2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq: (33 commits)
  usb: don't use flush_scheduled_work()
  speedtch: don't abuse struct delayed_work
  media/video: don't use flush_scheduled_work()
  media/video: explicitly flush request_module work
  ioc4: use static work_struct for ioc4_load_modules()
  init: don't call flush_scheduled_work() from do_initcalls()
  s390: don't use flush_scheduled_work()
  rtc: don't use flush_scheduled_work()
  mmc: update workqueue usages
  mfd: update workqueue usages
  dvb: don't use flush_scheduled_work()
  leds-wm8350: don't use flush_scheduled_work()
  mISDN: don't use flush_scheduled_work()
  macintosh/ams: don't use flush_scheduled_work()
  vmwgfx: don't use flush_scheduled_work()
  tpm: don't use flush_scheduled_work()
  sonypi: don't use flush_scheduled_work()
  hvsi: don't use flush_scheduled_work()
  xen: don't use flush_scheduled_work()
  gdrom: don't use flush_scheduled_work()
  ...

Fixed up trivial conflict in drivers/media/video/bt8xx/bttv-input.c
as per Tejun.

80 files changed:
Documentation/feature-removal-schedule.txt
arch/arm/mach-pxa/sharpsl_pm.c
arch/sh/drivers/push-switch.c
drivers/ata/libata-core.c
drivers/ata/libata-sff.c
drivers/block/floppy.c
drivers/block/xen-blkfront.c
drivers/cdrom/gdrom.c
drivers/char/hvsi.c
drivers/char/pcmcia/ipwireless/hardware.c
drivers/char/pcmcia/ipwireless/network.c
drivers/char/pcmcia/ipwireless/tty.c
drivers/char/sonypi.c
drivers/char/tpm/tpm.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
drivers/isdn/capi/capidrv.c
drivers/isdn/capi/kcapi.c
drivers/isdn/mISDN/hwchannel.c
drivers/isdn/mISDN/l1oip_core.c
drivers/leds/leds-wm8350.c
drivers/macintosh/ams/ams-core.c
drivers/macintosh/rack-meter.c
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-usb/dvb-usb-remote.c
drivers/media/dvb/mantis/mantis_evm.c
drivers/media/dvb/mantis/mantis_uart.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-input.c
drivers/media/video/cx18/cx18-driver.c
drivers/media/video/cx231xx/cx231xx-cards.c
drivers/media/video/cx23885/cx23885-input.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-input.c
drivers/media/video/omap24xxcam.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/mfd/menelaus.c
drivers/mfd/tps65010.c
drivers/misc/ioc4.c
drivers/mmc/core/core.c
drivers/mmc/host/omap.c
drivers/mmc/host/omap_hsmmc.c
drivers/net/chelsio/my3126.c
drivers/net/ibm_newemac/core.c
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/power/ds2760_battery.c
drivers/power/intel_mid_battery.c
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-ds1305.c
drivers/rtc/rtc-ds1374.c
drivers/rtc/rtc-ds3232.c
drivers/rtc/rtc-rx8025.c
drivers/s390/char/tape_3590.c
drivers/s390/char/tape_block.c
drivers/staging/pohmelfs/inode.c
drivers/usb/atm/cxacru.c
drivers/usb/atm/speedtch.c
drivers/usb/gadget/u_ether.c
drivers/usb/host/ohci-hcd.c
drivers/usb/otg/isp1301_omap.c
drivers/usb/serial/oti6858.c
drivers/video/fb_defio.c
drivers/video/omap/lcd_mipid.c
fs/ncpfs/inode.c
fs/nfsd/nfs4state.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/quorum.c
fs/xfs/xfs_mru_cache.c
include/linux/workqueue.h
init/main.c
kernel/workqueue.c
mm/slab.c
mm/vmstat.c
net/atm/lec.c
net/core/netpoll.c
net/dsa/dsa.c
net/netfilter/ipvs/ip_vs_ctl.c
net/sunrpc/xprtsock.c

index f2742e1..22f1081 100644 (file)
@@ -566,3 +566,13 @@ Why:       This field is deprecated. I2C device drivers shouldn't change their
 Who:   Jean Delvare <khali@linux-fr.org>
 
 ----------------------------
+
+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 <tj@kernel.org>
+
+----------------------------
index 8fed027..e68d46d 100644 (file)
@@ -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;
index 7b42c24..afc2455 100644 (file)
@@ -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);
 
index f23d6d4..0a6a943 100644 (file)
@@ -6128,7 +6128,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) {
index 484697f..af6141b 100644 (file)
@@ -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))
index 3951020..25e4dff 100644 (file)
@@ -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",
index 657873e..d7aa39e 100644 (file)
@@ -547,7 +547,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);
 
@@ -596,7 +596,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) {
index de65915..64a2146 100644 (file)
@@ -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);
index a2bc885..67a75a5 100644 (file)
@@ -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
index 99cffda..0aeb5a3 100644 (file)
@@ -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)
index 9fe5383..f7daeea 100644 (file)
@@ -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);
index 1a2c2c3..f5eb28b 100644 (file)
@@ -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);
index 73f66d0..79e36c8 100644 (file)
@@ -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);
index 7c41335..0b3af3f 100644 (file)
@@ -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 */
index 148a322..934a96a 100644 (file)
@@ -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))
                ;
index 41d9a5b..fe096a7 100644 (file)
@@ -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);
index e54e79d..92607ed 100644 (file)
@@ -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;
        }
index 3acf94c..2b33b26 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/rcupdate.h>
 
 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);
index 307bd6e..199f374 100644 (file)
@@ -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);
index 5b59796..bd526f6 100644 (file)
@@ -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);
 
index 5aab32c..a045232 100644 (file)
@@ -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);
index 2ad62c3..399beb1 100644 (file)
@@ -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);
index 53cce3a..39f660b 100644 (file)
@@ -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)
index 4df42aa..51752a9 100644 (file)
@@ -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;
index c6498f5..23005b3 100644 (file)
@@ -313,8 +313,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);
-               flush_scheduled_work();
+               cancel_delayed_work_sync(&d->rc_query_work);
                if (d->props.rc.mode == DVB_RC_LEGACY)
                        input_unregister_device(d->input_dev);
                else
index a7b369a..9f73c2c 100644 (file)
@@ -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);
 }
index 7d2f239..97b889e 100644 (file)
@@ -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);
index 849cd17..91399c9 100644 (file)
@@ -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 */
 
 
@@ -4429,6 +4435,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);
index 97793b9..e8b64bc 100644 (file)
@@ -319,16 +319,13 @@ static void bttv_ir_start(struct bttv *btv, struct bttv_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);
-               flush_scheduled_work();
 
                gpio = bttv_gpio_read(&btv->c);
                bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
index 676e5be..133ec2b 100644 (file)
@@ -267,8 +267,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 */
@@ -1233,6 +1239,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)
index 6905607..588f3e8 100644 (file)
@@ -813,8 +813,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 */
 
 /*
@@ -1147,6 +1153,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);
 
index 0b0d066..199b996 100644 (file)
@@ -229,8 +229,6 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev)
                v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
                v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
        }
-
-       flush_scheduled_work();
 }
 
 static void cx23885_input_ir_close(struct rc_dev *rc)
index f7d71ac..addf954 100644 (file)
@@ -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;
index 8af302b..099d5df 100644 (file)
@@ -2690,8 +2690,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 */
 
 /*
@@ -3118,6 +3124,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);
index 29cc744..ba1ba86 100644 (file)
@@ -551,7 +551,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;
        }
index 378b094..0175527 100644 (file)
@@ -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) {
index 756a278..6abeecf 100644 (file)
@@ -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);
index b890aaf..6b8459c 100644 (file)
@@ -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;
index 4ba85bb..9cee8e7 100644 (file)
@@ -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;
index d0016b6..90187fe 100644 (file)
@@ -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);
 
index 1932066..668d41e 100644 (file)
@@ -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);
 }
 
index 57dcf8f..a3a780f 100644 (file)
@@ -1790,7 +1790,7 @@ static int __init mmc_init(void)
 {
        int ret;
 
-       workqueue = create_singlethread_workqueue("kmmcd");
+       workqueue = alloc_ordered_workqueue("kmmcd", 0);
        if (!workqueue)
                return -ENOMEM;
 
index 0c7e37f..379d2ff 100644 (file)
@@ -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);
index 5d46021..078fdf1 100644 (file)
@@ -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);
index 4c60285..a683fd3 100644 (file)
@@ -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;
 }
 
index 8f11d29..6d9275c 100644 (file)
@@ -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);
index 43307bd..6107304 100644 (file)
@@ -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);
 }
index b3c01c1..e7f8978 100644 (file)
@@ -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);
index 2a10cd3..36cf402 100644 (file)
@@ -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);
index 62227cd..0cc0984 100644 (file)
@@ -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;
index 48da85e..077af1d 100644 (file)
@@ -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);
index 1f0007f..47fb635 100644 (file)
@@ -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);
index 5706355..23a9ee1 100644 (file)
@@ -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);
index 1146e35..af32a62 100644 (file)
@@ -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);
index deff2c3..fbe361f 100644 (file)
@@ -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);
 }
 
index f0fa9ca..55d2d0f 100644 (file)
@@ -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) {
index cc8d284..56d3a4e 100644 (file)
@@ -1325,8 +1325,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__);
index f383cb4..a845f8b 100644 (file)
@@ -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);
index 4716e70..0842cfb 100644 (file)
@@ -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
@@ -717,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)
@@ -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;
 
index e3454fe..1eda968 100644 (file)
@@ -839,11 +839,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;
 }
 
index 9751647..759a12f 100644 (file)
@@ -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);
index 4569694..e00fa1b 100644 (file)
@@ -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;
index e199b0f..5be866b 100644 (file)
@@ -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__);
index 6b93ef9..8040001 100644 (file)
@@ -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);
index 64dcc74..90e3bdd 100644 (file)
@@ -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)
index 9531c05..9b39a5d 100644 (file)
@@ -317,7 +317,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)
index 116cab9..fbd18c3 100644 (file)
@@ -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();
index 9f26ac9..9e3d45b 100644 (file)
@@ -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(&reg->hr_write_timeout_work);
-       flush_scheduled_work();
+       cancel_delayed_work_sync(&reg->hr_write_timeout_work);
 }
 
 static inline void o2hb_bio_wait_init(struct o2hb_bio_wait_ctxt *wc)
index cf3e166..a873667 100644 (file)
@@ -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);
 }
index 45ce15d..edfa178 100644 (file)
@@ -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);
        }
 
index bd257fe..1ac1158 100644 (file)
@@ -409,7 +409,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)
 {
@@ -417,7 +417,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);
index ea51770..00799c1 100644 (file)
@@ -777,9 +777,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();
 }
 
 /*
index e785b0f..8ee6ec8 100644 (file)
@@ -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.
index 6107f23..39e92c0 100644 (file)
--- 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;
index 8f62f17..33c33e7 100644 (file)
@@ -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:
index 179e04b..38754fd 100644 (file)
@@ -1607,7 +1607,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
index 72d9b50..02dc2cb 100644 (file)
@@ -923,7 +923,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);
index 6112a12..0c877a7 100644 (file)
@@ -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];
index c6f2936..22f7ad5 100644 (file)
@@ -3430,7 +3430,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);
index dfcab5a..96549df 100644 (file)
@@ -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);