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/rapidio/* from tasklet to BH workqueue.
Based on the work done by Tejun Heo <[email protected]>
Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10
Signed-off-by: Allen Pais <[email protected]>
---
drivers/rapidio/devices/tsi721.h | 2 +-
drivers/rapidio/devices/tsi721_dma.c | 15 +++++++--------
2 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h
index 4f996ce62725..8fd8127d11d1 100644
--- a/drivers/rapidio/devices/tsi721.h
+++ b/drivers/rapidio/devices/tsi721.h
@@ -704,7 +704,7 @@ struct tsi721_bdma_chan {
struct tsi721_tx_desc *active_tx;
struct list_head queue;
struct list_head free_list;
- struct tasklet_struct tasklet;
+ struct work_struct work;
bool active;
};
diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c
index f77f75172bdc..f71cbbacca12 100644
--- a/drivers/rapidio/devices/tsi721_dma.c
+++ b/drivers/rapidio/devices/tsi721_dma.c
@@ -278,7 +278,7 @@ void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan)
/* Disable BDMA channel interrupts */
iowrite32(0, bdma_chan->regs + TSI721_DMAC_INTE);
if (bdma_chan->active)
- tasklet_hi_schedule(&bdma_chan->tasklet);
+ queue_work(system_bh_highpri_wq, &bdma_chan->work);
}
#ifdef CONFIG_PCI_MSI
@@ -296,7 +296,7 @@ static irqreturn_t tsi721_bdma_msix(int irq, void *ptr)
struct tsi721_bdma_chan *bdma_chan = ptr;
if (bdma_chan->active)
- tasklet_hi_schedule(&bdma_chan->tasklet);
+ queue_work(system_bh_highpri_wq, &bdma_chan->work);
return IRQ_HANDLED;
}
#endif /* CONFIG_PCI_MSI */
@@ -568,9 +568,9 @@ static void tsi721_advance_work(struct tsi721_bdma_chan *bdma_chan,
bdma_chan->id);
}
-static void tsi721_dma_tasklet(unsigned long data)
+static void tsi721_dma_work(struct work_struct *t)
{
- struct tsi721_bdma_chan *bdma_chan = (struct tsi721_bdma_chan *)data;
+ struct tsi721_bdma_chan *bdma_chan = from_work(bdma_chan, t, work);
u32 dmac_int, dmac_sts;
dmac_int = ioread32(bdma_chan->regs + TSI721_DMAC_INT);
@@ -790,7 +790,7 @@ static void tsi721_free_chan_resources(struct dma_chan *dchan)
tsi721_bdma_interrupt_enable(bdma_chan, 0);
bdma_chan->active = false;
tsi721_sync_dma_irq(bdma_chan);
- tasklet_kill(&bdma_chan->tasklet);
+ cancel_work_sync(&bdma_chan->work);
INIT_LIST_HEAD(&bdma_chan->free_list);
kfree(bdma_chan->tx_desc);
tsi721_bdma_ch_free(bdma_chan);
@@ -990,8 +990,7 @@ int tsi721_register_dma(struct tsi721_device *priv)
INIT_LIST_HEAD(&bdma_chan->queue);
INIT_LIST_HEAD(&bdma_chan->free_list);
- tasklet_init(&bdma_chan->tasklet, tsi721_dma_tasklet,
- (unsigned long)bdma_chan);
+ INIT_WORK(&bdma_chan->work, tsi721_dma_work);
list_add_tail(&bdma_chan->dchan.device_node,
&mport->dma.channels);
nr_channels++;
@@ -1033,7 +1032,7 @@ void tsi721_unregister_dma(struct tsi721_device *priv)
tsi721_bdma_interrupt_enable(bdma_chan, 0);
bdma_chan->active = false;
tsi721_sync_dma_irq(bdma_chan);
- tasklet_kill(&bdma_chan->tasklet);
+ cancel_work_sync(&bdma_chan->work);
INIT_LIST_HEAD(&bdma_chan->free_list);
kfree(bdma_chan->tx_desc);
tsi721_bdma_ch_free(bdma_chan);
--
2.17.1