Message ID | 20240612235006.211471-1-allen.lkml@gmail.com |
---|---|
State | Superseded |
Headers | show |
Series | [v4] media: Convert from tasklet to BH workqueue | expand |
Hi Allen, On 13/06/2024 01:50, Allen Pais wrote: > The only generic interface to execute asynchronously in the BH context is > tasklet; however, it's marked deprecated and has some design flaws. To > replace tasklets, BH workqueue support was recently added. A BH workqueue > behaves similarly to regular workqueues except that the queued work items > are executed in the BH context. > > This patch converts drivers/media/* from tasklet to BH workqueue. > > Based on the work done by Tejun Heo <tj@kernel.org> > > Signed-off-by: Allen Pais <allen.lkml@gmail.com> > --- > > v4: > - fixed styling issues. > - rename work to bh_work [Hans Verkuil] I noticed that there are still places where 'work' is used instead of 'bh_work'. See below. Otherwise this builds fine and looks good. So I expect to be able to merge v5. > - Fixed mantis build failure [Hans Verkuil] > > v3: > https://lore.kernel.org/all/20240425183127.11409-1-apais@linux.microsoft.com/ > > v2: > https://lore.kernel.org/all/20240327160314.9982-9-apais@linux.microsoft.com/ > > drivers/media/pci/bt8xx/bt878.c | 8 ++-- > drivers/media/pci/bt8xx/bt878.h | 3 +- > drivers/media/pci/bt8xx/dvb-bt8xx.c | 9 +++-- > drivers/media/pci/ddbridge/ddbridge.h | 2 +- > drivers/media/pci/mantis/hopper_cards.c | 2 +- > drivers/media/pci/mantis/mantis_cards.c | 2 +- > drivers/media/pci/mantis/mantis_common.h | 2 +- > drivers/media/pci/mantis/mantis_dma.c | 4 +- > drivers/media/pci/mantis/mantis_dma.h | 2 +- > drivers/media/pci/mantis/mantis_dvb.c | 12 +++--- > drivers/media/pci/ngene/ngene-core.c | 22 +++++----- > drivers/media/pci/ngene/ngene.h | 5 ++- > drivers/media/pci/smipcie/smipcie-main.c | 18 ++++----- > drivers/media/pci/smipcie/smipcie.h | 3 +- > drivers/media/pci/ttpci/budget-av.c | 3 +- > drivers/media/pci/ttpci/budget-ci.c | 27 +++++++------ > drivers/media/pci/ttpci/budget-core.c | 10 ++--- > drivers/media/pci/ttpci/budget.h | 5 ++- > drivers/media/pci/tw5864/tw5864-core.c | 2 +- > drivers/media/pci/tw5864/tw5864-video.c | 13 +++--- > drivers/media/pci/tw5864/tw5864.h | 7 ++-- > drivers/media/platform/intel/pxa_camera.c | 15 +++---- > drivers/media/platform/marvell/mcam-core.c | 8 ++-- > drivers/media/platform/marvell/mcam-core.h | 3 +- > .../st/sti/c8sectpfe/c8sectpfe-core.c | 14 +++---- > .../st/sti/c8sectpfe/c8sectpfe-core.h | 2 +- > drivers/media/radio/wl128x/fmdrv.h | 5 ++- > drivers/media/radio/wl128x/fmdrv_common.c | 40 +++++++++---------- > drivers/media/rc/mceusb.c | 2 +- > drivers/media/usb/ttusb-dec/ttusb_dec.c | 21 +++++----- > 30 files changed, 142 insertions(+), 129 deletions(-) > > diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c > index 90972d6952f1..dedf82b76e28 100644 > --- a/drivers/media/pci/bt8xx/bt878.c > +++ b/drivers/media/pci/bt8xx/bt878.c > @@ -300,8 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id) > } > 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++; > @@ -478,8 +478,8 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) > 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; > > diff --git a/drivers/media/pci/bt8xx/bt878.h b/drivers/media/pci/bt8xx/bt878.h > index fde8db293c54..5b1c7f56e553 100644 > --- a/drivers/media/pci/bt8xx/bt878.h > +++ b/drivers/media/pci/bt8xx/bt878.h > @@ -14,6 +14,7 @@ > #include <linux/sched.h> > #include <linux/spinlock.h> > #include <linux/mutex.h> > +#include <linux/workqueue.h> > > #include "bt848.h" > #include "bttv.h" > @@ -120,7 +121,7 @@ struct bt878 { > dma_addr_t risc_dma; > u32 risc_pos; > > - struct tasklet_struct tasklet; > + struct work_struct bh_work; > int shutdown; > }; > > diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c > index 390cbba6c065..45074af3de66 100644 > --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c > +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c > @@ -15,6 +15,7 @@ > #include <linux/delay.h> > #include <linux/slab.h> > #include <linux/i2c.h> > +#include <linux/workqueue.h> > > #include <media/dmxdev.h> > #include <media/dvbdev.h> > @@ -39,9 +40,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); > > #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); > @@ -782,7 +783,7 @@ static int dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) > 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); > > @@ -922,7 +923,7 @@ static void dvb_bt8xx_remove(struct bttv_sub_device *sub) > 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); > diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h > index f3699dbd193f..f01ecdb0b627 100644 > --- a/drivers/media/pci/ddbridge/ddbridge.h > +++ b/drivers/media/pci/ddbridge/ddbridge.h > @@ -298,7 +298,7 @@ struct ddb_link { > 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 */ > diff --git a/drivers/media/pci/mantis/hopper_cards.c b/drivers/media/pci/mantis/hopper_cards.c > index c0bd5d7e148b..b85aef4e2b24 100644 > --- a/drivers/media/pci/mantis/hopper_cards.c > +++ b/drivers/media/pci/mantis/hopper_cards.c > @@ -116,7 +116,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id) > 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]); > diff --git a/drivers/media/pci/mantis/mantis_cards.c b/drivers/media/pci/mantis/mantis_cards.c > index 906e4500d87d..b44b4cf42f86 100644 > --- a/drivers/media/pci/mantis/mantis_cards.c > +++ b/drivers/media/pci/mantis/mantis_cards.c > @@ -125,7 +125,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id) > 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]); > diff --git a/drivers/media/pci/mantis/mantis_common.h b/drivers/media/pci/mantis/mantis_common.h > index d88ac280226c..6e563ecd94e8 100644 > --- a/drivers/media/pci/mantis/mantis_common.h > +++ b/drivers/media/pci/mantis/mantis_common.h > @@ -125,7 +125,7 @@ struct mantis_pci { > __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; > diff --git a/drivers/media/pci/mantis/mantis_dma.c b/drivers/media/pci/mantis/mantis_dma.c > index 80c843936493..eeb210a2862f 100644 > --- a/drivers/media/pci/mantis/mantis_dma.c > +++ b/drivers/media/pci/mantis/mantis_dma.c > @@ -200,9 +200,9 @@ void mantis_dma_stop(struct mantis_pci *mantis) > } > > > -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) { > diff --git a/drivers/media/pci/mantis/mantis_dma.h b/drivers/media/pci/mantis/mantis_dma.h > index 37da982c9c29..5db0d3728f15 100644 > --- a/drivers/media/pci/mantis/mantis_dma.h > +++ b/drivers/media/pci/mantis/mantis_dma.h > @@ -13,6 +13,6 @@ extern int mantis_dma_init(struct mantis_pci *mantis); > 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 */ > diff --git a/drivers/media/pci/mantis/mantis_dvb.c b/drivers/media/pci/mantis/mantis_dvb.c > index c7ba4a76e608..398e32f44692 100644 > --- a/drivers/media/pci/mantis/mantis_dvb.c > +++ b/drivers/media/pci/mantis/mantis_dvb.c > @@ -105,7 +105,7 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) > 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; > @@ -125,7 +125,7 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) > 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); > } > > @@ -205,8 +205,8 @@ int mantis_dvb_init(struct mantis_pci *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) { > @@ -235,7 +235,7 @@ int mantis_dvb_init(struct mantis_pci *mantis) > > /* 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); > @@ -273,7 +273,7 @@ int mantis_dvb_exit(struct mantis_pci *mantis) > 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); > diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c > index 24ec576dc3bf..9641f23b2247 100644 > --- a/drivers/media/pci/ngene/ngene-core.c > +++ b/drivers/media/pci/ngene/ngene-core.c > @@ -50,9 +50,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); > /* 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 = > @@ -68,9 +68,9 @@ static void event_tasklet(struct tasklet_struct *t) > } > } > > -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; > > @@ -204,7 +204,7 @@ static irqreturn_t irq_handler(int irq, void *dev_id) > dev->EventQueueOverflowFlag = 1; > } > dev->EventBuffer->EventStatus &= ~0x80; > - tasklet_schedule(&dev->event_tasklet); > + queue_work(system_bh_wq, &dev->event_bh_work); > rc = IRQ_HANDLED; > } > > @@ -217,8 +217,8 @@ static irqreturn_t irq_handler(int irq, void *dev_id) > 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; > } > } > @@ -1181,7 +1181,7 @@ static void ngene_init(struct ngene *dev) > 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); > @@ -1395,7 +1395,7 @@ static void release_channel(struct ngene_channel *chan) > 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); > @@ -1445,7 +1445,7 @@ static int init_channel(struct ngene_channel *chan) > 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 */ > @@ -1649,7 +1649,7 @@ void ngene_remove(struct pci_dev *pdev) > 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) > diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h > index d1d7da84cd9d..9f989420b9e7 100644 > --- a/drivers/media/pci/ngene/ngene.h > +++ b/drivers/media/pci/ngene/ngene.h > @@ -16,6 +16,7 @@ > #include <linux/scatterlist.h> > > #include <linux/dvb/frontend.h> > +#include <linux/workqueue.h> > > #include <media/dmxdev.h> > #include <media/dvbdev.h> > @@ -621,7 +622,7 @@ struct ngene_channel { > 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; > @@ -717,7 +718,7 @@ struct ngene { > 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; > diff --git a/drivers/media/pci/smipcie/smipcie-main.c b/drivers/media/pci/smipcie/smipcie-main.c > index 0c300d019d9c..7db6d443fc54 100644 > --- a/drivers/media/pci/smipcie/smipcie-main.c > +++ b/drivers/media/pci/smipcie/smipcie-main.c > @@ -279,10 +279,10 @@ static void smi_port_clearInterrupt(struct smi_port *port) > (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; > @@ -426,8 +426,8 @@ static int smi_port_init(struct smi_port *port, int dmaChanUsed) > } > > 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: > @@ -438,7 +438,7 @@ static int smi_port_init(struct smi_port *port, int dmaChanUsed) > 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; > } > @@ -452,7 +452,7 @@ static int smi_port_irq(struct smi_port *port, u32 int_status) > 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; > @@ -823,7 +823,7 @@ static int smi_start_feed(struct dvb_demux_feed *dvbdmxfeed) > 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; > } > @@ -837,7 +837,7 @@ static int smi_stop_feed(struct dvb_demux_feed *dvbdmxfeed) > 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; > diff --git a/drivers/media/pci/smipcie/smipcie.h b/drivers/media/pci/smipcie/smipcie.h > index 2b5e0154814c..98e44edaab9e 100644 > --- a/drivers/media/pci/smipcie/smipcie.h > +++ b/drivers/media/pci/smipcie/smipcie.h > @@ -17,6 +17,7 @@ > #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> > @@ -257,7 +258,7 @@ struct smi_port { > 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; > diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c > index 2e62c938e2cb..dd915bf5d2a4 100644 > --- a/drivers/media/pci/ttpci/budget-av.c > +++ b/drivers/media/pci/ttpci/budget-av.c > @@ -36,6 +36,7 @@ > #include <linux/interrupt.h> > #include <linux/input.h> > #include <linux/spinlock.h> > +#include <linux/workqueue.h> > > #include <media/dvb_ca_en50221.h> > > @@ -54,7 +55,7 @@ struct budget_av { > struct video_device vd; > int cur_input; > int has_saa7113; > - struct tasklet_struct ciintf_irq_tasklet; > + struct work_struct ciintf_irq_work; ciintf_irq_work -> ciintf_irq_bh_work > int slot_status; > struct dvb_ca_en50221 ca; > u8 reinitialise_demod:1; > diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c > index 76de40e3c802..8187e26a0b3d 100644 > --- a/drivers/media/pci/ttpci/budget-ci.c > +++ b/drivers/media/pci/ttpci/budget-ci.c > @@ -18,6 +18,7 @@ > #include <linux/slab.h> > #include <linux/interrupt.h> > #include <linux/spinlock.h> > +#include <linux/workqueue.h> > #include <media/rc-core.h> > > #include "budget.h" > @@ -81,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); > > struct budget_ci_ir { > struct rc_dev *dev; > - struct tasklet_struct msp430_irq_tasklet; > + struct work_struct msp430_irq_work; msp430_irq_bh_work > char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ > char phys[32]; > int rc5_device; > @@ -92,7 +93,7 @@ struct budget_ci_ir { > > struct budget_ci { > struct budget budget; > - struct tasklet_struct ciintf_irq_tasklet; > + struct work_struct ciintf_irq_work; ciintf_irq_bh_work > int slot_status; > int ci_irq; > struct dvb_ca_en50221 ca; > @@ -100,9 +101,9 @@ struct budget_ci { > 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_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; > @@ -231,7 +232,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) > > budget_ci->ir.dev = dev; > > - tasklet_setup(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt); > + INIT_WORK(&budget_ci->ir.msp430_irq_work, msp430_ir_interrupt); > > SAA7146_IER_ENABLE(saa, MASK_06); > saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); > @@ -245,7 +246,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) > > 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_work); > > rc_unregister_device(budget_ci->ir.dev); > } > @@ -349,10 +350,10 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) > 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_work); > struct saa7146_dev *saa = budget_ci->budget.dev; > unsigned int flags; > > @@ -491,7 +492,7 @@ static int ciintf_init(struct budget_ci *budget_ci) > > // Setup CI slot IRQ > if (budget_ci->ci_irq) { > - tasklet_setup(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt); > + INIT_WORK(&budget_ci->ciintf_irq_work, ciintf_interrupt); > if (budget_ci->slot_status != SLOTSTATUS_NONE) > saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); > else > @@ -530,7 +531,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) > 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_work); > } > > // reset interface > @@ -556,13 +557,13 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 *isr) > 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_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_work); > } > > static u8 philips_su1278_tt_inittab[] = { > diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c > index d33adeca196f..ebcae1baedfe 100644 > --- a/drivers/media/pci/ttpci/budget-core.c > +++ b/drivers/media/pci/ttpci/budget-core.c > @@ -172,9 +172,9 @@ static int budget_read_fe_status(struct dvb_frontend *fe, > 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_work); > u8 *mem = (u8 *) (budget->grabbing); > u32 olddma = budget->ttbp; > u32 newdma = saa7146_read(budget->dev, PCI_VDP3); > @@ -525,7 +525,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, > /* upload all */ > saa7146_write(dev, GPIO_CTRL, 0x000000); > > - tasklet_setup(&budget->vpe_tasklet, vpeirq); > + INIT_WORK(&budget->vpe_work, vpeirq); > > /* frontend power on */ > if (bi->type != BUDGET_FS_ACTIVY) > @@ -565,7 +565,7 @@ int ttpci_budget_deinit(struct budget *budget) > > budget_unregister(budget); > > - tasklet_kill(&budget->vpe_tasklet); > + cancel_work_sync(&budget->vpe_work); > > saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt); > > @@ -584,7 +584,7 @@ void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 *isr) > 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_work); > } > EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); > > diff --git a/drivers/media/pci/ttpci/budget.h b/drivers/media/pci/ttpci/budget.h > index 83ead34dc766..54bf96a2f5b5 100644 > --- a/drivers/media/pci/ttpci/budget.h > +++ b/drivers/media/pci/ttpci/budget.h > @@ -18,6 +18,7 @@ > > #include <linux/module.h> > #include <linux/mutex.h> > +#include <linux/workqueue.h> > > #include <media/drv-intf/saa7146.h> > > @@ -54,8 +55,8 @@ struct budget { > unsigned char *grabbing; > struct saa7146_pgtable pt; > > - struct tasklet_struct fidb_tasklet; > - struct tasklet_struct vpe_tasklet; > + struct work_struct fidb_work; fidb_bh_work > + struct work_struct vpe_work; vpe_bh_work > > struct dmxdev dmxdev; > struct dvb_demux demux; > diff --git a/drivers/media/pci/tw5864/tw5864-core.c b/drivers/media/pci/tw5864/tw5864-core.c > index 560ff1ddcc83..4d33caf83307 100644 > --- a/drivers/media/pci/tw5864/tw5864-core.c > +++ b/drivers/media/pci/tw5864/tw5864-core.c > @@ -144,7 +144,7 @@ static void tw5864_h264_isr(struct tw5864_dev *dev) > 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; > > diff --git a/drivers/media/pci/tw5864/tw5864-video.c b/drivers/media/pci/tw5864/tw5864-video.c > index 8b1aae4b6319..4f35c159efe5 100644 > --- a/drivers/media/pci/tw5864/tw5864-video.c > +++ b/drivers/media/pci/tw5864/tw5864-video.c > @@ -6,6 +6,7 @@ > */ > > #include <linux/module.h> > +#include <linux/workqueue.h> > #include <media/v4l2-common.h> > #include <media/v4l2-event.h> > #include <media/videobuf2-dma-contig.h> > @@ -175,7 +176,7 @@ static const unsigned int intra4x4_lambda3[] = { > 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); > > @@ -1062,7 +1063,7 @@ int tw5864_video_init(struct tw5864_dev *dev, int *video_nr) > 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; > @@ -1079,7 +1080,7 @@ int tw5864_video_init(struct tw5864_dev *dev, int *video_nr) > 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--) { > @@ -1198,7 +1199,7 @@ void tw5864_video_fini(struct tw5864_dev *dev) > { > 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]); > @@ -1315,9 +1316,9 @@ static int tw5864_is_motion_triggered(struct tw5864_h264_frame *frame) > 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; > > diff --git a/drivers/media/pci/tw5864/tw5864.h b/drivers/media/pci/tw5864/tw5864.h > index a8b6fbd5b710..2da5f4215fd9 100644 > --- a/drivers/media/pci/tw5864/tw5864.h > +++ b/drivers/media/pci/tw5864/tw5864.h > @@ -12,6 +12,7 @@ > #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> > @@ -85,7 +86,7 @@ struct tw5864_input { > 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; > @@ -142,7 +143,7 @@ struct tw5864_h264_frame { > > /* 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 > @@ -150,7 +151,7 @@ struct tw5864_dev { > 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) */ > diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c > index d904952bf00e..f118aaac0b38 100644 > --- a/drivers/media/platform/intel/pxa_camera.c > +++ b/drivers/media/platform/intel/pxa_camera.c > @@ -43,6 +43,7 @@ > #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" > @@ -683,7 +684,7 @@ struct pxa_camera_dev { > unsigned int buf_sequence; > > struct pxa_buffer *active; > - struct tasklet_struct task_eof; > + struct work_struct eof_bh_work; > > u32 save_cicr[5]; > }; > @@ -1146,9 +1147,9 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) > 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; > > @@ -1185,7 +1186,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) > 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; > @@ -2383,7 +2384,7 @@ static int pxa_camera_probe(struct platform_device *pdev) > } > } > > - tasklet_setup(&pcdev->task_eof, pxa_camera_eof); > + INIT_WORK(&pcdev->eof_bh_work, pxa_camera_eof_bh_work); > > pxa_camera_activate(pcdev); > > @@ -2409,7 +2410,7 @@ static int pxa_camera_probe(struct platform_device *pdev) > 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: > @@ -2428,7 +2429,7 @@ static void pxa_camera_remove(struct platform_device *pdev) > 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]); > diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c > index 66688b4aece5..fa7ebf2fcfac 100644 > --- a/drivers/media/platform/marvell/mcam-core.c > +++ b/drivers/media/platform/marvell/mcam-core.c > @@ -439,9 +439,9 @@ static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam) > /* > * 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_work); > int i; > unsigned long flags; > struct mcam_vb_buffer *buf; > @@ -493,7 +493,7 @@ static int mcam_check_dma_buffers(struct mcam_camera *cam) > > static void mcam_vmalloc_done(struct mcam_camera *cam, int frame) > { > - tasklet_schedule(&cam->s_tasklet); > + queue_work(system_bh_wq, &cam->s_work); > } > > #else /* MCAM_MODE_VMALLOC */ > @@ -1305,7 +1305,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam) > break; > case B_vmalloc: > #ifdef MCAM_MODE_VMALLOC > - tasklet_setup(&cam->s_tasklet, mcam_frame_tasklet); > + INIT_WORK(&cam->s_work, mcam_frame_work); > vq->ops = &mcam_vb2_ops; > vq->mem_ops = &vb2_vmalloc_memops; > cam->dma_setup = mcam_ctlr_dma_vmalloc; > diff --git a/drivers/media/platform/marvell/mcam-core.h b/drivers/media/platform/marvell/mcam-core.h > index 51e66db45af6..0d4b953dbb23 100644 > --- a/drivers/media/platform/marvell/mcam-core.h > +++ b/drivers/media/platform/marvell/mcam-core.h > @@ -9,6 +9,7 @@ > > #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> > @@ -167,7 +168,7 @@ struct mcam_camera { > 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_work; s_bh_work > #endif > unsigned int sequence; /* Frame sequence number */ > unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */ > diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c > index 2f58a0d0df85..7bbb26a5b366 100644 > --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c > +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c > @@ -72,16 +72,16 @@ static void c8sectpfe_timer_interrupt(struct timer_list *t) > > /* 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; > @@ -210,7 +210,7 @@ static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed) > > 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, > @@ -303,7 +303,7 @@ static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed) > /* 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; > @@ -630,8 +630,8 @@ static int configure_memdma_and_inputblock(struct c8sectpfei *fei, > 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 work */ > + INIT_WORK(&tsin->bh_work, channel_swdemux_bh_work); > > return 0; > > diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h > index bf377cc82225..c1b124c6ef12 100644 > --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h > +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h > @@ -51,7 +51,7 @@ struct channel_info { > unsigned long fifo; > > struct completion idle_completion; > - struct tasklet_struct tsklet; > + struct work_struct bh_work; > > struct c8sectpfei *fei; > void __iomem *irec; > diff --git a/drivers/media/radio/wl128x/fmdrv.h b/drivers/media/radio/wl128x/fmdrv.h > index da8920169df8..03117a41dbd4 100644 > --- a/drivers/media/radio/wl128x/fmdrv.h > +++ b/drivers/media/radio/wl128x/fmdrv.h > @@ -15,6 +15,7 @@ > #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> > @@ -200,10 +201,10 @@ struct fmdev { > 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 */ > > diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c > index 3da8e5102bec..37ed1ed664e0 100644 > --- a/drivers/media/radio/wl128x/fmdrv_common.c > +++ b/drivers/media/radio/wl128x/fmdrv_common.c > @@ -9,7 +9,7 @@ > * 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 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) > @@ -244,10 +244,10 @@ void fmc_update_region_info(struct fmdev *fmdev, u8 region_to_set) > } > > /* > - * FM common sub-module will schedule this tasklet whenever it receives > + * FM common sub-module will queue this 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; > @@ -256,7 +256,7 @@ static void recv_tasklet(struct tasklet_struct *t) > 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))) { > @@ -322,22 +322,22 @@ static void recv_tasklet(struct tasklet_struct *t) > > /* > * Check flow control field. If Num_FM_HCI_Commands field is > - * not zero, schedule FM TX tasklet. > + * not zero, queue FM TX 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; > @@ -366,7 +366,7 @@ static void send_tasklet(struct tasklet_struct *t) > if (len < 0) { > kfree_skb(skb); > fmdev->resp_comp = NULL; > - fmerr("TX tasklet failed to send skb(%p)\n", skb); > + fmerr("TX work failed to send skb(%p)\n", skb); > atomic_set(&fmdev->tx_cnt, 1); > } else { > fmdev->last_tx_jiffies = jiffies; > @@ -374,7 +374,7 @@ static void send_tasklet(struct tasklet_struct *t) > } > > /* > - * 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 work for > * transmission > */ > static int fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload, > @@ -440,7 +440,7 @@ 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; > } > @@ -462,7 +462,7 @@ int fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload, > > 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 work\n", > jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000); > return -ETIMEDOUT; > } > @@ -1455,7 +1455,7 @@ static long fm_st_receive(void *arg, struct sk_buff *skb) > > 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; > } > @@ -1537,13 +1537,13 @@ int fmc_prepare(struct fmdev *fmdev) > 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 work */ I noticed that in most comments 'tasklet' is replaced by 'work', but perhaps that should also be 'BH work' (you do that in a few comments). It would be nice if you can go through the patch and update comments where appropriate. It is not a blocker, but it would make it a bit more consistent. > 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 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); > @@ -1589,8 +1589,8 @@ int fmc_release(struct fmdev *fmdev) > /* 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); > diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c > index c76ba24c1f55..01b65451228d 100644 > --- a/drivers/media/rc/mceusb.c > +++ b/drivers/media/rc/mceusb.c > @@ -774,7 +774,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len, > > /* > * 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. > */ > diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c > index 79faa2560613..c8bc84f4aefb 100644 > --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c > +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c > @@ -19,6 +19,7 @@ > #include <linux/input.h> > > #include <linux/mutex.h> > +#include <linux/workqueue.h> > > #include <media/dmxdev.h> > #include <media/dvb_demux.h> > @@ -139,7 +140,7 @@ struct ttusb_dec { > int v_pes_postbytes; > > struct list_head urb_frame_list; > - struct tasklet_struct urb_tasklet; > + struct work_struct urb_work; urb_bh_work > spinlock_t urb_frame_list_lock; > > struct dvb_demux_filter *audio_filter; > @@ -766,9 +767,9 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b, > } > } > > -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_work); > struct list_head *item; > struct urb_frame *frame; > unsigned long flags; > @@ -822,7 +823,7 @@ static void ttusb_dec_process_urb(struct urb *urb) > spin_unlock_irqrestore(&dec->urb_frame_list_lock, > flags); > > - tasklet_schedule(&dec->urb_tasklet); > + queue_work(system_bh_wq, &dec->urb_work); > } > } > } else { > @@ -1198,11 +1199,11 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) > return 0; > } > > -static void ttusb_dec_init_tasklet(struct ttusb_dec *dec) > +static void ttusb_dec_init_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_work, ttusb_dec_process_urb_frame_list); > } > > static int ttusb_init_rc( struct ttusb_dec *dec) > @@ -1588,12 +1589,12 @@ static void ttusb_dec_exit_usb(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_work(struct ttusb_dec *dec) > { > struct list_head *item; > struct urb_frame *frame; > > - tasklet_kill(&dec->urb_tasklet); > + cancel_work_sync(&dec->urb_work); > > while ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) { > frame = list_entry(item, struct urb_frame, urb_frame_list); > @@ -1703,7 +1704,7 @@ static int ttusb_dec_probe(struct usb_interface *intf, > > ttusb_dec_init_v_pes(dec); > ttusb_dec_init_filters(dec); > - ttusb_dec_init_tasklet(dec); > + ttusb_dec_init_work(dec); > > dec->active = 1; > > @@ -1729,7 +1730,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf) > dprintk("%s\n", __func__); > > if (dec->active) { > - ttusb_dec_exit_tasklet(dec); > + ttusb_dec_exit_work(dec); > ttusb_dec_exit_filters(dec); > if(enable_rc) > ttusb_dec_exit_rc(dec); Regards, Hans
> > The only generic interface to execute asynchronously in the BH context is > > tasklet; however, it's marked deprecated and has some design flaws. To > > replace tasklets, BH workqueue support was recently added. A BH workqueue > > behaves similarly to regular workqueues except that the queued work items > > are executed in the BH context. > > > > This patch converts drivers/media/* from tasklet to BH workqueue. > > > > Based on the work done by Tejun Heo <tj@kernel.org> > > > > Signed-off-by: Allen Pais <allen.lkml@gmail.com> > > --- > > > > v4: > > - fixed styling issues. > > - rename work to bh_work [Hans Verkuil] > > I noticed that there are still places where 'work' is used instead of 'bh_work'. > See below. Otherwise this builds fine and looks good. So I expect to be able to > merge v5. > > > - Fixed mantis build failure [Hans Verkuil] > > > > v3: > > https://lore.kernel.org/all/20240425183127.11409-1-apais@linux.microsoft.com/ > > > > v2: > > https://lore.kernel.org/all/20240327160314.9982-9-apais@linux.microsoft.com/ > > > > drivers/media/pci/bt8xx/bt878.c | 8 ++-- > > drivers/media/pci/bt8xx/bt878.h | 3 +- > > drivers/media/pci/bt8xx/dvb-bt8xx.c | 9 +++-- > > drivers/media/pci/ddbridge/ddbridge.h | 2 +- > > drivers/media/pci/mantis/hopper_cards.c | 2 +- > > drivers/media/pci/mantis/mantis_cards.c | 2 +- > > drivers/media/pci/mantis/mantis_common.h | 2 +- > > drivers/media/pci/mantis/mantis_dma.c | 4 +- > > drivers/media/pci/mantis/mantis_dma.h | 2 +- > > drivers/media/pci/mantis/mantis_dvb.c | 12 +++--- > > drivers/media/pci/ngene/ngene-core.c | 22 +++++----- > > drivers/media/pci/ngene/ngene.h | 5 ++- > > drivers/media/pci/smipcie/smipcie-main.c | 18 ++++----- > > drivers/media/pci/smipcie/smipcie.h | 3 +- > > drivers/media/pci/ttpci/budget-av.c | 3 +- > > drivers/media/pci/ttpci/budget-ci.c | 27 +++++++------ > > drivers/media/pci/ttpci/budget-core.c | 10 ++--- > > drivers/media/pci/ttpci/budget.h | 5 ++- > > drivers/media/pci/tw5864/tw5864-core.c | 2 +- > > drivers/media/pci/tw5864/tw5864-video.c | 13 +++--- > > drivers/media/pci/tw5864/tw5864.h | 7 ++-- > > drivers/media/platform/intel/pxa_camera.c | 15 +++---- > > drivers/media/platform/marvell/mcam-core.c | 8 ++-- > > drivers/media/platform/marvell/mcam-core.h | 3 +- > > .../st/sti/c8sectpfe/c8sectpfe-core.c | 14 +++---- > > .../st/sti/c8sectpfe/c8sectpfe-core.h | 2 +- > > drivers/media/radio/wl128x/fmdrv.h | 5 ++- > > drivers/media/radio/wl128x/fmdrv_common.c | 40 +++++++++---------- > > drivers/media/rc/mceusb.c | 2 +- > > drivers/media/usb/ttusb-dec/ttusb_dec.c | 21 +++++----- > > 30 files changed, 142 insertions(+), 129 deletions(-) > > > > diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c > > index 90972d6952f1..dedf82b76e28 100644 > > --- a/drivers/media/pci/bt8xx/bt878.c > > +++ b/drivers/media/pci/bt8xx/bt878.c > > @@ -300,8 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id) > > } > > 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++; > > @@ -478,8 +478,8 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) > > 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; > > > > diff --git a/drivers/media/pci/bt8xx/bt878.h b/drivers/media/pci/bt8xx/bt878.h > > index fde8db293c54..5b1c7f56e553 100644 > > --- a/drivers/media/pci/bt8xx/bt878.h > > +++ b/drivers/media/pci/bt8xx/bt878.h > > @@ -14,6 +14,7 @@ > > #include <linux/sched.h> > > #include <linux/spinlock.h> > > #include <linux/mutex.h> > > +#include <linux/workqueue.h> > > > > #include "bt848.h" > > #include "bttv.h" > > @@ -120,7 +121,7 @@ struct bt878 { > > dma_addr_t risc_dma; > > u32 risc_pos; > > > > - struct tasklet_struct tasklet; > > + struct work_struct bh_work; > > int shutdown; > > }; > > > > diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c > > index 390cbba6c065..45074af3de66 100644 > > --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c > > +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c > > @@ -15,6 +15,7 @@ > > #include <linux/delay.h> > > #include <linux/slab.h> > > #include <linux/i2c.h> > > +#include <linux/workqueue.h> > > > > #include <media/dmxdev.h> > > #include <media/dvbdev.h> > > @@ -39,9 +40,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); > > > > #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); > > @@ -782,7 +783,7 @@ static int dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) > > 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); > > > > @@ -922,7 +923,7 @@ static void dvb_bt8xx_remove(struct bttv_sub_device *sub) > > 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); > > diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h > > index f3699dbd193f..f01ecdb0b627 100644 > > --- a/drivers/media/pci/ddbridge/ddbridge.h > > +++ b/drivers/media/pci/ddbridge/ddbridge.h > > @@ -298,7 +298,7 @@ struct ddb_link { > > 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 */ > > diff --git a/drivers/media/pci/mantis/hopper_cards.c b/drivers/media/pci/mantis/hopper_cards.c > > index c0bd5d7e148b..b85aef4e2b24 100644 > > --- a/drivers/media/pci/mantis/hopper_cards.c > > +++ b/drivers/media/pci/mantis/hopper_cards.c > > @@ -116,7 +116,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id) > > 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]); > > diff --git a/drivers/media/pci/mantis/mantis_cards.c b/drivers/media/pci/mantis/mantis_cards.c > > index 906e4500d87d..b44b4cf42f86 100644 > > --- a/drivers/media/pci/mantis/mantis_cards.c > > +++ b/drivers/media/pci/mantis/mantis_cards.c > > @@ -125,7 +125,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id) > > 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]); > > diff --git a/drivers/media/pci/mantis/mantis_common.h b/drivers/media/pci/mantis/mantis_common.h > > index d88ac280226c..6e563ecd94e8 100644 > > --- a/drivers/media/pci/mantis/mantis_common.h > > +++ b/drivers/media/pci/mantis/mantis_common.h > > @@ -125,7 +125,7 @@ struct mantis_pci { > > __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; > > diff --git a/drivers/media/pci/mantis/mantis_dma.c b/drivers/media/pci/mantis/mantis_dma.c > > index 80c843936493..eeb210a2862f 100644 > > --- a/drivers/media/pci/mantis/mantis_dma.c > > +++ b/drivers/media/pci/mantis/mantis_dma.c > > @@ -200,9 +200,9 @@ void mantis_dma_stop(struct mantis_pci *mantis) > > } > > > > > > -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) { > > diff --git a/drivers/media/pci/mantis/mantis_dma.h b/drivers/media/pci/mantis/mantis_dma.h > > index 37da982c9c29..5db0d3728f15 100644 > > --- a/drivers/media/pci/mantis/mantis_dma.h > > +++ b/drivers/media/pci/mantis/mantis_dma.h > > @@ -13,6 +13,6 @@ extern int mantis_dma_init(struct mantis_pci *mantis); > > 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 */ > > diff --git a/drivers/media/pci/mantis/mantis_dvb.c b/drivers/media/pci/mantis/mantis_dvb.c > > index c7ba4a76e608..398e32f44692 100644 > > --- a/drivers/media/pci/mantis/mantis_dvb.c > > +++ b/drivers/media/pci/mantis/mantis_dvb.c > > @@ -105,7 +105,7 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) > > 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; > > @@ -125,7 +125,7 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) > > 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); > > } > > > > @@ -205,8 +205,8 @@ int mantis_dvb_init(struct mantis_pci *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) { > > @@ -235,7 +235,7 @@ int mantis_dvb_init(struct mantis_pci *mantis) > > > > /* 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); > > @@ -273,7 +273,7 @@ int mantis_dvb_exit(struct mantis_pci *mantis) > > 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); > > diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c > > index 24ec576dc3bf..9641f23b2247 100644 > > --- a/drivers/media/pci/ngene/ngene-core.c > > +++ b/drivers/media/pci/ngene/ngene-core.c > > @@ -50,9 +50,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); > > /* 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 = > > @@ -68,9 +68,9 @@ static void event_tasklet(struct tasklet_struct *t) > > } > > } > > > > -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; > > > > @@ -204,7 +204,7 @@ static irqreturn_t irq_handler(int irq, void *dev_id) > > dev->EventQueueOverflowFlag = 1; > > } > > dev->EventBuffer->EventStatus &= ~0x80; > > - tasklet_schedule(&dev->event_tasklet); > > + queue_work(system_bh_wq, &dev->event_bh_work); > > rc = IRQ_HANDLED; > > } > > > > @@ -217,8 +217,8 @@ static irqreturn_t irq_handler(int irq, void *dev_id) > > 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; > > } > > } > > @@ -1181,7 +1181,7 @@ static void ngene_init(struct ngene *dev) > > 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); > > @@ -1395,7 +1395,7 @@ static void release_channel(struct ngene_channel *chan) > > 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); > > @@ -1445,7 +1445,7 @@ static int init_channel(struct ngene_channel *chan) > > 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 */ > > @@ -1649,7 +1649,7 @@ void ngene_remove(struct pci_dev *pdev) > > 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) > > diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h > > index d1d7da84cd9d..9f989420b9e7 100644 > > --- a/drivers/media/pci/ngene/ngene.h > > +++ b/drivers/media/pci/ngene/ngene.h > > @@ -16,6 +16,7 @@ > > #include <linux/scatterlist.h> > > > > #include <linux/dvb/frontend.h> > > +#include <linux/workqueue.h> > > > > #include <media/dmxdev.h> > > #include <media/dvbdev.h> > > @@ -621,7 +622,7 @@ struct ngene_channel { > > 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; > > @@ -717,7 +718,7 @@ struct ngene { > > 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; > > diff --git a/drivers/media/pci/smipcie/smipcie-main.c b/drivers/media/pci/smipcie/smipcie-main.c > > index 0c300d019d9c..7db6d443fc54 100644 > > --- a/drivers/media/pci/smipcie/smipcie-main.c > > +++ b/drivers/media/pci/smipcie/smipcie-main.c > > @@ -279,10 +279,10 @@ static void smi_port_clearInterrupt(struct smi_port *port) > > (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; > > @@ -426,8 +426,8 @@ static int smi_port_init(struct smi_port *port, int dmaChanUsed) > > } > > > > 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: > > @@ -438,7 +438,7 @@ static int smi_port_init(struct smi_port *port, int dmaChanUsed) > > 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; > > } > > @@ -452,7 +452,7 @@ static int smi_port_irq(struct smi_port *port, u32 int_status) > > 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; > > @@ -823,7 +823,7 @@ static int smi_start_feed(struct dvb_demux_feed *dvbdmxfeed) > > 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; > > } > > @@ -837,7 +837,7 @@ static int smi_stop_feed(struct dvb_demux_feed *dvbdmxfeed) > > 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; > > diff --git a/drivers/media/pci/smipcie/smipcie.h b/drivers/media/pci/smipcie/smipcie.h > > index 2b5e0154814c..98e44edaab9e 100644 > > --- a/drivers/media/pci/smipcie/smipcie.h > > +++ b/drivers/media/pci/smipcie/smipcie.h > > @@ -17,6 +17,7 @@ > > #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> > > @@ -257,7 +258,7 @@ struct smi_port { > > 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; > > diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c > > index 2e62c938e2cb..dd915bf5d2a4 100644 > > --- a/drivers/media/pci/ttpci/budget-av.c > > +++ b/drivers/media/pci/ttpci/budget-av.c > > @@ -36,6 +36,7 @@ > > #include <linux/interrupt.h> > > #include <linux/input.h> > > #include <linux/spinlock.h> > > +#include <linux/workqueue.h> > > > > #include <media/dvb_ca_en50221.h> > > > > @@ -54,7 +55,7 @@ struct budget_av { > > struct video_device vd; > > int cur_input; > > int has_saa7113; > > - struct tasklet_struct ciintf_irq_tasklet; > > + struct work_struct ciintf_irq_work; > > ciintf_irq_work -> ciintf_irq_bh_work > > > int slot_status; > > struct dvb_ca_en50221 ca; > > u8 reinitialise_demod:1; > > diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c > > index 76de40e3c802..8187e26a0b3d 100644 > > --- a/drivers/media/pci/ttpci/budget-ci.c > > +++ b/drivers/media/pci/ttpci/budget-ci.c > > @@ -18,6 +18,7 @@ > > #include <linux/slab.h> > > #include <linux/interrupt.h> > > #include <linux/spinlock.h> > > +#include <linux/workqueue.h> > > #include <media/rc-core.h> > > > > #include "budget.h" > > @@ -81,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); > > > > struct budget_ci_ir { > > struct rc_dev *dev; > > - struct tasklet_struct msp430_irq_tasklet; > > + struct work_struct msp430_irq_work; > > msp430_irq_bh_work > > > char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ > > char phys[32]; > > int rc5_device; > > @@ -92,7 +93,7 @@ struct budget_ci_ir { > > > > struct budget_ci { > > struct budget budget; > > - struct tasklet_struct ciintf_irq_tasklet; > > + struct work_struct ciintf_irq_work; > > ciintf_irq_bh_work > > > int slot_status; > > int ci_irq; > > struct dvb_ca_en50221 ca; > > @@ -100,9 +101,9 @@ struct budget_ci { > > 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_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; > > @@ -231,7 +232,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) > > > > budget_ci->ir.dev = dev; > > > > - tasklet_setup(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt); > > + INIT_WORK(&budget_ci->ir.msp430_irq_work, msp430_ir_interrupt); > > > > SAA7146_IER_ENABLE(saa, MASK_06); > > saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); > > @@ -245,7 +246,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) > > > > 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_work); > > > > rc_unregister_device(budget_ci->ir.dev); > > } > > @@ -349,10 +350,10 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) > > 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_work); > > struct saa7146_dev *saa = budget_ci->budget.dev; > > unsigned int flags; > > > > @@ -491,7 +492,7 @@ static int ciintf_init(struct budget_ci *budget_ci) > > > > // Setup CI slot IRQ > > if (budget_ci->ci_irq) { > > - tasklet_setup(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt); > > + INIT_WORK(&budget_ci->ciintf_irq_work, ciintf_interrupt); > > if (budget_ci->slot_status != SLOTSTATUS_NONE) > > saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); > > else > > @@ -530,7 +531,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) > > 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_work); > > } > > > > // reset interface > > @@ -556,13 +557,13 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 *isr) > > 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_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_work); > > } > > > > static u8 philips_su1278_tt_inittab[] = { > > diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c > > index d33adeca196f..ebcae1baedfe 100644 > > --- a/drivers/media/pci/ttpci/budget-core.c > > +++ b/drivers/media/pci/ttpci/budget-core.c > > @@ -172,9 +172,9 @@ static int budget_read_fe_status(struct dvb_frontend *fe, > > 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_work); > > u8 *mem = (u8 *) (budget->grabbing); > > u32 olddma = budget->ttbp; > > u32 newdma = saa7146_read(budget->dev, PCI_VDP3); > > @@ -525,7 +525,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, > > /* upload all */ > > saa7146_write(dev, GPIO_CTRL, 0x000000); > > > > - tasklet_setup(&budget->vpe_tasklet, vpeirq); > > + INIT_WORK(&budget->vpe_work, vpeirq); > > > > /* frontend power on */ > > if (bi->type != BUDGET_FS_ACTIVY) > > @@ -565,7 +565,7 @@ int ttpci_budget_deinit(struct budget *budget) > > > > budget_unregister(budget); > > > > - tasklet_kill(&budget->vpe_tasklet); > > + cancel_work_sync(&budget->vpe_work); > > > > saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt); > > > > @@ -584,7 +584,7 @@ void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 *isr) > > 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_work); > > } > > EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); > > > > diff --git a/drivers/media/pci/ttpci/budget.h b/drivers/media/pci/ttpci/budget.h > > index 83ead34dc766..54bf96a2f5b5 100644 > > --- a/drivers/media/pci/ttpci/budget.h > > +++ b/drivers/media/pci/ttpci/budget.h > > @@ -18,6 +18,7 @@ > > > > #include <linux/module.h> > > #include <linux/mutex.h> > > +#include <linux/workqueue.h> > > > > #include <media/drv-intf/saa7146.h> > > > > @@ -54,8 +55,8 @@ struct budget { > > unsigned char *grabbing; > > struct saa7146_pgtable pt; > > > > - struct tasklet_struct fidb_tasklet; > > - struct tasklet_struct vpe_tasklet; > > + struct work_struct fidb_work; > > fidb_bh_work > > > + struct work_struct vpe_work; > > vpe_bh_work > > > > > struct dmxdev dmxdev; > > struct dvb_demux demux; > > diff --git a/drivers/media/pci/tw5864/tw5864-core.c b/drivers/media/pci/tw5864/tw5864-core.c > > index 560ff1ddcc83..4d33caf83307 100644 > > --- a/drivers/media/pci/tw5864/tw5864-core.c > > +++ b/drivers/media/pci/tw5864/tw5864-core.c > > @@ -144,7 +144,7 @@ static void tw5864_h264_isr(struct tw5864_dev *dev) > > 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; > > > > diff --git a/drivers/media/pci/tw5864/tw5864-video.c b/drivers/media/pci/tw5864/tw5864-video.c > > index 8b1aae4b6319..4f35c159efe5 100644 > > --- a/drivers/media/pci/tw5864/tw5864-video.c > > +++ b/drivers/media/pci/tw5864/tw5864-video.c > > @@ -6,6 +6,7 @@ > > */ > > > > #include <linux/module.h> > > +#include <linux/workqueue.h> > > #include <media/v4l2-common.h> > > #include <media/v4l2-event.h> > > #include <media/videobuf2-dma-contig.h> > > @@ -175,7 +176,7 @@ static const unsigned int intra4x4_lambda3[] = { > > 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); > > > > @@ -1062,7 +1063,7 @@ int tw5864_video_init(struct tw5864_dev *dev, int *video_nr) > > 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; > > @@ -1079,7 +1080,7 @@ int tw5864_video_init(struct tw5864_dev *dev, int *video_nr) > > 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--) { > > @@ -1198,7 +1199,7 @@ void tw5864_video_fini(struct tw5864_dev *dev) > > { > > 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]); > > @@ -1315,9 +1316,9 @@ static int tw5864_is_motion_triggered(struct tw5864_h264_frame *frame) > > 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; > > > > diff --git a/drivers/media/pci/tw5864/tw5864.h b/drivers/media/pci/tw5864/tw5864.h > > index a8b6fbd5b710..2da5f4215fd9 100644 > > --- a/drivers/media/pci/tw5864/tw5864.h > > +++ b/drivers/media/pci/tw5864/tw5864.h > > @@ -12,6 +12,7 @@ > > #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> > > @@ -85,7 +86,7 @@ struct tw5864_input { > > 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; > > @@ -142,7 +143,7 @@ struct tw5864_h264_frame { > > > > /* 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 > > @@ -150,7 +151,7 @@ struct tw5864_dev { > > 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) */ > > diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c > > index d904952bf00e..f118aaac0b38 100644 > > --- a/drivers/media/platform/intel/pxa_camera.c > > +++ b/drivers/media/platform/intel/pxa_camera.c > > @@ -43,6 +43,7 @@ > > #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" > > @@ -683,7 +684,7 @@ struct pxa_camera_dev { > > unsigned int buf_sequence; > > > > struct pxa_buffer *active; > > - struct tasklet_struct task_eof; > > + struct work_struct eof_bh_work; > > > > u32 save_cicr[5]; > > }; > > @@ -1146,9 +1147,9 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) > > 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; > > > > @@ -1185,7 +1186,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) > > 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; > > @@ -2383,7 +2384,7 @@ static int pxa_camera_probe(struct platform_device *pdev) > > } > > } > > > > - tasklet_setup(&pcdev->task_eof, pxa_camera_eof); > > + INIT_WORK(&pcdev->eof_bh_work, pxa_camera_eof_bh_work); > > > > pxa_camera_activate(pcdev); > > > > @@ -2409,7 +2410,7 @@ static int pxa_camera_probe(struct platform_device *pdev) > > 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: > > @@ -2428,7 +2429,7 @@ static void pxa_camera_remove(struct platform_device *pdev) > > 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]); > > diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c > > index 66688b4aece5..fa7ebf2fcfac 100644 > > --- a/drivers/media/platform/marvell/mcam-core.c > > +++ b/drivers/media/platform/marvell/mcam-core.c > > @@ -439,9 +439,9 @@ static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam) > > /* > > * 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_work); > > int i; > > unsigned long flags; > > struct mcam_vb_buffer *buf; > > @@ -493,7 +493,7 @@ static int mcam_check_dma_buffers(struct mcam_camera *cam) > > > > static void mcam_vmalloc_done(struct mcam_camera *cam, int frame) > > { > > - tasklet_schedule(&cam->s_tasklet); > > + queue_work(system_bh_wq, &cam->s_work); > > } > > > > #else /* MCAM_MODE_VMALLOC */ > > @@ -1305,7 +1305,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam) > > break; > > case B_vmalloc: > > #ifdef MCAM_MODE_VMALLOC > > - tasklet_setup(&cam->s_tasklet, mcam_frame_tasklet); > > + INIT_WORK(&cam->s_work, mcam_frame_work); > > vq->ops = &mcam_vb2_ops; > > vq->mem_ops = &vb2_vmalloc_memops; > > cam->dma_setup = mcam_ctlr_dma_vmalloc; > > diff --git a/drivers/media/platform/marvell/mcam-core.h b/drivers/media/platform/marvell/mcam-core.h > > index 51e66db45af6..0d4b953dbb23 100644 > > --- a/drivers/media/platform/marvell/mcam-core.h > > +++ b/drivers/media/platform/marvell/mcam-core.h > > @@ -9,6 +9,7 @@ > > > > #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> > > @@ -167,7 +168,7 @@ struct mcam_camera { > > 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_work; > > s_bh_work > > > #endif > > unsigned int sequence; /* Frame sequence number */ > > unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */ > > diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c > > index 2f58a0d0df85..7bbb26a5b366 100644 > > --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c > > +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c > > @@ -72,16 +72,16 @@ static void c8sectpfe_timer_interrupt(struct timer_list *t) > > > > /* 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; > > @@ -210,7 +210,7 @@ static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed) > > > > 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, > > @@ -303,7 +303,7 @@ static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed) > > /* 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; > > @@ -630,8 +630,8 @@ static int configure_memdma_and_inputblock(struct c8sectpfei *fei, > > 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 work */ > > + INIT_WORK(&tsin->bh_work, channel_swdemux_bh_work); > > > > return 0; > > > > diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h > > index bf377cc82225..c1b124c6ef12 100644 > > --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h > > +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h > > @@ -51,7 +51,7 @@ struct channel_info { > > unsigned long fifo; > > > > struct completion idle_completion; > > - struct tasklet_struct tsklet; > > + struct work_struct bh_work; > > > > struct c8sectpfei *fei; > > void __iomem *irec; > > diff --git a/drivers/media/radio/wl128x/fmdrv.h b/drivers/media/radio/wl128x/fmdrv.h > > index da8920169df8..03117a41dbd4 100644 > > --- a/drivers/media/radio/wl128x/fmdrv.h > > +++ b/drivers/media/radio/wl128x/fmdrv.h > > @@ -15,6 +15,7 @@ > > #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> > > @@ -200,10 +201,10 @@ struct fmdev { > > 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 */ > > > > diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c > > index 3da8e5102bec..37ed1ed664e0 100644 > > --- a/drivers/media/radio/wl128x/fmdrv_common.c > > +++ b/drivers/media/radio/wl128x/fmdrv_common.c > > @@ -9,7 +9,7 @@ > > * 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 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) > > @@ -244,10 +244,10 @@ void fmc_update_region_info(struct fmdev *fmdev, u8 region_to_set) > > } > > > > /* > > - * FM common sub-module will schedule this tasklet whenever it receives > > + * FM common sub-module will queue this 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; > > @@ -256,7 +256,7 @@ static void recv_tasklet(struct tasklet_struct *t) > > 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))) { > > @@ -322,22 +322,22 @@ static void recv_tasklet(struct tasklet_struct *t) > > > > /* > > * Check flow control field. If Num_FM_HCI_Commands field is > > - * not zero, schedule FM TX tasklet. > > + * not zero, queue FM TX 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; > > @@ -366,7 +366,7 @@ static void send_tasklet(struct tasklet_struct *t) > > if (len < 0) { > > kfree_skb(skb); > > fmdev->resp_comp = NULL; > > - fmerr("TX tasklet failed to send skb(%p)\n", skb); > > + fmerr("TX work failed to send skb(%p)\n", skb); > > atomic_set(&fmdev->tx_cnt, 1); > > } else { > > fmdev->last_tx_jiffies = jiffies; > > @@ -374,7 +374,7 @@ static void send_tasklet(struct tasklet_struct *t) > > } > > > > /* > > - * 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 work for > > * transmission > > */ > > static int fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload, > > @@ -440,7 +440,7 @@ 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; > > } > > @@ -462,7 +462,7 @@ int fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload, > > > > 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 work\n", > > jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000); > > return -ETIMEDOUT; > > } > > @@ -1455,7 +1455,7 @@ static long fm_st_receive(void *arg, struct sk_buff *skb) > > > > 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; > > } > > @@ -1537,13 +1537,13 @@ int fmc_prepare(struct fmdev *fmdev) > > 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 work */ > > I noticed that in most comments 'tasklet' is replaced by 'work', but perhaps > that should also be 'BH work' (you do that in a few comments). It would be > nice if you can go through the patch and update comments where appropriate. > > It is not a blocker, but it would make it a bit more consistent. Makes sense. I will work on this and have a new version out by eod. Thanks. > > > 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 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); > > @@ -1589,8 +1589,8 @@ int fmc_release(struct fmdev *fmdev) > > /* 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); > > diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c > > index c76ba24c1f55..01b65451228d 100644 > > --- a/drivers/media/rc/mceusb.c > > +++ b/drivers/media/rc/mceusb.c > > @@ -774,7 +774,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len, > > > > /* > > * 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. > > */ > > diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c > > index 79faa2560613..c8bc84f4aefb 100644 > > --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c > > +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c > > @@ -19,6 +19,7 @@ > > #include <linux/input.h> > > > > #include <linux/mutex.h> > > +#include <linux/workqueue.h> > > > > #include <media/dmxdev.h> > > #include <media/dvb_demux.h> > > @@ -139,7 +140,7 @@ struct ttusb_dec { > > int v_pes_postbytes; > > > > struct list_head urb_frame_list; > > - struct tasklet_struct urb_tasklet; > > + struct work_struct urb_work; > > urb_bh_work > > > spinlock_t urb_frame_list_lock; > > > > struct dvb_demux_filter *audio_filter; > > @@ -766,9 +767,9 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b, > > } > > } > > > > -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_work); > > struct list_head *item; > > struct urb_frame *frame; > > unsigned long flags; > > @@ -822,7 +823,7 @@ static void ttusb_dec_process_urb(struct urb *urb) > > spin_unlock_irqrestore(&dec->urb_frame_list_lock, > > flags); > > > > - tasklet_schedule(&dec->urb_tasklet); > > + queue_work(system_bh_wq, &dec->urb_work); > > } > > } > > } else { > > @@ -1198,11 +1199,11 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) > > return 0; > > } > > > > -static void ttusb_dec_init_tasklet(struct ttusb_dec *dec) > > +static void ttusb_dec_init_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_work, ttusb_dec_process_urb_frame_list); > > } > > > > static int ttusb_init_rc( struct ttusb_dec *dec) > > @@ -1588,12 +1589,12 @@ static void ttusb_dec_exit_usb(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_work(struct ttusb_dec *dec) > > { > > struct list_head *item; > > struct urb_frame *frame; > > > > - tasklet_kill(&dec->urb_tasklet); > > + cancel_work_sync(&dec->urb_work); > > > > while ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) { > > frame = list_entry(item, struct urb_frame, urb_frame_list); > > @@ -1703,7 +1704,7 @@ static int ttusb_dec_probe(struct usb_interface *intf, > > > > ttusb_dec_init_v_pes(dec); > > ttusb_dec_init_filters(dec); > > - ttusb_dec_init_tasklet(dec); > > + ttusb_dec_init_work(dec); > > > > dec->active = 1; > > > > @@ -1729,7 +1730,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf) > > dprintk("%s\n", __func__); > > > > if (dec->active) { > > - ttusb_dec_exit_tasklet(dec); > > + ttusb_dec_exit_work(dec); > > ttusb_dec_exit_filters(dec); > > if(enable_rc) > > ttusb_dec_exit_rc(dec); > > Regards, > > Hans
diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c index 90972d6952f1..dedf82b76e28 100644 --- a/drivers/media/pci/bt8xx/bt878.c +++ b/drivers/media/pci/bt8xx/bt878.c @@ -300,8 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id) } 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++; @@ -478,8 +478,8 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) 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; diff --git a/drivers/media/pci/bt8xx/bt878.h b/drivers/media/pci/bt8xx/bt878.h index fde8db293c54..5b1c7f56e553 100644 --- a/drivers/media/pci/bt8xx/bt878.h +++ b/drivers/media/pci/bt8xx/bt878.h @@ -14,6 +14,7 @@ #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/mutex.h> +#include <linux/workqueue.h> #include "bt848.h" #include "bttv.h" @@ -120,7 +121,7 @@ struct bt878 { dma_addr_t risc_dma; u32 risc_pos; - struct tasklet_struct tasklet; + struct work_struct bh_work; int shutdown; }; diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index 390cbba6c065..45074af3de66 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -15,6 +15,7 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/i2c.h> +#include <linux/workqueue.h> #include <media/dmxdev.h> #include <media/dvbdev.h> @@ -39,9 +40,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #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); @@ -782,7 +783,7 @@ static int dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) 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); @@ -922,7 +923,7 @@ static void dvb_bt8xx_remove(struct bttv_sub_device *sub) 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); diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h index f3699dbd193f..f01ecdb0b627 100644 --- a/drivers/media/pci/ddbridge/ddbridge.h +++ b/drivers/media/pci/ddbridge/ddbridge.h @@ -298,7 +298,7 @@ struct ddb_link { 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 */ diff --git a/drivers/media/pci/mantis/hopper_cards.c b/drivers/media/pci/mantis/hopper_cards.c index c0bd5d7e148b..b85aef4e2b24 100644 --- a/drivers/media/pci/mantis/hopper_cards.c +++ b/drivers/media/pci/mantis/hopper_cards.c @@ -116,7 +116,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id) 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]); diff --git a/drivers/media/pci/mantis/mantis_cards.c b/drivers/media/pci/mantis/mantis_cards.c index 906e4500d87d..b44b4cf42f86 100644 --- a/drivers/media/pci/mantis/mantis_cards.c +++ b/drivers/media/pci/mantis/mantis_cards.c @@ -125,7 +125,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id) 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]); diff --git a/drivers/media/pci/mantis/mantis_common.h b/drivers/media/pci/mantis/mantis_common.h index d88ac280226c..6e563ecd94e8 100644 --- a/drivers/media/pci/mantis/mantis_common.h +++ b/drivers/media/pci/mantis/mantis_common.h @@ -125,7 +125,7 @@ struct mantis_pci { __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; diff --git a/drivers/media/pci/mantis/mantis_dma.c b/drivers/media/pci/mantis/mantis_dma.c index 80c843936493..eeb210a2862f 100644 --- a/drivers/media/pci/mantis/mantis_dma.c +++ b/drivers/media/pci/mantis/mantis_dma.c @@ -200,9 +200,9 @@ void mantis_dma_stop(struct mantis_pci *mantis) } -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) { diff --git a/drivers/media/pci/mantis/mantis_dma.h b/drivers/media/pci/mantis/mantis_dma.h index 37da982c9c29..5db0d3728f15 100644 --- a/drivers/media/pci/mantis/mantis_dma.h +++ b/drivers/media/pci/mantis/mantis_dma.h @@ -13,6 +13,6 @@ extern int mantis_dma_init(struct mantis_pci *mantis); 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 */ diff --git a/drivers/media/pci/mantis/mantis_dvb.c b/drivers/media/pci/mantis/mantis_dvb.c index c7ba4a76e608..398e32f44692 100644 --- a/drivers/media/pci/mantis/mantis_dvb.c +++ b/drivers/media/pci/mantis/mantis_dvb.c @@ -105,7 +105,7 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) 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; @@ -125,7 +125,7 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 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); } @@ -205,8 +205,8 @@ int mantis_dvb_init(struct mantis_pci *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) { @@ -235,7 +235,7 @@ int mantis_dvb_init(struct mantis_pci *mantis) /* 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); @@ -273,7 +273,7 @@ int mantis_dvb_exit(struct mantis_pci *mantis) 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); diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c index 24ec576dc3bf..9641f23b2247 100644 --- a/drivers/media/pci/ngene/ngene-core.c +++ b/drivers/media/pci/ngene/ngene-core.c @@ -50,9 +50,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); /* 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 = @@ -68,9 +68,9 @@ static void event_tasklet(struct tasklet_struct *t) } } -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; @@ -204,7 +204,7 @@ static irqreturn_t irq_handler(int irq, void *dev_id) dev->EventQueueOverflowFlag = 1; } dev->EventBuffer->EventStatus &= ~0x80; - tasklet_schedule(&dev->event_tasklet); + queue_work(system_bh_wq, &dev->event_bh_work); rc = IRQ_HANDLED; } @@ -217,8 +217,8 @@ static irqreturn_t irq_handler(int irq, void *dev_id) 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; } } @@ -1181,7 +1181,7 @@ static void ngene_init(struct ngene *dev) 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); @@ -1395,7 +1395,7 @@ static void release_channel(struct ngene_channel *chan) 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); @@ -1445,7 +1445,7 @@ static int init_channel(struct ngene_channel *chan) 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 */ @@ -1649,7 +1649,7 @@ void ngene_remove(struct pci_dev *pdev) 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) diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h index d1d7da84cd9d..9f989420b9e7 100644 --- a/drivers/media/pci/ngene/ngene.h +++ b/drivers/media/pci/ngene/ngene.h @@ -16,6 +16,7 @@ #include <linux/scatterlist.h> #include <linux/dvb/frontend.h> +#include <linux/workqueue.h> #include <media/dmxdev.h> #include <media/dvbdev.h> @@ -621,7 +622,7 @@ struct ngene_channel { 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; @@ -717,7 +718,7 @@ struct ngene { 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; diff --git a/drivers/media/pci/smipcie/smipcie-main.c b/drivers/media/pci/smipcie/smipcie-main.c index 0c300d019d9c..7db6d443fc54 100644 --- a/drivers/media/pci/smipcie/smipcie-main.c +++ b/drivers/media/pci/smipcie/smipcie-main.c @@ -279,10 +279,10 @@ static void smi_port_clearInterrupt(struct smi_port *port) (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; @@ -426,8 +426,8 @@ static int smi_port_init(struct smi_port *port, int dmaChanUsed) } 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: @@ -438,7 +438,7 @@ static int smi_port_init(struct smi_port *port, int dmaChanUsed) 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; } @@ -452,7 +452,7 @@ static int smi_port_irq(struct smi_port *port, u32 int_status) 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; @@ -823,7 +823,7 @@ static int smi_start_feed(struct dvb_demux_feed *dvbdmxfeed) 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; } @@ -837,7 +837,7 @@ static int smi_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 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; diff --git a/drivers/media/pci/smipcie/smipcie.h b/drivers/media/pci/smipcie/smipcie.h index 2b5e0154814c..98e44edaab9e 100644 --- a/drivers/media/pci/smipcie/smipcie.h +++ b/drivers/media/pci/smipcie/smipcie.h @@ -17,6 +17,7 @@ #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> @@ -257,7 +258,7 @@ struct smi_port { 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; diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c index 2e62c938e2cb..dd915bf5d2a4 100644 --- a/drivers/media/pci/ttpci/budget-av.c +++ b/drivers/media/pci/ttpci/budget-av.c @@ -36,6 +36,7 @@ #include <linux/interrupt.h> #include <linux/input.h> #include <linux/spinlock.h> +#include <linux/workqueue.h> #include <media/dvb_ca_en50221.h> @@ -54,7 +55,7 @@ struct budget_av { struct video_device vd; int cur_input; int has_saa7113; - struct tasklet_struct ciintf_irq_tasklet; + struct work_struct ciintf_irq_work; int slot_status; struct dvb_ca_en50221 ca; u8 reinitialise_demod:1; diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c index 76de40e3c802..8187e26a0b3d 100644 --- a/drivers/media/pci/ttpci/budget-ci.c +++ b/drivers/media/pci/ttpci/budget-ci.c @@ -18,6 +18,7 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/spinlock.h> +#include <linux/workqueue.h> #include <media/rc-core.h> #include "budget.h" @@ -81,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct budget_ci_ir { struct rc_dev *dev; - struct tasklet_struct msp430_irq_tasklet; + struct work_struct msp430_irq_work; char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ char phys[32]; int rc5_device; @@ -92,7 +93,7 @@ struct budget_ci_ir { struct budget_ci { struct budget budget; - struct tasklet_struct ciintf_irq_tasklet; + struct work_struct ciintf_irq_work; int slot_status; int ci_irq; struct dvb_ca_en50221 ca; @@ -100,9 +101,9 @@ struct budget_ci { 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_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; @@ -231,7 +232,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) budget_ci->ir.dev = dev; - tasklet_setup(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt); + INIT_WORK(&budget_ci->ir.msp430_irq_work, msp430_ir_interrupt); SAA7146_IER_ENABLE(saa, MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); @@ -245,7 +246,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) 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_work); rc_unregister_device(budget_ci->ir.dev); } @@ -349,10 +350,10 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) 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_work); struct saa7146_dev *saa = budget_ci->budget.dev; unsigned int flags; @@ -491,7 +492,7 @@ static int ciintf_init(struct budget_ci *budget_ci) // Setup CI slot IRQ if (budget_ci->ci_irq) { - tasklet_setup(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt); + INIT_WORK(&budget_ci->ciintf_irq_work, ciintf_interrupt); if (budget_ci->slot_status != SLOTSTATUS_NONE) saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); else @@ -530,7 +531,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) 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_work); } // reset interface @@ -556,13 +557,13 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 *isr) 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_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_work); } static u8 philips_su1278_tt_inittab[] = { diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c index d33adeca196f..ebcae1baedfe 100644 --- a/drivers/media/pci/ttpci/budget-core.c +++ b/drivers/media/pci/ttpci/budget-core.c @@ -172,9 +172,9 @@ static int budget_read_fe_status(struct dvb_frontend *fe, 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_work); u8 *mem = (u8 *) (budget->grabbing); u32 olddma = budget->ttbp; u32 newdma = saa7146_read(budget->dev, PCI_VDP3); @@ -525,7 +525,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, /* upload all */ saa7146_write(dev, GPIO_CTRL, 0x000000); - tasklet_setup(&budget->vpe_tasklet, vpeirq); + INIT_WORK(&budget->vpe_work, vpeirq); /* frontend power on */ if (bi->type != BUDGET_FS_ACTIVY) @@ -565,7 +565,7 @@ int ttpci_budget_deinit(struct budget *budget) budget_unregister(budget); - tasklet_kill(&budget->vpe_tasklet); + cancel_work_sync(&budget->vpe_work); saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt); @@ -584,7 +584,7 @@ void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 *isr) 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_work); } EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); diff --git a/drivers/media/pci/ttpci/budget.h b/drivers/media/pci/ttpci/budget.h index 83ead34dc766..54bf96a2f5b5 100644 --- a/drivers/media/pci/ttpci/budget.h +++ b/drivers/media/pci/ttpci/budget.h @@ -18,6 +18,7 @@ #include <linux/module.h> #include <linux/mutex.h> +#include <linux/workqueue.h> #include <media/drv-intf/saa7146.h> @@ -54,8 +55,8 @@ struct budget { unsigned char *grabbing; struct saa7146_pgtable pt; - struct tasklet_struct fidb_tasklet; - struct tasklet_struct vpe_tasklet; + struct work_struct fidb_work; + struct work_struct vpe_work; struct dmxdev dmxdev; struct dvb_demux demux; diff --git a/drivers/media/pci/tw5864/tw5864-core.c b/drivers/media/pci/tw5864/tw5864-core.c index 560ff1ddcc83..4d33caf83307 100644 --- a/drivers/media/pci/tw5864/tw5864-core.c +++ b/drivers/media/pci/tw5864/tw5864-core.c @@ -144,7 +144,7 @@ static void tw5864_h264_isr(struct tw5864_dev *dev) 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; diff --git a/drivers/media/pci/tw5864/tw5864-video.c b/drivers/media/pci/tw5864/tw5864-video.c index 8b1aae4b6319..4f35c159efe5 100644 --- a/drivers/media/pci/tw5864/tw5864-video.c +++ b/drivers/media/pci/tw5864/tw5864-video.c @@ -6,6 +6,7 @@ */ #include <linux/module.h> +#include <linux/workqueue.h> #include <media/v4l2-common.h> #include <media/v4l2-event.h> #include <media/videobuf2-dma-contig.h> @@ -175,7 +176,7 @@ static const unsigned int intra4x4_lambda3[] = { 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); @@ -1062,7 +1063,7 @@ int tw5864_video_init(struct tw5864_dev *dev, int *video_nr) 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; @@ -1079,7 +1080,7 @@ int tw5864_video_init(struct tw5864_dev *dev, int *video_nr) 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--) { @@ -1198,7 +1199,7 @@ void tw5864_video_fini(struct tw5864_dev *dev) { 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]); @@ -1315,9 +1316,9 @@ static int tw5864_is_motion_triggered(struct tw5864_h264_frame *frame) 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; diff --git a/drivers/media/pci/tw5864/tw5864.h b/drivers/media/pci/tw5864/tw5864.h index a8b6fbd5b710..2da5f4215fd9 100644 --- a/drivers/media/pci/tw5864/tw5864.h +++ b/drivers/media/pci/tw5864/tw5864.h @@ -12,6 +12,7 @@ #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> @@ -85,7 +86,7 @@ struct tw5864_input { 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; @@ -142,7 +143,7 @@ struct tw5864_h264_frame { /* 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 @@ -150,7 +151,7 @@ struct tw5864_dev { 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) */ diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c index d904952bf00e..f118aaac0b38 100644 --- a/drivers/media/platform/intel/pxa_camera.c +++ b/drivers/media/platform/intel/pxa_camera.c @@ -43,6 +43,7 @@ #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" @@ -683,7 +684,7 @@ struct pxa_camera_dev { unsigned int buf_sequence; struct pxa_buffer *active; - struct tasklet_struct task_eof; + struct work_struct eof_bh_work; u32 save_cicr[5]; }; @@ -1146,9 +1147,9 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) 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; @@ -1185,7 +1186,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) 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; @@ -2383,7 +2384,7 @@ static int pxa_camera_probe(struct platform_device *pdev) } } - tasklet_setup(&pcdev->task_eof, pxa_camera_eof); + INIT_WORK(&pcdev->eof_bh_work, pxa_camera_eof_bh_work); pxa_camera_activate(pcdev); @@ -2409,7 +2410,7 @@ static int pxa_camera_probe(struct platform_device *pdev) 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: @@ -2428,7 +2429,7 @@ static void pxa_camera_remove(struct platform_device *pdev) 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]); diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c index 66688b4aece5..fa7ebf2fcfac 100644 --- a/drivers/media/platform/marvell/mcam-core.c +++ b/drivers/media/platform/marvell/mcam-core.c @@ -439,9 +439,9 @@ static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam) /* * 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_work); int i; unsigned long flags; struct mcam_vb_buffer *buf; @@ -493,7 +493,7 @@ static int mcam_check_dma_buffers(struct mcam_camera *cam) static void mcam_vmalloc_done(struct mcam_camera *cam, int frame) { - tasklet_schedule(&cam->s_tasklet); + queue_work(system_bh_wq, &cam->s_work); } #else /* MCAM_MODE_VMALLOC */ @@ -1305,7 +1305,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam) break; case B_vmalloc: #ifdef MCAM_MODE_VMALLOC - tasklet_setup(&cam->s_tasklet, mcam_frame_tasklet); + INIT_WORK(&cam->s_work, mcam_frame_work); vq->ops = &mcam_vb2_ops; vq->mem_ops = &vb2_vmalloc_memops; cam->dma_setup = mcam_ctlr_dma_vmalloc; diff --git a/drivers/media/platform/marvell/mcam-core.h b/drivers/media/platform/marvell/mcam-core.h index 51e66db45af6..0d4b953dbb23 100644 --- a/drivers/media/platform/marvell/mcam-core.h +++ b/drivers/media/platform/marvell/mcam-core.h @@ -9,6 +9,7 @@ #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> @@ -167,7 +168,7 @@ struct mcam_camera { 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_work; #endif unsigned int sequence; /* Frame sequence number */ unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */ diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c index 2f58a0d0df85..7bbb26a5b366 100644 --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c @@ -72,16 +72,16 @@ static void c8sectpfe_timer_interrupt(struct timer_list *t) /* 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; @@ -210,7 +210,7 @@ static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed) 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, @@ -303,7 +303,7 @@ static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed) /* 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; @@ -630,8 +630,8 @@ static int configure_memdma_and_inputblock(struct c8sectpfei *fei, 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 work */ + INIT_WORK(&tsin->bh_work, channel_swdemux_bh_work); return 0; diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h index bf377cc82225..c1b124c6ef12 100644 --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h @@ -51,7 +51,7 @@ struct channel_info { unsigned long fifo; struct completion idle_completion; - struct tasklet_struct tsklet; + struct work_struct bh_work; struct c8sectpfei *fei; void __iomem *irec; diff --git a/drivers/media/radio/wl128x/fmdrv.h b/drivers/media/radio/wl128x/fmdrv.h index da8920169df8..03117a41dbd4 100644 --- a/drivers/media/radio/wl128x/fmdrv.h +++ b/drivers/media/radio/wl128x/fmdrv.h @@ -15,6 +15,7 @@ #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> @@ -200,10 +201,10 @@ struct fmdev { 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 */ diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index 3da8e5102bec..37ed1ed664e0 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -9,7 +9,7 @@ * 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 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) @@ -244,10 +244,10 @@ void fmc_update_region_info(struct fmdev *fmdev, u8 region_to_set) } /* - * FM common sub-module will schedule this tasklet whenever it receives + * FM common sub-module will queue this 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; @@ -256,7 +256,7 @@ static void recv_tasklet(struct tasklet_struct *t) 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))) { @@ -322,22 +322,22 @@ static void recv_tasklet(struct tasklet_struct *t) /* * Check flow control field. If Num_FM_HCI_Commands field is - * not zero, schedule FM TX tasklet. + * not zero, queue FM TX 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; @@ -366,7 +366,7 @@ static void send_tasklet(struct tasklet_struct *t) if (len < 0) { kfree_skb(skb); fmdev->resp_comp = NULL; - fmerr("TX tasklet failed to send skb(%p)\n", skb); + fmerr("TX work failed to send skb(%p)\n", skb); atomic_set(&fmdev->tx_cnt, 1); } else { fmdev->last_tx_jiffies = jiffies; @@ -374,7 +374,7 @@ static void send_tasklet(struct tasklet_struct *t) } /* - * 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 work for * transmission */ static int fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload, @@ -440,7 +440,7 @@ 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; } @@ -462,7 +462,7 @@ int fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload, 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 work\n", jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000); return -ETIMEDOUT; } @@ -1455,7 +1455,7 @@ static long fm_st_receive(void *arg, struct sk_buff *skb) 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; } @@ -1537,13 +1537,13 @@ int fmc_prepare(struct fmdev *fmdev) 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 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 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); @@ -1589,8 +1589,8 @@ int fmc_release(struct fmdev *fmdev) /* 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); diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index c76ba24c1f55..01b65451228d 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -774,7 +774,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len, /* * 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. */ diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c index 79faa2560613..c8bc84f4aefb 100644 --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c @@ -19,6 +19,7 @@ #include <linux/input.h> #include <linux/mutex.h> +#include <linux/workqueue.h> #include <media/dmxdev.h> #include <media/dvb_demux.h> @@ -139,7 +140,7 @@ struct ttusb_dec { int v_pes_postbytes; struct list_head urb_frame_list; - struct tasklet_struct urb_tasklet; + struct work_struct urb_work; spinlock_t urb_frame_list_lock; struct dvb_demux_filter *audio_filter; @@ -766,9 +767,9 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b, } } -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_work); struct list_head *item; struct urb_frame *frame; unsigned long flags; @@ -822,7 +823,7 @@ static void ttusb_dec_process_urb(struct urb *urb) spin_unlock_irqrestore(&dec->urb_frame_list_lock, flags); - tasklet_schedule(&dec->urb_tasklet); + queue_work(system_bh_wq, &dec->urb_work); } } } else { @@ -1198,11 +1199,11 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) return 0; } -static void ttusb_dec_init_tasklet(struct ttusb_dec *dec) +static void ttusb_dec_init_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_work, ttusb_dec_process_urb_frame_list); } static int ttusb_init_rc( struct ttusb_dec *dec) @@ -1588,12 +1589,12 @@ static void ttusb_dec_exit_usb(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_work(struct ttusb_dec *dec) { struct list_head *item; struct urb_frame *frame; - tasklet_kill(&dec->urb_tasklet); + cancel_work_sync(&dec->urb_work); while ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) { frame = list_entry(item, struct urb_frame, urb_frame_list); @@ -1703,7 +1704,7 @@ static int ttusb_dec_probe(struct usb_interface *intf, ttusb_dec_init_v_pes(dec); ttusb_dec_init_filters(dec); - ttusb_dec_init_tasklet(dec); + ttusb_dec_init_work(dec); dec->active = 1; @@ -1729,7 +1730,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf) dprintk("%s\n", __func__); if (dec->active) { - ttusb_dec_exit_tasklet(dec); + ttusb_dec_exit_work(dec); ttusb_dec_exit_filters(dec); if(enable_rc) ttusb_dec_exit_rc(dec);
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/media/* from tasklet to BH workqueue. Based on the work done by Tejun Heo <tj@kernel.org> Signed-off-by: Allen Pais <allen.lkml@gmail.com> --- v4: - fixed styling issues. - rename work to bh_work [Hans Verkuil] - Fixed mantis build failure [Hans Verkuil] v3: https://lore.kernel.org/all/20240425183127.11409-1-apais@linux.microsoft.com/ v2: https://lore.kernel.org/all/20240327160314.9982-9-apais@linux.microsoft.com/ drivers/media/pci/bt8xx/bt878.c | 8 ++-- drivers/media/pci/bt8xx/bt878.h | 3 +- drivers/media/pci/bt8xx/dvb-bt8xx.c | 9 +++-- drivers/media/pci/ddbridge/ddbridge.h | 2 +- drivers/media/pci/mantis/hopper_cards.c | 2 +- drivers/media/pci/mantis/mantis_cards.c | 2 +- drivers/media/pci/mantis/mantis_common.h | 2 +- drivers/media/pci/mantis/mantis_dma.c | 4 +- drivers/media/pci/mantis/mantis_dma.h | 2 +- drivers/media/pci/mantis/mantis_dvb.c | 12 +++--- drivers/media/pci/ngene/ngene-core.c | 22 +++++----- drivers/media/pci/ngene/ngene.h | 5 ++- drivers/media/pci/smipcie/smipcie-main.c | 18 ++++----- drivers/media/pci/smipcie/smipcie.h | 3 +- drivers/media/pci/ttpci/budget-av.c | 3 +- drivers/media/pci/ttpci/budget-ci.c | 27 +++++++------ drivers/media/pci/ttpci/budget-core.c | 10 ++--- drivers/media/pci/ttpci/budget.h | 5 ++- drivers/media/pci/tw5864/tw5864-core.c | 2 +- drivers/media/pci/tw5864/tw5864-video.c | 13 +++--- drivers/media/pci/tw5864/tw5864.h | 7 ++-- drivers/media/platform/intel/pxa_camera.c | 15 +++---- drivers/media/platform/marvell/mcam-core.c | 8 ++-- drivers/media/platform/marvell/mcam-core.h | 3 +- .../st/sti/c8sectpfe/c8sectpfe-core.c | 14 +++---- .../st/sti/c8sectpfe/c8sectpfe-core.h | 2 +- drivers/media/radio/wl128x/fmdrv.h | 5 ++- drivers/media/radio/wl128x/fmdrv_common.c | 40 +++++++++---------- drivers/media/rc/mceusb.c | 2 +- drivers/media/usb/ttusb-dec/ttusb_dec.c | 21 +++++----- 30 files changed, 142 insertions(+), 129 deletions(-)