Re: [PATCH V2] mmc: Kill block requests if card is removed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Sujit,

On Tue, Nov 22, 2011 at 11:56 AM, Sujit Reddy Thumma
<sthumma@xxxxxxxxxxxxxx> 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 <sthumma@xxxxxxxxxxxxxx>
>
> ---
> 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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux