public inbox for linux-mmc@vger.kernel.org
 help / color / mirror / Atom feed
From: Sujit Reddy Thumma <sthumma@codeaurora.org>
To: Per Forlin <per.lkml@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>,
	linux-mmc@vger.kernel.org, linux-arm-msm@vger.kernel.org,
	cjb@laptop.org
Subject: Re: [PATCH] mmc: core: Kill block requests if card is removed
Date: Mon, 14 Nov 2011 09:49:26 +0530	[thread overview]
Message-ID: <4EC096CE.7000003@codeaurora.org> (raw)
In-Reply-To: <CAFEEs1nFkWv5x1RbJ923JJk9C3A3XX84k+=RT1+rd9S1rau99A@mail.gmail.com>

On 11/10/2011 7:50 PM, Per Forlin wrote:
> On Thu, Nov 10, 2011 at 10:35 AM, Adrian Hunter<adrian.hunter@intel.com>  wrote:
>> On 10/11/11 06:02, Sujit Reddy Thumma wrote:
>>> Hi,
>>>> Hi Adrian,
>>>>
>>>> On Wed, Nov 9, 2011 at 10:34 AM, Adrian Hunter<adrian.hunter@intel.com>
>>>> wrote:
>>>>> On 09/11/11 06:31, Sujit Reddy Thumma 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@codeaurora.org>
>>>>>> ---
>>>>>
>>>>>
>>>>> It is safer to have zero initialisations so I suggest inverting
>>>>> the meaning of the state bit i.e.
>>>
>>> Makes sense. Will take care in V2.
>>>
>>>>>
>>>>> #define MMC_STATE_CARD_GONE     (1<<7)          /* card removed from the
>>>>> slot */
>>>>>
>>>>>
>>>>> Also it would be nice is a request did not start if the card is
>>>>> gone.  For the non-async case, that is easy:
>>>>>
>>>> As far as I understand Sujit's patch it will stop new requests from
>>>> being issued, blk_fetch_request(q) returns NULL.
>>>
>>> Yes, Per you are right. The ongoing requests will fail at the controller
>>> driver layer and only the new requests coming to MMC queue layer will be
>>> blocked.
>>>
>>> Adrian's suggestion is to stop all the requests reaching host controller
>>> layer by mmc core. This seems to be a good approach but the problem here is
>>> the host driver should inform mmc core that card is gone.
>>>
>>> Adrian, do you agree if we need to change all the host drivers to set the
>>> MMC_STATE_CARD_GONE flag as soon as the card detect irq handler detects the
>>> card as removed?
>>
>> Typically a card detect interrupt queues a rescan which in turn will have
>> to wait to claim the host.  In the meantime, in the async case, the block
>> driver will not release the host until the queue is empty.
> Here is a patch that let async-mmc release host and reclaim it in case of error.
> When the host is released mmc_rescan will claim the host and run.
> --------------------------------
> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
> index cf73877..8952e63 100644
> --- a/drivers/mmc/card/block.c
> +++ b/drivers/mmc/card/block.c
> @@ -1209,6 +1209,28 @@ static int mmc_blk_cmd_err(struct mmc_blk_data
> *md, struct mmc_card *card,
>   	return ret;
>   }
>
> +/*
> + * This function should be called to resend a request after failure.
> + * Prepares and starts the request.
> + */
> +static inline struct mmc_async_req *mmc_blk_resend(struct mmc_card *card,
> +						   struct mmc_queue *mq,
> +						   struct mmc_queue_req *mqrq,
> +						   int disable_multi,
> +						   struct mmc_async_req *areq)
> +{
> +	/*
> +	 * Release host after failure in case the host is needed
> +	 * by someone else. For instance, if the card is removed the
> +	 * worker thread needs to claim the host in order to do mmc_rescan.
> +	 */
> +	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);
> +}
> +
>   static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
>   {
>   	struct mmc_blk_data *md = mq->data;
> @@ -1308,14 +1330,14 @@ static int mmc_blk_issue_rw_rq(struct
> mmc_queue *mq, struct request *rqc)
>   			break;
>   		}
>
> -		if (ret) {
> +		if (ret)
>   			/*
>   			 * In case of a incomplete request
>   			 * prepare it again and resend.
>   			 */
> -			mmc_blk_rw_rq_prep(mq_rq, card, disable_multi, mq);
> -			mmc_start_req(card->host,&mq_rq->mmc_active, NULL);
> -		}
> +			mmc_blk_prep_start(card, mq, mq_rq, disable_multi,
> +					&mq_rq->mmc_active);
> +

:%s/mmc_blk_prep_start/mmc_blk_resend

