}
                if (astat & BT878_ARISCI) {
                        bt->finished_block = (stat & BT878_ARISCS) >> 28;
-                       if (bt->tasklet.callback)
-                               tasklet_schedule(&bt->tasklet);
+                       if (bt->bh_work.func)
+                               queue_work(system_bh_wq, &bt->bh_work);
                        break;
                }
                count++;
        btwrite(0, BT878_AINT_MASK);
        bt878_num++;
 
-       if (!bt->tasklet.func)
-               tasklet_disable(&bt->tasklet);
+       if (!bt->bh_work.func)
+               disable_work_sync(&bt->bh_work);
 
        return 0;
 
 
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #include "bt848.h"
 #include "bttv.h"
        dma_addr_t risc_dma;
        u32 risc_pos;
 
-       struct tasklet_struct tasklet;
+       struct work_struct bh_work;
        int shutdown;
 };
 
 
 
 #define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
 
-static void dvb_bt8xx_task(struct tasklet_struct *t)
+static void dvb_bt8xx_work(struct work_struct *t)
 {
-       struct bt878 *bt = from_tasklet(bt, t, tasklet);
+       struct bt878 *bt = from_work(bt, t, bh_work);
        struct dvb_bt8xx_card *card = dev_get_drvdata(&bt->adapter->dev);
 
        dprintk("%d\n", card->bt->finished_block);
                goto err_disconnect_frontend;
        }
 
-       tasklet_setup(&card->bt->tasklet, dvb_bt8xx_task);
+       INIT_WORK(&card->bt->bh_work, dvb_bt8xx_work);
 
        frontend_init(card, type);
 
        dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
 
        bt878_stop(card->bt);
-       tasklet_kill(&card->bt->tasklet);
+       cancel_work_sync(&card->bt->bh_work);
        dvb_net_release(&card->dvbnet);
        card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
        card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
 
        spinlock_t             lock; /* lock link access */
        struct mutex           flash_mutex; /* lock flash access */
        struct ddb_lnb         lnb;
