From: Chuanxiao Dong <chuanxiao.dong@intel.com>
To: linux-mmc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, cjb@laptop.org, akpm@linux-foundation.org
Subject: [PATCH v6 2/3]mmc: do HW reset if eMMC card occurs timeout error
Date: Mon, 27 Dec 2010 18:13:55 +0800 [thread overview]
Message-ID: <20101227101355.GC20143@intel.com> (raw)
Two new callbacks were added in mmc_bus_ops to implement this.
hwreset_emmc: trigger a RST_n signal for host to reset card.
reinit_emmc: reinitialize eMMC card after hardware reset occurs.
MMC core layer will check whether occurs a timeout error in the new added
function mmc_handle_timeout_error.
Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
---
drivers/mmc/card/block.c | 10 +++++++++
drivers/mmc/core/core.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/mmc/core/core.h | 26 ++++++++++++++++++++++++
include/linux/mmc/core.h | 1 +
4 files changed, 85 insertions(+), 0 deletions(-)
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 217f820..ba9614d 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -424,6 +424,16 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
mmc_wait_for_req(card->host, &brq.mrq);
+ /* Check if need to do HW reset */
+ if (brq.cmd.error)
+ mmc_handle_timeout_error(card->host, brq.cmd.error);
+
+ if (brq.data.error)
+ mmc_handle_timeout_error(card->host, brq.data.error);
+
+ if (brq.stop.error)
+ mmc_handle_timeout_error(card->host, brq.stop.error);
+
mmc_queue_bounce_post(mq);
/*
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index a8e89f3..795bd81 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -83,6 +83,52 @@ static void mmc_flush_scheduled_work(void)
}
/**
+ * mmc_handle_timeout_error - handle timeout errors occurs by card
+ * @host: MMC host used to handle error
+ * @error: error condition
+ *
+ * check whether there is a command or data timeout error occurred,
+ * if so, reset and reinit eMMC card if card has such capability.
+ *
+ * In this function, driver will do follow things:
+ * 1. let host controller do a specific hardware reset for eMMC
+ * card (trigger RST_n signal).
+ * 2. after reset done, reinit eMMC card.
+ */
+void mmc_handle_timeout_error(struct mmc_host *host, int error)
+{
+ struct mmc_card *card = host->card;
+
+ /*
+ * If error condition is not timeout, do nothing
+ */
+ if (error != -ETIMEDOUT)
+ return;
+ /*
+ * make sure card is not NULL
+ * make sure mmc_card has HW reset capability
+ */
+ if (!card || !card->ext_csd.rst)
+ return;
+
+ /* check whether host has such callback */
+ if (!host->bus_ops->hwreset_emmc ||
+ !host->bus_ops->reinit_emmc)
+ return;
+
+ /*
+ * if there occurs any timeout error, HW reset
+ * eMMC card and reinit again.
+ */
+ if (host->bus_ops->hwreset_emmc(host))
+ pr_warn("MMC card reset failed\n");
+ else
+ if (host->bus_ops->reinit_emmc(host))
+ pr_warn("MMC card reinit failed\n");
+}
+EXPORT_SYMBOL(mmc_handle_timeout_error);
+
+/**
* mmc_request_done - finish processing an MMC request
* @host: MMC host which completed request
* @mrq: MMC request which request
@@ -1341,6 +1387,8 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
if (err) {
printk(KERN_ERR "mmc_erase: erase error %d, status %#x\n",
err, cmd.resp[0]);
+ /* Before return, check whether can do a HW reset */
+ mmc_handle_timeout_error(card->host, cmd.error);
err = -EIO;
goto out;
}
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 026c975..09b6c54 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -24,6 +24,32 @@ struct mmc_bus_ops {
int (*resume)(struct mmc_host *);
int (*power_save)(struct mmc_host *);
int (*power_restore)(struct mmc_host *);
+ /*
+ * New added callback
+ * This function is used to reinitialize eMMC card after eMMC card been
+ * reset.
+ *
+ * Note 1: before calling this, mmc_claim_host is needed. After finish
+ * this calling, mmc_release_host is needed.
+ *
+ * return value:
+ * 0 - successfully reinit card
+ * other - failed to reinit
+ */
+ int (*reinit_emmc)(struct mmc_host *);
+ /*
+ * New added callback
+ * This function is used to trigger RST_n signal to reset eMMC card as
+ * eMMC4.4 spec recommended.
+ *
+ * Note 1: this function may sleep since delay is needed when pull
+ * up/down GPIO line.
+ *
+ * return value:
+ * 0 - successfully reset eMMC card
+ * other - failed to reset eMMC card
+ */
+ int (*hwreset_emmc)(struct mmc_host *);
};
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 64e013f..115d589 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -131,6 +131,7 @@ struct mmc_request {
struct mmc_host;
struct mmc_card;
+extern void mmc_handle_timeout_error(struct mmc_host *, int);
extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
--
1.6.6.1
reply other threads:[~2010-12-27 10:13 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20101227101355.GC20143@intel.com \
--to=chuanxiao.dong@intel.com \
--cc=akpm@linux-foundation.org \
--cc=cjb@laptop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mmc@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.