提交 62612cf9 编写于 作者: S Sahitya Tummala 提交者: David Brown

mmc: msm_sdcc: Fix possible circular locking dependency warning

In the context of request processing thread, data mover lock is
acquired after the host lock.  In another context, in the completion
handler of data mover the locks are acquired in the reverse order,
resulting in possible circular lock dependency warning. Hence,
schedule a tasklet to process the dma completion so as to avoid
nested locks.
Signed-off-by: NSahitya Tummala <stummala@codeaurora.org>
Signed-off-by: NDavid Brown <davidb@codeaurora.org>
上级 50bc0ef4
...@@ -189,42 +189,40 @@ msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd) ...@@ -189,42 +189,40 @@ msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd)
} }
static void static void
msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd, msmsdcc_dma_complete_tlet(unsigned long data)
unsigned int result,
struct msm_dmov_errdata *err)
{ {
struct msmsdcc_dma_data *dma_data = struct msmsdcc_host *host = (struct msmsdcc_host *)data;
container_of(cmd, struct msmsdcc_dma_data, hdr);
struct msmsdcc_host *host = dma_data->host;
unsigned long flags; unsigned long flags;
struct mmc_request *mrq; struct mmc_request *mrq;
struct msm_dmov_errdata err;
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
host->dma.active = 0; host->dma.active = 0;
err = host->dma.err;
mrq = host->curr.mrq; mrq = host->curr.mrq;
BUG_ON(!mrq); BUG_ON(!mrq);
WARN_ON(!mrq->data); WARN_ON(!mrq->data);
if (!(result & DMOV_RSLT_VALID)) { if (!(host->dma.result & DMOV_RSLT_VALID)) {
pr_err("msmsdcc: Invalid DataMover result\n"); pr_err("msmsdcc: Invalid DataMover result\n");
goto out; goto out;
} }
if (result & DMOV_RSLT_DONE) { if (host->dma.result & DMOV_RSLT_DONE) {
host->curr.data_xfered = host->curr.xfer_size; host->curr.data_xfered = host->curr.xfer_size;
} else { } else {
/* Error or flush */ /* Error or flush */
if (result & DMOV_RSLT_ERROR) if (host->dma.result & DMOV_RSLT_ERROR)
pr_err("%s: DMA error (0x%.8x)\n", pr_err("%s: DMA error (0x%.8x)\n",
mmc_hostname(host->mmc), result); mmc_hostname(host->mmc), host->dma.result);
if (result & DMOV_RSLT_FLUSH) if (host->dma.result & DMOV_RSLT_FLUSH)
pr_err("%s: DMA channel flushed (0x%.8x)\n", pr_err("%s: DMA channel flushed (0x%.8x)\n",
mmc_hostname(host->mmc), result); mmc_hostname(host->mmc), host->dma.result);
if (err)
pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n", pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n",
err->flush[0], err->flush[1], err->flush[2], err.flush[0], err.flush[1], err.flush[2],
err->flush[3], err->flush[4], err->flush[5]); err.flush[3], err.flush[4], err.flush[5]);
if (!mrq->data->error) if (!mrq->data->error)
mrq->data->error = -EIO; mrq->data->error = -EIO;
} }
...@@ -273,6 +271,22 @@ msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd, ...@@ -273,6 +271,22 @@ msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
return; return;
} }
static void
msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
unsigned int result,
struct msm_dmov_errdata *err)
{
struct msmsdcc_dma_data *dma_data =
container_of(cmd, struct msmsdcc_dma_data, hdr);
struct msmsdcc_host *host = dma_data->host;
dma_data->result = result;
if (err)
memcpy(&dma_data->err, err, sizeof(struct msm_dmov_errdata));
tasklet_schedule(&host->dma_tlet);
}
static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data) static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data)
{ {
if (host->dma.channel == -1) if (host->dma.channel == -1)
...@@ -1118,6 +1132,9 @@ msmsdcc_probe(struct platform_device *pdev) ...@@ -1118,6 +1132,9 @@ msmsdcc_probe(struct platform_device *pdev)
host->dmares = dmares; host->dmares = dmares;
spin_lock_init(&host->lock); spin_lock_init(&host->lock);
tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet,
(unsigned long)host);
/* /*
* Setup DMA * Setup DMA
*/ */
......
...@@ -172,6 +172,8 @@ struct msmsdcc_dma_data { ...@@ -172,6 +172,8 @@ struct msmsdcc_dma_data {
struct msmsdcc_host *host; struct msmsdcc_host *host;
int busy; /* Set if DM is busy */ int busy; /* Set if DM is busy */
int active; int active;
unsigned int result;
struct msm_dmov_errdata err;
}; };
struct msmsdcc_pio_data { struct msmsdcc_pio_data {
...@@ -235,6 +237,7 @@ struct msmsdcc_host { ...@@ -235,6 +237,7 @@ struct msmsdcc_host {
int cmdpoll; int cmdpoll;
struct msmsdcc_stats stats; struct msmsdcc_stats stats;
struct tasklet_struct dma_tlet;
/* Command parameters */ /* Command parameters */
unsigned int cmd_timeout; unsigned int cmd_timeout;
unsigned int cmd_pio_irqmask; unsigned int cmd_pio_irqmask;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册