-       struct tasklet_struct  tasklet;
+       struct work_struct     bh_work;
        struct ddb_ids         ids;
 
        spinlock_t             temp_lock; /* lock temp chip access */
 
        if (stat & MANTIS_INT_RISCI) {
                dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
                mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
-               tasklet_schedule(&mantis->tasklet);
+               queue_work(system_bh_wq, &mantis->bh_work);
        }
        if (stat & MANTIS_INT_I2CDONE) {
                dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
 
        if (stat & MANTIS_INT_RISCI) {
                dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
                mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
-               tasklet_schedule(&mantis->tasklet);
+               queue_work(system_bh_wq, &mantis->bh_work);
        }
        if (stat & MANTIS_INT_I2CDONE) {
                dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
 
        __le32                  *risc_cpu;
        dma_addr_t              risc_dma;
 
-       struct tasklet_struct   tasklet;
+       struct work_struct      bh_work;
        spinlock_t              intmask_lock;
 
        struct i2c_adapter      adapter;
 
 }
 
 
-void mantis_dma_xfer(struct tasklet_struct *t)
+void mantis_dma_xfer(struct work_struct *t)
 {
-       struct mantis_pci *mantis = from_tasklet(mantis, t, tasklet);
+       struct mantis_pci *mantis = from_work(mantis, t, bh_work);
        struct mantis_hwconfig *config = mantis->hwconfig;
 
        while (mantis->last_block != mantis->busy_block) {
 
 extern int mantis_dma_exit(struct mantis_pci *mantis);
 extern void mantis_dma_start(struct mantis_pci *mantis);
 extern void mantis_dma_stop(struct mantis_pci *mantis);
-extern void mantis_dma_xfer(struct tasklet_struct *t);
+extern void mantis_dma_xfer(struct work_struct *t);
 
 #endif /* __MANTIS_DMA_H */
 
        if (mantis->feeds == 1)  {
                dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
                mantis_dma_start(mantis);
-               tasklet_enable(&mantis->tasklet);
+               enable_and_queue_work(system_bh_wq, &mantis->bh_work);
        }
 
        return mantis->feeds;
        mantis->feeds--;
        if (mantis->feeds == 0) {
                dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
-               tasklet_disable(&mantis->tasklet);
+               disable_work_sync(&mantis->bh_work);
                mantis_dma_stop(mantis);
        }
 
        }
 
        dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
-       tasklet_setup(&mantis->tasklet, mantis_dma_xfer);
-       tasklet_disable(&mantis->tasklet);
+       INIT_WORK(&mantis->bh_work, mantis_dma_xfer);
+       disable_work_sync(&mantis->bh_work);
        if (mantis->hwconfig) {
                result = config->frontend_init(mantis, mantis->fe);
                if (result < 0) {
 
        /* Error conditions ..  */
 err5:
-       tasklet_kill(&mantis->tasklet);
+       cancel_work_sync(&mantis->bh_work);
        dvb_net_release(&mantis->dvbnet);
        if (mantis->fe) {
                dvb_unregister_frontend(mantis->fe);
                dvb_frontend_detach(mantis->fe);
        }
 
-       tasklet_kill(&mantis->tasklet);
+       cancel_work_sync(&mantis->bh_work);
        dvb_net_release(&mantis->dvbnet);
 
        mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
 
 /* nGene interrupt handler **************************************************/
 /****************************************************************************/
 
-static void event_tasklet(struct tasklet_struct *t)
+static void event_bh_work(struct work_struct *t)
 {
-       struct ngene *dev = from_tasklet(dev, t, event_tasklet);
+       struct ngene *dev = from_work(dev, t, event_bh_work);
 
        while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) {
                struct EVENT_BUFFER Event =
        }
 }
 
-static void demux_tasklet(struct tasklet_struct *t)
+static void demux_bh_work(struct work_struct *t)
 {
-       struct ngene_channel *chan = from_tasklet(chan, t, demux_tasklet);
+       struct ngene_channel *chan = from_work(chan, t, demux_bh_work);
        struct device *pdev = &chan->dev->pci_dev->dev;
        struct SBufferHeader *Cur = chan->nextBuffer;
 
                        dev->EventQueueOverflowFlag = 1;
                }
                dev->EventBuffer->EventStatus &= ~0x80;
-               tasklet_schedule(&dev->event_tasklet);
+               queue_work(system_bh_wq, &dev->event_bh_work);
                rc = IRQ_HANDLED;
        }
 
                             ngeneBuffer.SR.Flags & 0xC0) == 0x80) {
                                dev->channel[i].nextBuffer->
                                        ngeneBuffer.SR.Flags |= 0x40;
-                               tasklet_schedule(
-                                       &dev->channel[i].demux_tasklet);
+                               queue_work(system_bh_wq,
+                                          &dev->channel[i].demux_bh_work);
                                rc = IRQ_HANDLED;
                        }
                }
        struct device *pdev = &dev->pci_dev->dev;
        int i;
 
-       tasklet_setup(&dev->event_tasklet, event_tasklet);
+       INIT_WORK(&dev->event_bh_work, event_bh_work);
 
        memset_io(dev->iomem + 0xc000, 0x00, 0x220);
        memset_io(dev->iomem + 0xc400, 0x00, 0x100);
        if (chan->running)
                set_transfer(chan, 0);
 
-       tasklet_kill(&chan->demux_tasklet);
+       cancel_work_sync(&chan->demux_bh_work);
 
        if (chan->ci_dev) {
                dvb_unregister_device(chan->ci_dev);
        struct ngene_info *ni = dev->card_info;
        int io = ni->io_type[nr];
 
-       tasklet_setup(&chan->demux_tasklet, demux_tasklet);
+       INIT_WORK(&chan->demux_bh_work, demux_bh_work);
        chan->users = 0;
        chan->type = io;
        chan->mode = chan->type;        /* for now only one mode */
        struct ngene *dev = pci_get_drvdata(pdev);
        int i;
 
-       tasklet_kill(&dev->event_tasklet);
+       cancel_work_sync(&dev->event_bh_work);
        for (i = MAX_STREAM - 1; i >= 0; i--)
                release_channel(&dev->channel[i]);
        if (dev->ci.en)
 
 #include <linux/scatterlist.h>
 
 #include <linux/dvb/frontend.h>
+#include <linux/workqueue.h>
 
 #include <media/dmxdev.h>
 #include <media/dvbdev.h>
        int                   users;
        struct video_device  *v4l_dev;
        struct dvb_device    *ci_dev;
-       struct tasklet_struct demux_tasklet;
+       struct work_struct    demux_bh_work;
 
        struct SBufferHeader *nextBuffer;
        enum KSSTATE          State;
        struct EVENT_BUFFER   EventQueue[EVENT_QUEUE_SIZE];
        int                   EventQueueOverflowCount;
        int                   EventQueueOverflowFlag;
-       struct tasklet_struct event_tasklet;
+       struct work_struct    event_bh_work;
        struct EVENT_BUFFER  *EventBuffer;
        int                   EventQueueWriteIndex;
        int                   EventQueueReadIndex;
 
                (port->_dmaInterruptCH0 | port->_dmaInterruptCH1));
 }
 
