From 65dee48836422bcaa97b84b6f30a96d45bfa15fe Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Thu, 20 Jun 2013 18:15:50 +0530 Subject: [PATCH] mmc: block: fix the block driver shutdown mmc_queue_suspend() function returns the -EBUSY error if the MMC request queue is not empty as this function was getting called from the system suspend path which enforces time limit on the completion of the driver suspend callback. But recently the driver shutdown routine also started using mmc_queue_suspend() function but in shutdown case, we would really want to wait for the MMC request queue to be empty. To fix above issue, this change have added new argument named "wait" to mmc_queue_suspend() function which would tell whether it needs to wait for the MMC request queue to be empty or not. Driver shutdown callback will tell the mmc_queue_suspend() to wait but suspend callback won't. CRs-Fixed: 503227 Change-Id: I86f32d68ec4c4799648785681c5776f090ea6e36 Signed-off-by: Subhash Jadavani --- drivers/mmc/card/block.c | 4 ++-- drivers/mmc/card/queue.c | 8 ++++++-- drivers/mmc/card/queue.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 06748b32d5d4..c3abd5c6ce52 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -3180,11 +3180,11 @@ static int _mmc_blk_suspend(struct mmc_card *card) int rc = 0; if (md) { - rc = mmc_queue_suspend(&md->queue); + rc = mmc_queue_suspend(&md->queue, 0); if (rc) goto out; list_for_each_entry(part_md, &md->part, part) { - rc = mmc_queue_suspend(&part_md->queue); + rc = mmc_queue_suspend(&part_md->queue, 0); if (rc) goto out_resume; } diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index de3c1dd0a569..4756193e9a0f 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -421,12 +421,13 @@ void mmc_packed_clean(struct mmc_queue *mq) /** * mmc_queue_suspend - suspend a MMC request queue * @mq: MMC queue to suspend + * @wait: Wait till MMC request queue is empty * * Stop the block request queue, and wait for our thread to * complete any outstanding requests. This ensures that we * won't suspend while a request is being processed. */ -int mmc_queue_suspend(struct mmc_queue *mq) +int mmc_queue_suspend(struct mmc_queue *mq, int wait) { struct request_queue *q = mq->queue; unsigned long flags; @@ -440,7 +441,7 @@ int mmc_queue_suspend(struct mmc_queue *mq) spin_unlock_irqrestore(q->queue_lock, flags); rc = down_trylock(&mq->thread_sem); - if (rc) { + if (rc && !wait) { /* * Failed to take the lock so better to abort the * suspend because mmcqd thread is processing requests. @@ -450,6 +451,9 @@ int mmc_queue_suspend(struct mmc_queue *mq) blk_start_queue(q); spin_unlock_irqrestore(q->queue_lock, flags); rc = -EBUSY; + } else if (rc && wait) { + down(&mq->thread_sem); + rc = 0; } } return rc; diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index 900137715ceb..2e23b6d849ae 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h @@ -69,7 +69,7 @@ struct mmc_queue { extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *, const char *); extern void mmc_cleanup_queue(struct mmc_queue *); -extern int mmc_queue_suspend(struct mmc_queue *); +extern int mmc_queue_suspend(struct mmc_queue *, int); extern void mmc_queue_resume(struct mmc_queue *); extern unsigned int mmc_queue_map_sg(struct mmc_queue *,