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>
This commit is contained in:
Adrian Hunter 2011-10-03 15:33:33 +03:00 committed by Chris Ball
parent 88b4767974
commit 08a7e1dfaa

View File

@ -141,12 +141,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);
@ -253,7 +253,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);
}
}
/**