diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2011-10-03 15:33:33 +0300 |
---|---|---|
committer | Ulf HANSSON <ulf.hansson@stericsson.com> | 2011-10-11 15:54:04 +0200 |
commit | ffed8df76220080d99db7e3fa0174c5a64c5922b (patch) | |
tree | 21e35e73debbea1803cdd32af0aa0a2537116186 /drivers/mmc | |
parent | cf7390b487f2a261db6fedbc8513357c9fc129ed (diff) |
mmc: core: move ->request() call from atomic context
mmc_request_done() is sometimes called from interrupt or other atomic
context. Mostly all mmc_request_done() does is complete(), however it
contains code to retry on error, which uses ->request(). As the error
path is certainly not performance critical, this may be moved to the
waiting function mmc_wait_for_req_done().
This allows ->request() to use runtime PM get_sync() and guarantee it
is never in an atomic context.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Ulf Hansson <ulf.hansson@stericsson.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
Change-Id: I3559026e3736c9c044d1ca2cbbfda0b2b12b4a07
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33707
Reviewed-by: Ulf HANSSON <ulf.hansson@stericsson.com>
Tested-by: Ulf HANSSON <ulf.hansson@stericsson.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/core.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 9461b38b0aa..02d534cfe1d 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -140,12 +140,12 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) } if (err && cmd->retries) { - pr_debug("%s: req failed (CMD%u): %d, retrying...\n", - mmc_hostname(host), cmd->opcode, err); - - cmd->retries--; - cmd->error = 0; - host->ops->request(host, mrq); + /* + * Request starter must handle retries - see + * mmc_wait_for_req_done(). + */ + if (mrq->done) + mrq->done(mrq); } else { mmc_should_fail_request(host, mrq); @@ -252,7 +252,21 @@ static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) static void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq) { - wait_for_completion(&mrq->completion); + struct mmc_command *cmd; + + while (1) { + wait_for_completion(&mrq->completion); + + cmd = mrq->cmd; + if (!cmd->error || !cmd->retries) + break; + + pr_debug("%s: req failed (CMD%u): %d, retrying...\n", + mmc_hostname(host), cmd->opcode, cmd->error); + cmd->retries--; + cmd->error = 0; + host->ops->request(host, mrq); + } } /** |