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 <subhashj@codeaurora.org>
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index f01ddab..d975543 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -3130,11 +3130,11 @@
/* Silent the block layer */
if (md) {
- rc = mmc_queue_suspend(&md->queue);
+ rc = mmc_queue_suspend(&md->queue, 1);
if (rc)
goto suspend_error;
list_for_each_entry(part_md, &md->part, part) {
- rc = mmc_queue_suspend(&part_md->queue);
+ rc = mmc_queue_suspend(&part_md->queue, 1);
if (rc)
goto suspend_error;
}
@@ -3161,11 +3161,11 @@
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 0e024dd..507cd5b 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -438,12 +438,13 @@
/**
* 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;
@@ -457,7 +458,7 @@
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.
@@ -467,6 +468,9 @@
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 9280d1b..d1fe01c 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -60,7 +60,7 @@
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 *,