aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/msm_sdcc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/msm_sdcc.c')
-rw-r--r--drivers/mmc/host/msm_sdcc.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 1290d14c5839..b147971a96ef 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -189,42 +189,40 @@ msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd)
189} 189}
190 190
191static void 191static void
192msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd, 192msmsdcc_dma_complete_tlet(unsigned long data)
193 unsigned int result,
194 struct msm_dmov_errdata *err)
195{ 193{
196 struct msmsdcc_dma_data *dma_data = 194 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
197 container_of(cmd, struct msmsdcc_dma_data, hdr);
198 struct msmsdcc_host *host = dma_data->host;
199 unsigned long flags; 195 unsigned long flags;
200 struct mmc_request *mrq; 196 struct mmc_request *mrq;
197 struct msm_dmov_errdata err;
201 198
202 spin_lock_irqsave(&host->lock, flags); 199 spin_lock_irqsave(&host->lock, flags);
203 host->dma.active = 0; 200 host->dma.active = 0;
204 201
202 err = host->dma.err;
205 mrq = host->curr.mrq; 203 mrq = host->curr.mrq;
206 BUG_ON(!mrq); 204 BUG_ON(!mrq);
207 WARN_ON(!mrq->data); 205 WARN_ON(!mrq->data);
208 206
209 if (!(result & DMOV_RSLT_VALID)) { 207 if (!(host->dma.result & DMOV_RSLT_VALID)) {
210 pr_err("msmsdcc: Invalid DataMover result\n"); 208 pr_err("msmsdcc: Invalid DataMover result\n");
211 goto out; 209 goto out;
212 } 210 }
213 211
214 if (result & DMOV_RSLT_DONE) { 212 if (host->dma.result & DMOV_RSLT_DONE) {
215 host->curr.data_xfered = host->curr.xfer_size; 213 host->curr.data_xfered = host->curr.xfer_size;
216 } else { 214 } else {
217 /* Error or flush */ 215 /* Error or flush */
218 if (result & DMOV_RSLT_ERROR) 216 if (host->dma.result & DMOV_RSLT_ERROR)
219 pr_err("%s: DMA error (0x%.8x)\n", 217 pr_err("%s: DMA error (0x%.8x)\n",
220 mmc_hostname(host->mmc), result); 218 mmc_hostname(host->mmc), host->dma.result);
221 if (result & DMOV_RSLT_FLUSH) 219 if (host->dma.result & DMOV_RSLT_FLUSH)
222 pr_err("%s: DMA channel flushed (0x%.8x)\n", 220 pr_err("%s: DMA channel flushed (0x%.8x)\n",
223 mmc_hostname(host->mmc), result); 221 mmc_hostname(host->mmc), host->dma.result);
224 if (err) 222
225 pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n", 223 pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n",
226 err->flush[0], err->flush[1], err->flush[2], 224 err.flush[0], err.flush[1], err.flush[2],
227 err->flush[3], err->flush[4], err->flush[5]); 225 err.flush[3], err.flush[4], err.flush[5]);
228 if (!mrq->data->error) 226 if (!mrq->data->error)
229 mrq->data->error = -EIO; 227 mrq->data->error = -EIO;
230 } 228 }
@@ -273,6 +271,22 @@ out:
273 return; 271 return;
274} 272}
275 273
274static void
275msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
276 unsigned int result,
277 struct msm_dmov_errdata *err)
278{
279 struct msmsdcc_dma_data *dma_data =
280 container_of(cmd, struct msmsdcc_dma_data, hdr);
281 struct msmsdcc_host *host = dma_data->host;
282
283 dma_data->result = result;
284 if (err)
285 memcpy(&dma_data->err, err, sizeof(struct msm_dmov_errdata));
286
287 tasklet_schedule(&host->dma_tlet);
288}
289
276static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data) 290static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data)
277{ 291{
278 if (host->dma.channel == -1) 292 if (host->dma.channel == -1)
@@ -1118,6 +1132,9 @@ msmsdcc_probe(struct platform_device *pdev)
1118 host->dmares = dmares; 1132 host->dmares = dmares;
1119 spin_lock_init(&host->lock); 1133 spin_lock_init(&host->lock);
1120 1134
1135 tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet,
1136 (unsigned long)host);
1137
1121 /* 1138 /*
1122 * Setup DMA 1139 * Setup DMA
1123 */ 1140 */