diff options
author | Ulf Hansson <ulf.hansson@stericsson.com> | 2012-03-05 09:52:43 -0500 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-03-27 12:20:04 -0400 |
commit | 956d9fd5eb3cbb322440844ed341145707bd71f8 (patch) | |
tree | 8ad90a2718b202c4bee5fee7366fca715820a62b | |
parent | 907d2e7cc7ebba4ab398422a7f0435e1802be65b (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.c | 35 |
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 | ||
252 | static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) | 252 | static 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 | ||
264 | static void mmc_wait_for_req_done(struct mmc_host *host, | 265 | static 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; |