summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/au1xmmc.c
diff options
context:
space:
mode:
authorAllen Pais <allen.lkml@gmail.com>2024-07-01 13:07:33 +0300
committerUlf Hansson <ulf.hansson@linaro.org>2024-07-08 12:41:30 +0300
commit921c87ba3893b5d3608e7f248366266b40b86c75 (patch)
tree46d8d628a666d161233a05c9a7a2fd953c9d226c /drivers/mmc/host/au1xmmc.c
parent85683fb39d9b671620b5a9343fab3356e486a9a6 (diff)
downloadlinux-921c87ba3893b5d3608e7f248366266b40b86c75.tar.xz
mmc: Convert from tasklet to BH workqueue
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/mmc/* from tasklet to BH workqueue. Based on the work done by Tejun Heo <tj@kernel.org> Tested-by: Christian Loehle <christian.loehle@arm.com> Tested-by: Aubin Constans <aubin.constans@microchip.com> Acked-by: Aubin Constans <aubin.constans@microchip.com> Acked-by: Michał Mirosław <mirq-linux@rere.qmqm.pl> Reviewed-by: Christian Loehle <christian.loehle@arm.com> Signed-off-by: Allen Pais <allen.lkml@gmail.com> Link: https://lore.kernel.org/r/20240701100736.4001658-1-allen.lkml@gmail.com Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc/host/au1xmmc.c')
-rw-r--r--drivers/mmc/host/au1xmmc.c37
1 files changed, 19 insertions, 18 deletions
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index b5a5c6a2fe8b..6e80bcb668ec 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -42,6 +42,7 @@
#include <linux/leds.h>
#include <linux/mmc/host.h>
#include <linux/slab.h>
+#include <linux/workqueue.h>
#include <asm/io.h>
#include <asm/mach-au1x00/au1000.h>
@@ -113,8 +114,8 @@ struct au1xmmc_host {
int irq;
- struct tasklet_struct finish_task;
- struct tasklet_struct data_task;
+ struct work_struct finish_bh_work;
+ struct work_struct data_bh_work;
struct au1xmmc_platform_data *platdata;
struct platform_device *pdev;
struct resource *ioarea;
@@ -253,9 +254,9 @@ static void au1xmmc_finish_request(struct au1xmmc_host *host)
mmc_request_done(host->mmc, mrq);
}
-static void au1xmmc_tasklet_finish(struct tasklet_struct *t)
+static void au1xmmc_finish_bh_work(struct work_struct *t)
{
- struct au1xmmc_host *host = from_tasklet(host, t, finish_task);
+ struct au1xmmc_host *host = from_work(host, t, finish_bh_work);
au1xmmc_finish_request(host);
}
@@ -363,9 +364,9 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
au1xmmc_finish_request(host);
}
-static void au1xmmc_tasklet_data(struct tasklet_struct *t)
+static void au1xmmc_data_bh_work(struct work_struct *t)
{
- struct au1xmmc_host *host = from_tasklet(host, t, data_task);
+ struct au1xmmc_host *host = from_work(host, t, data_bh_work);
u32 status = __raw_readl(HOST_STATUS(host));
au1xmmc_data_complete(host, status);
@@ -425,7 +426,7 @@ static void au1xmmc_send_pio(struct au1xmmc_host *host)
if (host->flags & HOST_F_STOP)
SEND_STOP(host);
- tasklet_schedule(&host->data_task);
+ queue_work(system_bh_wq, &host->data_bh_work);
}
}
@@ -505,7 +506,7 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
if (host->flags & HOST_F_STOP)
SEND_STOP(host);
- tasklet_schedule(&host->data_task);
+ queue_work(system_bh_wq, &host->data_bh_work);
}
}
@@ -561,7 +562,7 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
if (!trans || cmd->error) {
IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA | SD_CONFIG_RF);
- tasklet_schedule(&host->finish_task);
+ queue_work(system_bh_wq, &host->finish_bh_work);
return;
}
@@ -797,7 +798,7 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
/* IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA | SD_CONFIG_RF); */
- tasklet_schedule(&host->finish_task);
+ queue_work(system_bh_wq, &host->finish_bh_work);
}
#if 0
else if (status & SD_STATUS_DD) {
@@ -806,7 +807,7 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
au1xmmc_receive_pio(host);
else {
au1xmmc_data_complete(host, status);
- /* tasklet_schedule(&host->data_task); */
+ /* queue_work(system_bh_wq, &host->data_bh_work); */
}
}
#endif
@@ -854,7 +855,7 @@ static void au1xmmc_dbdma_callback(int irq, void *dev_id)
if (host->flags & HOST_F_STOP)
SEND_STOP(host);
- tasklet_schedule(&host->data_task);
+ queue_work(system_bh_wq, &host->data_bh_work);
}
static int au1xmmc_dbdma_init(struct au1xmmc_host *host)
@@ -1039,9 +1040,9 @@ static int au1xmmc_probe(struct platform_device *pdev)
if (host->platdata)
mmc->caps &= ~(host->platdata->mask_host_caps);
- tasklet_setup(&host->data_task, au1xmmc_tasklet_data);
+ INIT_WORK(&host->data_bh_work, au1xmmc_data_bh_work);
- tasklet_setup(&host->finish_task, au1xmmc_tasklet_finish);
+ INIT_WORK(&host->finish_bh_work, au1xmmc_finish_bh_work);
if (has_dbdma()) {
ret = au1xmmc_dbdma_init(host);
@@ -1091,8 +1092,8 @@ out5:
if (host->flags & HOST_F_DBDMA)
au1xmmc_dbdma_shutdown(host);
- tasklet_kill(&host->data_task);
- tasklet_kill(&host->finish_task);
+ cancel_work_sync(&host->data_bh_work);
+ cancel_work_sync(&host->finish_bh_work);
if (host->platdata && host->platdata->cd_setup &&
!(mmc->caps & MMC_CAP_NEEDS_POLL))
@@ -1135,8 +1136,8 @@ static void au1xmmc_remove(struct platform_device *pdev)
__raw_writel(0, HOST_CONFIG2(host));
wmb(); /* drain writebuffer */
- tasklet_kill(&host->data_task);
- tasklet_kill(&host->finish_task);
+ cancel_work_sync(&host->data_bh_work);
+ cancel_work_sync(&host->finish_bh_work);
if (host->flags & HOST_F_DBDMA)
au1xmmc_dbdma_shutdown(host);