-/* tasklet handler: DMA data to dmx.*/
-static void smi_dma_xfer(struct tasklet_struct *t)
+/* BH work handler: DMA data to dmx.*/
+static void smi_dma_xfer(struct work_struct *t)
 {
-       struct smi_port *port = from_tasklet(port, t, tasklet);
+       struct smi_port *port = from_work(port, t, bh_work);
        struct smi_dev *dev = port->dev;
        u32 intr_status, finishedData, dmaManagement;
        u8 dmaChan0State, dmaChan1State;
        }
 
        smi_port_disableInterrupt(port);
-       tasklet_setup(&port->tasklet, smi_dma_xfer);
-       tasklet_disable(&port->tasklet);
+       INIT_WORK(&port->bh_work, smi_dma_xfer);
+       disable_work_sync(&port->bh_work);
        port->enable = 1;
        return 0;
 err:
 static void smi_port_exit(struct smi_port *port)
 {
        smi_port_disableInterrupt(port);
-       tasklet_kill(&port->tasklet);
+       cancel_work_sync(&port->bh_work);
        smi_port_dma_free(port);
        port->enable = 0;
 }
                smi_port_disableInterrupt(port);
                port->_int_status = int_status;
                smi_port_clearInterrupt(port);
-               tasklet_schedule(&port->tasklet);
+               queue_work(system_bh_wq, &port->bh_work);
                handled = 1;
        }
        return handled;
                smi_port_clearInterrupt(port);
                smi_port_enableInterrupt(port);
                smi_write(port->DMA_MANAGEMENT, dmaManagement);
-               tasklet_enable(&port->tasklet);
+               enable_and_queue_work(system_bh_wq, &port->bh_work);
        }
        return port->users;
 }
        if (--port->users)
                return port->users;
 
-       tasklet_disable(&port->tasklet);
+       disable_work_sync(&port->bh_work);
        smi_port_disableInterrupt(port);
        smi_clear(port->DMA_MANAGEMENT, 0x30003);
        return 0;
 
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 #include <media/rc-core.h>
 
 #include <media/demux.h>
        u32 _dmaInterruptCH0;
        u32 _dmaInterruptCH1;
        u32 _int_status;
-       struct tasklet_struct tasklet;
+       struct work_struct bh_work;
        /* dvb */
        struct dmx_frontend hw_frontend;
        struct dmx_frontend mem_frontend;
 
 #include <linux/interrupt.h>
 #include <linux/input.h>
 #include <linux/spinlock.h>
+#include <linux/workqueue.h>
 
 #include <media/dvb_ca_en50221.h>
 
        struct video_device vd;
        int cur_input;
        int has_saa7113;
-       struct tasklet_struct ciintf_irq_tasklet;
+       struct work_struct ciintf_irq_bh_work;
        int slot_status;
        struct dvb_ca_en50221 ca;
        u8 reinitialise_demod:1;
 
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/workqueue.h>
 #include <media/rc-core.h>
 
 #include "budget.h"
 
 struct budget_ci_ir {
        struct rc_dev *dev;
-       struct tasklet_struct msp430_irq_tasklet;
+       struct work_struct msp430_irq_bh_work;
        char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
        char phys[32];
        int rc5_device;
 
 struct budget_ci {
        struct budget budget;
-       struct tasklet_struct ciintf_irq_tasklet;
+       struct work_struct ciintf_irq_bh_work;
        int slot_status;
        int ci_irq;
        struct dvb_ca_en50221 ca;
        u8 tuner_pll_address; /* used for philips_tdm1316l configs */
 };
 
-static void msp430_ir_interrupt(struct tasklet_struct *t)
+static void msp430_ir_interrupt(struct work_struct *t)
 {
-       struct budget_ci_ir *ir = from_tasklet(ir, t, msp430_irq_tasklet);
+       struct budget_ci_ir *ir = from_work(ir, t, msp430_irq_bh_work);
        struct budget_ci *budget_ci = container_of(ir, typeof(*budget_ci), ir);
        struct rc_dev *dev = budget_ci->ir.dev;
        u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
 
        budget_ci->ir.dev = dev;
 
-       tasklet_setup(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt);
+       INIT_WORK(&budget_ci->ir.msp430_irq_bh_work, msp430_ir_interrupt);
 
        SAA7146_IER_ENABLE(saa, MASK_06);
        saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
 
        SAA7146_IER_DISABLE(saa, MASK_06);
        saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
-       tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
+       cancel_work_sync(&budget_ci->ir.msp430_irq_bh_work);
 
        rc_unregister_device(budget_ci->ir.dev);
 }
        return 0;
 }
 
