#include <linux/dmaengine.h>
#include <linux/platform_device.h>
+#include <linux/workqueue.h>
#include "tmio_mmc.h"
struct renesas_sdhi_scc {
dma_filter_fn filter;
void (*enable)(struct tmio_mmc_host *host, bool enable);
struct completion dma_dataend;
- struct tasklet_struct dma_complete;
+ struct work_struct dma_complete;
};
struct renesas_sdhi {
unsigned int tap_set;
struct reset_control *rstc;
+ struct tmio_mmc_host *host;
};
#define host_to_priv(host) \
writel(status ^ dma_irqs, host->ctl + DM_CM_INFO1);
set_bit(SDHI_DMA_END_FLAG_DMA, &dma_priv->end_flags);
if (test_bit(SDHI_DMA_END_FLAG_ACCESS, &dma_priv->end_flags))
- tasklet_schedule(&dma_priv->dma_complete);
+ queue_work(system_bh_wq, &dma_priv->dma_complete);
}
return status & dma_irqs;
set_bit(SDHI_DMA_END_FLAG_ACCESS, &dma_priv->end_flags);
if (test_bit(SDHI_DMA_END_FLAG_DMA, &dma_priv->end_flags) ||
host->data->error)
- tasklet_schedule(&dma_priv->dma_complete);
+ queue_work(system_bh_wq, &dma_priv->dma_complete);
}
/*
renesas_sdhi_internal_dmac_enable_dma(host, false);
}
-static void renesas_sdhi_internal_dmac_issue_tasklet_fn(unsigned long arg)
+static void renesas_sdhi_internal_dmac_issue_work_fn(struct work_struct *work)
{
- struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg;
+ struct tmio_mmc_host *host = from_work(host, work, dma_issue);
struct renesas_sdhi *priv = host_to_priv(host);
tmio_mmc_enable_mmc_irqs(host, TMIO_STAT_DATAEND);
/* on CMD errors, simulate DMA end immediately */
set_bit(SDHI_DMA_END_FLAG_DMA, &priv->dma_priv.end_flags);
if (test_bit(SDHI_DMA_END_FLAG_ACCESS, &priv->dma_priv.end_flags))
- tasklet_schedule(&priv->dma_priv.dma_complete);
+ queue_work(system_bh_wq, &priv->dma_priv.dma_complete);
}
}
return true;
}
-static void renesas_sdhi_internal_dmac_complete_tasklet_fn(unsigned long arg)
+static void renesas_sdhi_internal_dmac_complete_work_fn(struct work_struct *work)
{
- struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg;
+ struct renesas_sdhi_dma *dma_priv = from_work(dma_priv, work, dma_complete);
+ struct renesas_sdhi *priv = container_of(dma_priv, typeof(*priv), dma_priv);
+ struct tmio_mmc_host *host = priv->host;
spin_lock_irq(&host->lock);
if (!renesas_sdhi_internal_dmac_complete(host))
/* Each value is set to non-zero to assume "enabling" each DMA */
host->chan_rx = host->chan_tx = (void *)0xdeadbeaf;
- tasklet_init(&priv->dma_priv.dma_complete,
- renesas_sdhi_internal_dmac_complete_tasklet_fn,
- (unsigned long)host);
- tasklet_init(&host->dma_issue,
- renesas_sdhi_internal_dmac_issue_tasklet_fn,
- (unsigned long)host);
+ INIT_WORK(&priv->dma_priv.dma_complete,
+ renesas_sdhi_internal_dmac_complete_work_fn);
+ INIT_WORK(&host->dma_issue,
+ renesas_sdhi_internal_dmac_issue_work_fn);
/* Add pre_req and post_req */
host->ops.pre_req = renesas_sdhi_internal_dmac_pre_req;
}
}
-static void renesas_sdhi_sys_dmac_issue_tasklet_fn(unsigned long priv)
+static void renesas_sdhi_sys_dmac_issue_work_fn(struct work_struct *work)
{
- struct tmio_mmc_host *host = (struct tmio_mmc_host *)priv;
+ struct tmio_mmc_host *host = from_work(host, work, dma_issue);
struct dma_chan *chan = NULL;
spin_lock_irq(&host->lock);
goto ebouncebuf;
init_completion(&priv->dma_priv.dma_dataend);
- tasklet_init(&host->dma_issue,
- renesas_sdhi_sys_dmac_issue_tasklet_fn,
- (unsigned long)host);
+ INIT_WORK(&host->dma_issue,
+ renesas_sdhi_sys_dmac_issue_work_fn);
}
renesas_sdhi_sys_dmac_enable_dma(host, true);