aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2011-10-03 15:33:33 +0300
committerRobert Marklund <robert.marklund@stericsson.com>2011-10-27 16:08:27 +0200
commitd3d896856c87d0b1d7aed6948614d34be4e91ff4 (patch)
tree7c747b6a7398d35ebd1429db6bcacbf955882c89
parent3970fd88af4b0a67f92a30dc448ccd38fd468f4a (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>
-rw-r--r--drivers/mmc/core/core.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 31b9c09d87a..139ecef5e96 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);
+ }
}
/**