-static void ciintf_interrupt(struct tasklet_struct *t)
+static void ciintf_interrupt(struct work_struct *t)
 {
-       struct budget_ci *budget_ci = from_tasklet(budget_ci, t,
-                                                  ciintf_irq_tasklet);
+       struct budget_ci *budget_ci = from_work(budget_ci, t,
+                                                  ciintf_irq_bh_work);
        struct saa7146_dev *saa = budget_ci->budget.dev;
        unsigned int flags;
 
 
        // Setup CI slot IRQ
        if (budget_ci->ci_irq) {
-               tasklet_setup(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt);
+               INIT_WORK(&budget_ci->ciintf_irq_bh_work, ciintf_interrupt);
                if (budget_ci->slot_status != SLOTSTATUS_NONE)
                        saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
                else
        if (budget_ci->ci_irq) {
                SAA7146_IER_DISABLE(saa, MASK_03);
                saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
-               tasklet_kill(&budget_ci->ciintf_irq_tasklet);
+               cancel_work_sync(&budget_ci->ciintf_irq_bh_work);
        }
 
        // reset interface
        dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
 
        if (*isr & MASK_06)
-               tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
+               queue_work(system_bh_wq, &budget_ci->ir.msp430_irq_bh_work);
 
        if (*isr & MASK_10)
                ttpci_budget_irq10_handler(dev, isr);
 
        if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
-               tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
+               queue_work(system_bh_wq, &budget_ci->ciintf_irq_bh_work);
 }
 
 static u8 philips_su1278_tt_inittab[] = {
 
        return ret;
 }
 
-static void vpeirq(struct tasklet_struct *t)
+static void vpeirq(struct work_struct *t)
 {
-       struct budget *budget = from_tasklet(budget, t, vpe_tasklet);
+       struct budget *budget = from_work(budget, t, vpe_bh_work);
        u8 *mem = (u8 *) (budget->grabbing);
        u32 olddma = budget->ttbp;
        u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
        /* upload all */
        saa7146_write(dev, GPIO_CTRL, 0x000000);
 
-       tasklet_setup(&budget->vpe_tasklet, vpeirq);
+       INIT_WORK(&budget->vpe_bh_work, vpeirq);
 
        /* frontend power on */
        if (bi->type != BUDGET_FS_ACTIVY)
 
        budget_unregister(budget);
 
-       tasklet_kill(&budget->vpe_tasklet);
+       cancel_work_sync(&budget->vpe_bh_work);
 
        saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
 
        dprintk(8, "dev: %p, budget: %p\n", dev, budget);
 
        if (*isr & MASK_10)
-               tasklet_schedule(&budget->vpe_tasklet);
+               queue_work(system_bh_wq, &budget->vpe_bh_work);
 }
 EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
 
 
 
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #include <media/drv-intf/saa7146.h>
 
        unsigned char *grabbing;
        struct saa7146_pgtable pt;
 
-       struct tasklet_struct fidb_tasklet;
-       struct tasklet_struct vpe_tasklet;
+       struct work_struct fidb_bh_work;
+       struct work_struct vpe_bh_work;
 
        struct dmxdev dmxdev;
        struct dvb_demux demux;
 
                cur_frame->gop_seqno = input->frame_gop_seqno;
 
                dev->h264_buf_w_index = next_frame_index;
-               tasklet_schedule(&dev->tasklet);
+               queue_work(system_bh_wq, &dev->bh_work);
 
                cur_frame = next_frame;
 
 
  */
 
 #include <linux/module.h>
+#include <linux/workqueue.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-event.h>
 #include <media/videobuf2-dma-contig.h>
 static v4l2_std_id tw5864_get_v4l2_std(enum tw5864_vid_std std);
 static enum tw5864_vid_std tw5864_from_v4l2_std(v4l2_std_id v4l2_std);
 
-static void tw5864_handle_frame_task(struct tasklet_struct *t);
+static void tw5864_handle_frame_work(struct work_struct *t);
 static void tw5864_handle_frame(struct tw5864_h264_frame *frame);
 static void tw5864_frame_interval_set(struct tw5864_input *input);
 
        dev->irqmask |= TW5864_INTR_VLC_DONE | TW5864_INTR_TIMER;
        tw5864_irqmask_apply(dev);
 
-       tasklet_setup(&dev->tasklet, tw5864_handle_frame_task);
+       INIT_WORK(&dev->bh_work, tw5864_handle_frame_work);
 
        for (i = 0; i < TW5864_INPUTS; i++) {
                dev->inputs[i].root = dev;
        for (i = last_input_nr_registered; i >= 0; i--)
                tw5864_video_input_fini(&dev->inputs[i]);
 
-       tasklet_kill(&dev->tasklet);
+       cancel_work_sync(&dev->bh_work);
 
 free_dma:
        for (i = last_dma_allocated; i >= 0; i--) {
 {
        int i;
 
-       tasklet_kill(&dev->tasklet);
+       cancel_work_sync(&dev->bh_work);
 
        for (i = 0; i < TW5864_INPUTS; i++)
                tw5864_video_input_fini(&dev->inputs[i]);
        return detected;
 }
 
-static void tw5864_handle_frame_task(struct tasklet_struct *t)
+static void tw5864_handle_frame_work(struct work_struct *t)
 {
-       struct tw5864_dev *dev = from_tasklet(dev, t, tasklet);
+       struct tw5864_dev *dev = from_work(dev, t, bh_work);
        unsigned long flags;
        int batch_size = H264_BUF_CNT;
 
 
 #include <linux/mutex.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
+#include <linux/workqueue.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
        int nr; /* input number */
        struct tw5864_dev *root;
        struct mutex lock; /* used for vidq and vdev */
-       spinlock_t slock; /* used for sync between ISR, tasklet & V4L2 API */
+       spinlock_t slock; /* used for sync between ISR, bh_work & V4L2 API */
        struct video_device vdev;
        struct v4l2_ctrl_handler hdl;
        struct vb2_queue vidq;
 
 /* global device status */
 struct tw5864_dev {
-       spinlock_t slock; /* used for sync between ISR, tasklet & V4L2 API */
+       spinlock_t slock; /* used for sync between ISR, bh_work & V4L2 API */
        struct v4l2_device v4l2_dev;
        struct tw5864_input inputs[TW5864_INPUTS];
 #define H264_BUF_CNT 4
        int h264_buf_r_index;
        int h264_buf_w_index;
 
-       struct tasklet_struct tasklet;
+       struct work_struct bh_work;
 
        int encoder_busy;
        /* Input number to check next for ready raw picture (in RR fashion) */
 
 #include <linux/videodev2.h>
 
 #include <linux/platform_data/media/camera-pxa.h>
+#include <linux/workqueue.h>
 
 #define PXA_CAM_VERSION "0.0.6"
 #define PXA_CAM_DRV_NAME "pxa27x-camera"
        unsigned int            buf_sequence;
 
        struct pxa_buffer       *active;
-       struct tasklet_struct   task_eof;
+       struct work_struct      eof_bh_work;
 
        u32                     save_cicr[5];
 };
        clk_disable_unprepare(pcdev->clk);
 }
 
-static void pxa_camera_eof(struct tasklet_struct *t)
+static void pxa_camera_eof_bh_work(struct work_struct *t)
 {
-       struct pxa_camera_dev *pcdev = from_tasklet(pcdev, t, task_eof);
+       struct pxa_camera_dev *pcdev = from_work(pcdev, t, eof_bh_work);
        unsigned long cifr;
        struct pxa_buffer *buf;
 
        if (status & CISR_EOF) {
                cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_EOFM;
                __raw_writel(cicr0, pcdev->base + CICR0);
-               tasklet_schedule(&pcdev->task_eof);
+               queue_work(system_bh_wq, &pcdev->eof_bh_work);
        }
 
        return IRQ_HANDLED;
                }
        }
 
-       tasklet_setup(&pcdev->task_eof, pxa_camera_eof);
+       INIT_WORK(&pcdev->eof_bh_work, pxa_camera_eof_bh_work);
 
        pxa_camera_activate(pcdev);
 
        return 0;
 exit_deactivate:
        pxa_camera_deactivate(pcdev);
-       tasklet_kill(&pcdev->task_eof);
+       cancel_work_sync(&pcdev->eof_bh_work);
 exit_free_dma:
        dma_release_channel(pcdev->dma_chans[2]);
 exit_free_dma_u:
        struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
 
        pxa_camera_deactivate(pcdev);
-       tasklet_kill(&pcdev->task_eof);
+       cancel_work_sync(&pcdev->eof_bh_work);
        dma_release_channel(pcdev->dma_chans[0]);
        dma_release_channel(pcdev->dma_chans[1]);
        dma_release_channel(pcdev->dma_chans[2]);
 
 /*
  * Copy data out to user space in the vmalloc case
  */
-static void mcam_frame_tasklet(struct tasklet_struct *t)
+static void mcam_frame_work(struct work_struct *t)
 {
-       struct mcam_camera *cam = from_tasklet(cam, t, s_tasklet);
+       struct mcam_camera *cam = from_work(cam, t, s_bh_work);
        int i;
        unsigned long flags;
        struct mcam_vb_buffer *buf;
 
 static void mcam_vmalloc_done(struct mcam_camera *cam, int frame)
 {
-       tasklet_schedule(&cam->s_tasklet);
+       queue_work(system_bh_wq, &cam->s_bh_work);
 }
 
 #else /* MCAM_MODE_VMALLOC */
                break;
        case B_vmalloc:
 #ifdef MCAM_MODE_VMALLOC
-               tasklet_setup(&cam->s_tasklet, mcam_frame_tasklet);
+               INIT_WORK(&cam->s_bh_work, mcam_frame_work);
                vq->ops = &mcam_vb2_ops;
                vq->mem_ops = &vb2_vmalloc_memops;
                cam->dma_setup = mcam_ctlr_dma_vmalloc;
 
 
 #include <linux/list.h>
 #include <linux/clk-provider.h>
+#include <linux/workqueue.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-dev.h>
        unsigned int dma_buf_size;      /* allocated size */
        void *dma_bufs[MAX_DMA_BUFS];   /* Internal buffer addresses */
        dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */
-       struct tasklet_struct s_tasklet;
+       struct work_struct s_bh_work;
 #endif
        unsigned int sequence;          /* Frame sequence number */
        unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */
 
 
                /* is this descriptor initialised and TP enabled */
                if (channel->irec && readl(channel->irec + DMA_PRDS_TPENABLE))
-                       tasklet_schedule(&channel->tsklet);
+                       queue_work(system_bh_wq, &channel->bh_work);
        }
 
        fei->timer.expires = jiffies +  msecs_to_jiffies(POLL_MSECS);
        add_timer(&fei->timer);
 }
 
-static void channel_swdemux_tsklet(struct tasklet_struct *t)
+static void channel_swdemux_bh_work(struct work_struct *t)
 {
-       struct channel_info *channel = from_tasklet(channel, t, tsklet);
+       struct channel_info *channel = from_work(channel, t, bh_work);
        struct c8sectpfei *fei;
        unsigned long wp, rp;
        int pos, num_packets, n, size;
 
                dev_dbg(fei->dev, "Starting channel=%p\n", channel);
 
-               tasklet_setup(&channel->tsklet, channel_swdemux_tsklet);
+               INIT_WORK(&channel->bh_work, channel_swdemux_bh_work);
 
                /* Reset the internal inputblock sram pointers */
                writel(channel->fifo,
                /* disable this channels descriptor */
                writel(0,  channel->irec + DMA_PRDS_TPENABLE);
 
-               tasklet_disable(&channel->tsklet);
+               disable_work_sync(&channel->bh_work);
 
                /* now request memdma channel goes idle */
                idlereq = (1 << channel->tsin_id) | IDLEREQ;
        writel(tsin->back_buffer_busaddr, tsin->irec + DMA_PRDS_BUSWP_TP(0));
        writel(tsin->back_buffer_busaddr, tsin->irec + DMA_PRDS_BUSRP_TP(0));
 
-       /* initialize tasklet */
-       tasklet_setup(&tsin->tsklet, channel_swdemux_tsklet);
+       /* initialize bh work */
+       INIT_WORK(&tsin->bh_work, channel_swdemux_bh_work);
 
        return 0;
 
 
        unsigned long  fifo;
 
        struct completion idle_completion;
-       struct tasklet_struct tsklet;
+       struct work_struct bh_work;
 
        struct c8sectpfei *fei;
        void __iomem *irec;
 
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <linux/timer.h>
+#include <linux/workqueue.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
        int streg_cbdata; /* status of ST registration */
 
        struct sk_buff_head rx_q;       /* RX queue */
-       struct tasklet_struct rx_task;  /* RX Tasklet */
+       struct work_struct rx_bh_work;  /* RX BH Work */
 
        struct sk_buff_head tx_q;       /* TX queue */
-       struct tasklet_struct tx_task;  /* TX Tasklet */
+       struct work_struct tx_bh_work;  /* TX BH Work */
        unsigned long last_tx_jiffies;  /* Timestamp of last pkt sent */
        atomic_t tx_cnt;        /* Number of packets can send at a time */
 
 
  *     one Channel-8 command to be sent to the chip).
  *  2) Sending each Channel-8 command to the chip and reading
  *     response back over Shared Transport.
- *  3) Managing TX and RX Queues and Tasklets.
+ *  3) Managing TX and RX Queues and BH bh Works.
  *  4) Handling FM Interrupt packet and taking appropriate action.
  *  5) Loading FM firmware to the chip (common, FM TX, and FM RX
  *     firmware files based on mode selection)
 }
 
 /*
- * FM common sub-module will schedule this tasklet whenever it receives
+ * FM common sub-module will queue this bh work whenever it receives
  * FM packet from ST driver.
  */
