Hi Sujit,
On Tue, Nov 22, 2011 at 11:56 AM, Sujit Reddy Thumma
<[email protected]> wrote:
> Kill block requests when the host knows that the card is
> removed from the slot and is sure that subsequent requests
> are bound to fail. Do this silently so that the block
> layer doesn't output unnecessary error messages.
>
> This patch implements suggestion from Adrian Hunter,
> http://thread.gmane.org/gmane.linux.kernel.mmc/2714/focus=3474
>
> Signed-off-by: Sujit Reddy Thumma <[email protected]>
>
> ---
> Changes in v2:
> - Changed the implementation with further comments from Adrian
> - Set the card removed flag in bus notifier callbacks
> - This patch is now dependent on patch from Per Forlin:
> http://thread.gmane.org/gmane.linux.kernel.mmc/11128/focus=11211
> ---
> drivers/mmc/card/block.c | 33 ++++++++++++++++++++++++++++-----
> drivers/mmc/card/queue.c | 5 +++++
> drivers/mmc/core/bus.c | 32 +++++++++++++++++++++++++++++++-
> drivers/mmc/core/core.c | 8 +++++++-
> include/linux/mmc/card.h | 3 +++
> 5 files changed, 74 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
> index edc379e..83956fa 100644
> --- a/drivers/mmc/card/block.c
> +++ b/drivers/mmc/card/block.c
> @@ -648,8 +648,15 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card,
> struct request *req,
> }
>
> /* We couldn't get a response from the card. Give up. */
> - if (err)
> + if (err) {
> + /*
> + * If the card didn't respond to status command,
> + * it is likely that card is gone. Flag it as removed,
> + * mmc_detect_change() cleans the rest.
> + */
> + mmc_card_set_removed(card);
> return ERR_ABORT;
> + }
>
> /* Flag ECC errors */
> if ((status & R1_CARD_ECC_FAILED) ||
> @@ -1168,6 +1175,9 @@ static inline struct mmc_async_req
> *mmc_blk_resend(struct mmc_card *card,
> int disable_multi,
> struct mmc_async_req *areq)
> {
> + struct mmc_blk_data *md = mmc_get_drvdata(card);
> + struct request *req = mqrq->req;
> + int ret;
> /*
> * Release host after failure in case the host is needed
> * by someone else. For instance, if the card is removed the
> @@ -1175,11 +1185,24 @@ static inline struct mmc_async_req
> *mmc_blk_resend(struct mmc_card *card,
> */
> mmc_release_host(card->host);
> mmc_claim_host(card->host);
> -
> - mmc_blk_rw_rq_prep(mqrq, card, disable_multi, mq);
> - return mmc_start_req(card->host, areq, NULL);
> + if (mmc_card_removed(card)) {
> + /*
> + * End the pending async request without starting
> + * it when card is removed.
> + */
> + spin_lock_irq(&md->lock);
> + req->cmd_flags |= REQ_QUIET;
> + do {
> + ret = __blk_end_request(req,
> + -EIO, blk_rq_cur_bytes(req));
> + } while (ret);
> + spin_unlock_irq(&md->lock);
> + return NULL;
> + } else {
> + mmc_blk_rw_rq_prep(mqrq, card, disable_multi, mq);
> + return mmc_start_req(card->host, areq, NULL);
> + }
mmc_blk_resend is only called to resend a request that has failed. If
the card is removed the request will still be issued, but when it
retries it will give up here.
You have added a check in mmc_wait_for_req(). What about this:
--------------------------
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index b526036..dcdcb9a 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -287,11 +287,17 @@ static void mmc_wait_done(struct mmc_request *mrq)
complete(&mrq->completion);
}
-static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
+static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
{
- init_completion(&mrq->completion);
- mrq->done = mmc_wait_done;
- mmc_start_request(host, mrq);
+ if (mmc_card_removed(host->card)) {
+ mrq->cmd->error = -ENOMEDIUM;
+ return -ENOMEDIUM;
+ }
+
+ init_completion(&mrq->completion);
+ mrq->done = mmc_wait_done;
+ mmc_start_request(host, mrq);
+ return 0;
}
static void mmc_wait_for_req_done(struct mmc_host *host,
@@ -418,7 +424,8 @@ EXPORT_SYMBOL(mmc_start_req);
*/
void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
{
- __mmc_start_req(host, mrq);
+ if (__mmc_start_req(host, mrq))
+ return
mmc_wait_for_req_done(host, mrq);
}
EXPORT_SYMBOL(mmc_wait_for_req);
----------------------------------
This patch will set error to -ENOMEDIUM for both mmc_start_req() and
mmc_wait_for_req()
mmc_blk_err_check() can check for -ENOMEDIUM and return something like
MMC_BLK_ENOMEDIUM
And eventually do
+ /*
+ * End the pending async request without starting
+ * it when card is removed.
+ */
+ spin_lock_irq(&md->lock);
+ req->cmd_flags |= REQ_QUIET;
+ do {
+ ret = __blk_end_request(req,
+ -EIO, blk_rq_cur_bytes(req));
+ } while (ret);
+ spin_unlock_irq(&md->lock);
Regards,
Per
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html