mmc: Add MMC host software queue support
[linux-2.6-microblaze.git] / drivers / mmc / core / queue.c
index 9edc086..25bee3d 100644 (file)
@@ -62,7 +62,7 @@ enum mmc_issue_type mmc_issue_type(struct mmc_queue *mq, struct request *req)
 {
        struct mmc_host *host = mq->card->host;
 
-       if (mq->use_cqe)
+       if (mq->use_cqe && !host->hsq_enabled)
                return mmc_cqe_issue_type(host, req);
 
        if (req_op(req) == REQ_OP_READ || req_op(req) == REQ_OP_WRITE)
@@ -124,12 +124,14 @@ static enum blk_eh_timer_return mmc_mq_timed_out(struct request *req,
 {
        struct request_queue *q = req->q;
        struct mmc_queue *mq = q->queuedata;
+       struct mmc_card *card = mq->card;
+       struct mmc_host *host = card->host;
        unsigned long flags;
        int ret;
 
        spin_lock_irqsave(&mq->lock, flags);
 
-       if (mq->recovery_needed || !mq->use_cqe)
+       if (mq->recovery_needed || !mq->use_cqe || host->hsq_enabled)
                ret = BLK_EH_RESET_TIMER;
        else
                ret = mmc_cqe_timed_out(req);
@@ -144,12 +146,13 @@ static void mmc_mq_recovery_handler(struct work_struct *work)
        struct mmc_queue *mq = container_of(work, struct mmc_queue,
                                            recovery_work);
        struct request_queue *q = mq->queue;
+       struct mmc_host *host = mq->card->host;
 
        mmc_get_card(mq->card, &mq->ctx);
 
        mq->in_recovery = true;
 
-       if (mq->use_cqe)
+       if (mq->use_cqe && !host->hsq_enabled)
                mmc_blk_cqe_recovery(mq);
        else
                mmc_blk_mq_recovery(mq);
@@ -160,6 +163,9 @@ static void mmc_mq_recovery_handler(struct work_struct *work)
        mq->recovery_needed = false;
        spin_unlock_irq(&mq->lock);
 
+       if (host->hsq_enabled)
+               host->cqe_ops->cqe_recovery_finish(host);
+
        mmc_put_card(mq->card, &mq->ctx);
 
        blk_mq_run_hw_queues(q, true);
@@ -279,6 +285,14 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
                }
                break;
        case MMC_ISSUE_ASYNC:
+               /*
+                * For MMC host software queue, we only allow 2 requests in
+                * flight to avoid a long latency.
+                */
+               if (host->hsq_enabled && mq->in_flight[issue_type] > 2) {
+                       spin_unlock_irq(&mq->lock);
+                       return BLK_STS_RESOURCE;
+               }
                break;
        default:
                /*
@@ -430,7 +444,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card)
         * The queue depth for CQE must match the hardware because the request
         * tag is used to index the hardware queue.
         */
-       if (mq->use_cqe)
+       if (mq->use_cqe && !host->hsq_enabled)
                mq->tag_set.queue_depth =
                        min_t(int, card->ext_csd.cmdq_depth, host->cqe_qdepth);
        else