-static void recv_tasklet(struct tasklet_struct *t)
+static void recv_bh_work(struct work_struct *t)
 {
        struct fmdev *fmdev;
        struct fm_irq *irq_info;
        u8 num_fm_hci_cmds;
        unsigned long flags;
 
-       fmdev = from_tasklet(fmdev, t, tx_task);
+       fmdev = from_work(fmdev, t, tx_bh_work);
        irq_info = &fmdev->irq_info;
        /* Process all packets in the RX queue */
        while ((skb = skb_dequeue(&fmdev->rx_q))) {
 
                /*
                 * Check flow control field. If Num_FM_HCI_Commands field is
-                * not zero, schedule FM TX tasklet.
+                * not zero, queue FM TX bh work.
                 */
                if (num_fm_hci_cmds && atomic_read(&fmdev->tx_cnt))
                        if (!skb_queue_empty(&fmdev->tx_q))
-                               tasklet_schedule(&fmdev->tx_task);
+                               queue_work(system_bh_wq, &fmdev->tx_bh_work);
        }
 }
 
-/* FM send tasklet: is scheduled when FM packet has to be sent to chip */
-static void send_tasklet(struct tasklet_struct *t)
+/* FM send_bh_work: is scheduled when FM packet has to be sent to chip */
+static void send_bh_work(struct work_struct *t)
 {
        struct fmdev *fmdev;
        struct sk_buff *skb;
        int len;
 
-       fmdev = from_tasklet(fmdev, t, tx_task);
+       fmdev = from_work(fmdev, t, tx_bh_work);
 
        if (!atomic_read(&fmdev->tx_cnt))
                return;
        if (len < 0) {
                kfree_skb(skb);
                fmdev->resp_comp = NULL;
-               fmerr("TX tasklet failed to send skb(%p)\n", skb);
+               fmerr("TX bh work failed to send skb(%p)\n", skb);
                atomic_set(&fmdev->tx_cnt, 1);
        } else {
                fmdev->last_tx_jiffies = jiffies;
 }
 
 /*
- * Queues FM Channel-8 packet to FM TX queue and schedules FM TX tasklet for
+ * Queues FM Channel-8 packet to FM TX queue and schedules FM TX bh work for
  * transmission
  */
 static int fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type,        void *payload,
 
        fm_cb(skb)->completion = wait_completion;
        skb_queue_tail(&fmdev->tx_q, skb);
-       tasklet_schedule(&fmdev->tx_task);
+       queue_work(system_bh_wq, &fmdev->tx_bh_work);
 
        return 0;
 }
 
        if (!wait_for_completion_timeout(&fmdev->maintask_comp,
                                         FM_DRV_TX_TIMEOUT)) {
-               fmerr("Timeout(%d sec),didn't get regcompletion signal from RX tasklet\n",
+               fmerr("Timeout(%d sec),didn't get regcompletion signal from RX bh work\n",
                           jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
                return -ETIMEDOUT;
        }
 
        memcpy(skb_push(skb, 1), &skb->cb[0], 1);
        skb_queue_tail(&fmdev->rx_q, skb);
-       tasklet_schedule(&fmdev->rx_task);
+       queue_work(system_bh_wq, &fmdev->rx_bh_work);
 
        return 0;
 }
        spin_lock_init(&fmdev->rds_buff_lock);
        spin_lock_init(&fmdev->resp_skb_lock);
 
-       /* Initialize TX queue and TX tasklet */
+       /* Initialize TX queue and TX bh work */
        skb_queue_head_init(&fmdev->tx_q);
-       tasklet_setup(&fmdev->tx_task, send_tasklet);
+       INIT_WORK(&fmdev->tx_bh_work, send_bh_work);
 
-       /* Initialize RX Queue and RX tasklet */
+       /* Initialize RX Queue and RX bh work */
        skb_queue_head_init(&fmdev->rx_q);
-       tasklet_setup(&fmdev->rx_task, recv_tasklet);
+       INIT_WORK(&fmdev->rx_bh_work, recv_bh_work);
 
        fmdev->irq_info.stage = 0;
        atomic_set(&fmdev->tx_cnt, 1);
        /* Service pending read */
        wake_up_interruptible(&fmdev->rx.rds.read_queue);
 
-       tasklet_kill(&fmdev->tx_task);
-       tasklet_kill(&fmdev->rx_task);
+       cancel_work_sync(&fmdev->tx_bh_work);
+       cancel_work_sync(&fmdev->rx_bh_work);
 
        skb_queue_purge(&fmdev->tx_q);
        skb_queue_purge(&fmdev->rx_q);
 
 
 /*
  * Schedule work that can't be done in interrupt handlers
- * (mceusb_dev_recv() and mce_write_callback()) nor tasklets.
+ * (mceusb_dev_recv() and mce_write_callback()) nor BH work.
  * Invokes mceusb_deferred_kevent() for recovering from
  * error events specified by the kevent bit field.
  */
 
 #include <linux/input.h>
 
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #include <media/dmxdev.h>
 #include <media/dvb_demux.h>
        int                     v_pes_postbytes;
 
        struct list_head        urb_frame_list;
-       struct tasklet_struct   urb_tasklet;
+       struct work_struct      urb_bh_work;
        spinlock_t              urb_frame_list_lock;
 
        struct dvb_demux_filter *audio_filter;
        }
 }
 
