summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/card/queue.c40
1 files changed, 24 insertions, 16 deletions
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index ba3949adbe48..3fcd18353eca 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -686,12 +686,6 @@ void mmc_cmdq_clean(struct mmc_queue *mq, struct mmc_card *card)
mq->mqrq_cmdq = NULL;
}
-static void mmc_wait_for_pending_reqs(struct mmc_queue *mq)
-{
- wait_for_completion(&mq->cmdq_shutdown_complete);
- mq->cmdq_shutdown(mq);
-}
-
/**
* mmc_queue_suspend - suspend a MMC request queue
* @mq: MMC queue to suspend
@@ -708,22 +702,36 @@ int mmc_queue_suspend(struct mmc_queue *mq, int wait)
int rc = 0;
struct mmc_card *card = mq->card;
- if (card->cmdq_init && blk_queue_tagged(q) && wait) {
+ if (card->cmdq_init && blk_queue_tagged(q)) {
struct mmc_host *host = card->host;
spin_lock_irqsave(q->queue_lock, flags);
blk_stop_queue(q);
spin_unlock_irqrestore(q->queue_lock, flags);
- /*
- * Wait for already queued requests to be issued by
- * mmc_cmdqd.
- */
- down(&mq->thread_sem);
- /* Wait for already issued requests to complete */
- if (host->cmdq_ctx.active_reqs)
- mmc_wait_for_pending_reqs(mq);
- mq->cmdq_shutdown(mq);
+ if (wait) {
+ /*
+ * Wait for already queued requests to be issued by
+ * mmc_cmdqd.
+ */
+ down(&mq->thread_sem);
+ /* Wait for already issued requests to complete */
+ if (host->cmdq_ctx.active_reqs)
+ wait_for_completion(
+ &mq->cmdq_shutdown_complete);
+
+ mq->cmdq_shutdown(mq);
+ } else if (!test_and_set_bit(MMC_QUEUE_SUSPENDED, &mq->flags)) {
+ rc = down_trylock(&mq->thread_sem);
+ if (rc || host->cmdq_ctx.active_reqs) {
+ clear_bit(MMC_QUEUE_SUSPENDED, &mq->flags);
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_start_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+ rc = -EBUSY;
+ }
+ }
+
goto out;
}