>   	} while (ret);
>
>   	return 1;
> @@ -1327,10 +1349,9 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue
> *mq, struct request *rqc)
>   	spin_unlock_irq(&md->lock);
>
>    start_new_req:
> -	if (rqc) {
> -		mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
> -		mmc_start_req(card->host,&mq->mqrq_cur->mmc_active, NULL);
> -	}
> +	if (rqc)
> +		mmc_blk_prep_start(card, mq, mq->mqrq_cur, 0,
> +				&mq->mqrq_cur->mmc_active);
>
>   	return 0;
>   }

Thanks Per. This looks good. Can we split this into a different patch?

> -------------------------------------
>
>
>>   The block
>> driver will see errors and will use a send status command which will fail
>> so the request will be aborted, but the next request will be started
>> anyway.
>>
>> There are two problems:
>>
>> 1. When do we reliably know that the card has really gone?
>>
>> At present, the detect method for SD and MMC is just the send status
>> command, which is what the block driver is doing i.e. if the block
>> driver sees send status fail, after an errored request, and the
>> card is removable, then it is very likely the card has gone.
>>
>> At present, it is not considered that the host controller driver
>> knows whether the card is really gone - just that it might be.
>>
>> Setting a MMC_STATE_CARD_GONE flag early may be a little complicated.
>> e.g. mmc_detect_change() flags that the card may be gone.  After an
>> error, if the "card may be gone" flag is set a new bus method could
>> be called that just does send status.  If that fails, then the
>> MMC_STATE_CARD_GONE flag is set.  Any calls to the detect method
>> must first check the MMC_STATE_CARD_GONE flag so that, once gone,
>> a card can not come back.
>>
>> Maybe you can think of something simpler.

Can we do something like this:

--- 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_card_gone(card);
                 return ERR_ABORT;
+       }

         /* Flag ECC errors */
         if ((status & R1_CARD_ECC_FAILED) ||

and some additions to Per's patch, changes denoted in (++):

+/*
+ * This function should be called to resend a request after failure.
+ * Prepares and starts the request.
+ */
+static inline struct mmc_async_req *mmc_blk_resend(struct mmc_card *card,
+						   struct mmc_queue *mq,
+						   struct mmc_queue_req *mqrq,
+						   int disable_multi,
+						   struct mmc_async_req *areq)
+{
+	/*
+	 * Release host after failure in case the host is needed
+	 * by someone else. For instance, if the card is removed the
+	 * worker thread needs to claim the host in order to do mmc_rescan.
+	 */
+	mmc_release_host(card->host);
+	mmc_claim_host(card->host);
++	if (mmc_card_gone(card)) {
++	/*
++	 * End the pending async request without starting it when card
++	 * is removed.
++	 */
++		req->cmd_flags |= REQ_QUIET;
++		__blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
+	} else {
+		mmc_blk_rw_rq_prep(mqrq, card, disable_multi, mq);
+		return mmc_start_req(card->host, areq, NULL);
+	}
+}
+


>>
>> 2. How can new requests be prevented from starting once the card
>> is gone?
>>
>> Using BLKPREP_KILL will do that for all but the request that has been
>> prepared already (i.e. async case) if the MMC_STATE_CARD_GONE flag is set
>> early enough.
>>
>> Maybe blocking requests at a lower level is not needed.
>>
>>
>>>
>>>>

  reply	other threads:[~2011-11-14  4:19 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-09  4:31 [PATCH] mmc: core: Kill block requests if card is removed Sujit Reddy Thumma
2011-11-09  9:34 ` Adrian Hunter
2011-11-09 20:53   ` Per Forlin
2011-11-09 22:05     ` Per Forlin
2011-11-10  4:13       ` Sujit Reddy Thumma
2011-11-10  4:02     ` Sujit Reddy Thumma
2011-11-10  9:35       ` Adrian Hunter
2011-11-10 14:20         ` Per Forlin
2011-11-14  4:19           ` Sujit Reddy Thumma [this message]
2011-11-14  7:52             ` Per Forlin
2011-11-14  8:24               ` Per Forlin
2011-11-14  8:46                 ` Sujit Reddy Thumma
2011-11-09 21:47 ` Per Forlin
2011-11-10  5:31   ` Sujit Reddy Thumma
2011-11-22 20:18 ` David Taylor
2011-11-24  9:30   ` Per Forlin
2011-11-24 11:31     ` Sujit Reddy Thumma

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=4EC096CE.7000003@codeaurora.org \
    --to=sthumma@codeaurora.org \
    --cc=adrian.hunter@intel.com \
    --cc=cjb@laptop.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=per.lkml@gmail.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox