diff options
-rw-r--r-- | drivers/mmc/host/msm_sdcc.c | 49 | ||||
-rw-r--r-- | drivers/mmc/host/msm_sdcc.h | 3 |
2 files changed, 36 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 | ||
191 | static void | 191 | static void |
192 | msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd, | 192 | msmsdcc_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 | ||
274 | static void | ||
275 | msmsdcc_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 | |||
276 | static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data) | 290 | static 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 | */ |
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h index ff2b0f74f6f4..996990dfc7cc 100644 --- a/drivers/mmc/host/msm_sdcc.h +++ b/drivers/mmc/host/msm_sdcc.h | |||
@@ -172,6 +172,8 @@ struct msmsdcc_dma_data { | |||
172 | struct msmsdcc_host *host; | 172 | struct msmsdcc_host *host; |
173 | int busy; /* Set if DM is busy */ | 173 | int busy; /* Set if DM is busy */ |
174 | int active; | 174 | int active; |
175 | unsigned int result; | ||
176 | struct msm_dmov_errdata err; | ||
175 | }; | 177 | }; |
176 | 178 | ||
177 | struct msmsdcc_pio_data { | 179 | struct msmsdcc_pio_data { |
@@ -235,6 +237,7 @@ struct msmsdcc_host { | |||
235 | int cmdpoll; | 237 | int cmdpoll; |
236 | struct msmsdcc_stats stats; | 238 | struct msmsdcc_stats stats; |
237 | 239 | ||
240 | struct tasklet_struct dma_tlet; | ||
238 | /* Command parameters */ | 241 | /* Command parameters */ |
239 | unsigned int cmd_timeout; | 242 | unsigned int cmd_timeout; |
240 | unsigned int cmd_pio_irqmask; | 243 | unsigned int cmd_pio_irqmask; |