aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@stericsson.com>2012-03-05 09:52:43 -0500
committerChris Ball <cjb@laptop.org>2012-03-27 12:20:04 -0400
commit956d9fd5eb3cbb322440844ed341145707bd71f8 (patch)
tree8ad90a2718b202c4bee5fee7366fca715820a62b
parent907d2e7cc7ebba4ab398422a7f0435e1802be65b (diff)
mmc: core: Clean up after mmc_pre_req if card was removed
Make sure mmc_start_req cancels the prepared job, if the request was prevented to be started due to the card has been removed. This bug was introduced in commit: mmc: allow upper layers to know immediately if card has been removed Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com> Reviewed-by: Per Forlin <per.forlin@stericsson.com> Tested-by: Jaehoon Chung <jh80.chung@samsung.com> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/core/core.c35
1 files changed, 15 insertions, 20 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9b56674ddc2a..14f262e9246d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -249,16 +249,17 @@ static void mmc_wait_done(struct mmc_request *mrq)
249 complete(&mrq->completion); 249 complete(&mrq->completion);
250} 250}
251 251
252static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) 252static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
253{ 253{
254 init_completion(&mrq->completion); 254 init_completion(&mrq->completion);
255 mrq->done = mmc_wait_done; 255 mrq->done = mmc_wait_done;
256 if (mmc_card_removed(host->card)) { 256 if (mmc_card_removed(host->card)) {
257 mrq->cmd->error = -ENOMEDIUM; 257 mrq->cmd->error = -ENOMEDIUM;
258 complete(&mrq->completion); 258 complete(&mrq->completion);
259 return; 259 return -ENOMEDIUM;
260 } 260 }
261 mmc_start_request(host, mrq); 261 mmc_start_request(host, mrq);
262 return 0;
262} 263}
263 264
264static void mmc_wait_for_req_done(struct mmc_host *host, 265static void mmc_wait_for_req_done(struct mmc_host *host,
@@ -342,6 +343,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
342 struct mmc_async_req *areq, int *error) 343 struct mmc_async_req *areq, int *error)
343{ 344{
344 int err = 0; 345 int err = 0;
346 int start_err = 0;
345 struct mmc_async_req *data = host->areq; 347 struct mmc_async_req *data = host->areq;
346 348
347 /* Prepare a new request */ 349 /* Prepare a new request */
@@ -351,30 +353,23 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
351 if (host->areq) { 353 if (host->areq) {
352 mmc_wait_for_req_done(host, host->areq->mrq); 354 mmc_wait_for_req_done(host, host->areq->mrq);
353 err = host->areq->err_check(host->card, host->areq); 355 err = host->areq->err_check(host->card, host->areq);
354 if (err) {
355 /* post process the completed failed request */
356 mmc_post_req(host, host->areq->mrq, 0);
357 if (areq)
358 /*
359 * Cancel the new prepared request, because
360 * it can't run until the failed
361 * request has been properly handled.
362 */
363 mmc_post_req(host, areq->mrq, -EINVAL);
364
365 host->areq = NULL;
366 goto out;
367 }
368 } 356 }
369 357
370 if (areq) 358 if (!err && areq)
371 __mmc_start_req(host, areq->mrq); 359 start_err = __mmc_start_req(host, areq->mrq);
372 360
373 if (host->areq) 361 if (host->areq)
374 mmc_post_req(host, host->areq->mrq, 0); 362 mmc_post_req(host, host->areq->mrq, 0);
375 363
376 host->areq = areq; 364 /* Cancel a prepared request if it was not started. */
377 out: 365 if ((err || start_err) && areq)
366 mmc_post_req(host, areq->mrq, -EINVAL);
367
368 if (err)
369 host->areq = NULL;
370 else
371 host->areq = areq;
372
378 if (error) 373 if (error)
379 *error = err; 374 *error = err;
380 return data; 375 return data;