-static void ttusb_dec_process_urb_frame_list(struct tasklet_struct *t)
+static void ttusb_dec_process_urb_frame_list(struct work_struct *t)
 {
-       struct ttusb_dec *dec = from_tasklet(dec, t, urb_tasklet);
+       struct ttusb_dec *dec = from_work(dec, t, urb_bh_work);
        struct list_head *item;
        struct urb_frame *frame;
        unsigned long flags;
                                spin_unlock_irqrestore(&dec->urb_frame_list_lock,
                                                       flags);
 
-                               tasklet_schedule(&dec->urb_tasklet);
+                               queue_work(system_bh_wq, &dec->urb_bh_work);
                        }
                }
        } else {
        return 0;
 }
 
-static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
+static void ttusb_dec_init_bh_work(struct ttusb_dec *dec)
 {
        spin_lock_init(&dec->urb_frame_list_lock);
        INIT_LIST_HEAD(&dec->urb_frame_list);
-       tasklet_setup(&dec->urb_tasklet, ttusb_dec_process_urb_frame_list);
+       INIT_WORK(&dec->urb_bh_work, ttusb_dec_process_urb_frame_list);
 }
 
 static int ttusb_init_rc( struct ttusb_dec *dec)
        ttusb_dec_free_iso_urbs(dec);
 }
 
-static void ttusb_dec_exit_tasklet(struct ttusb_dec *dec)
+static void ttusb_dec_exit_bh_work(struct ttusb_dec *dec)
 {
        struct list_head *item;
        struct urb_frame *frame;
 
-       tasklet_kill(&dec->urb_tasklet);
+       cancel_work_sync(&dec->urb_bh_work);
 
        while ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) {
                frame = list_entry(item, struct urb_frame, urb_frame_list);
 
        ttusb_dec_init_v_pes(dec);
        ttusb_dec_init_filters(dec);
-       ttusb_dec_init_tasklet(dec);
+       ttusb_dec_init_bh_work(dec);
 
        dec->active = 1;
 
        dprintk("%s\n", __func__);
 
        if (dec->active) {
-               ttusb_dec_exit_tasklet(dec);
+               ttusb_dec_exit_bh_work(dec);
                ttusb_dec_exit_filters(dec);
                if(enable_rc)
                        ttusb_dec_exit_rc(dec);