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