This is 2nd step change in a bid to enable mapping of multiple
device hardware queues to a single CPU.

It enables number of tags assigned to a hardware context to exceed
the device hardware queue depth. As result single hardware context
could be mapped to multiple low-level hardware contexts. This is a
prerequisite to introduce combined hardware contexts.

CC: Jens Axboe <ax...@kernel.dk>
CC: linux-n...@lists.infradead.org
Signed-off-by: Alexander Gordeev <agord...@redhat.com>
---
 block/blk-core.c       | 4 +++-
 block/blk-mq.c         | 9 +++++++--
 include/linux/blk-mq.h | 7 +++++++
 3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index bf4f196..36ae127 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -3312,9 +3312,11 @@ bool blk_poll(struct request_queue *q, blk_qc_t cookie)
 
        state = current->state;
        while (!need_resched()) {
+               unsigned int tag = blk_qc_t_to_tag(cookie);
                unsigned int queue_num = blk_qc_t_to_queue_num(cookie);
                struct blk_mq_hw_ctx *hctx = q->queue_hw_ctx[queue_num];
-               struct blk_mq_llhw_ctx *llhw_ctx = &hctx->llhw_ctxs[0];
+               int idx = blk_mq_tag_to_llhw_ctx_idx(hctx, tag);
+               struct blk_mq_llhw_ctx *llhw_ctx = &hctx->llhw_ctxs[idx];
                int ret;
 
                hctx->poll_invoked++;
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 274eab8..6d055ec 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -829,6 +829,7 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx 
*hctx)
        queued = 0;
        while (!list_empty(&rq_list)) {
                struct blk_mq_queue_data bd;
+               int llhw_ctx_idx;
                int ret;
 
                rq = list_first_entry(&rq_list, struct request, queuelist);
@@ -838,7 +839,9 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx 
*hctx)
                bd.list = dptr;
                bd.last = list_empty(&rq_list);
 
-               ret = q->mq_ops->queue_rq(&hctx->llhw_ctxs[0], &bd);
+               llhw_ctx_idx = blk_mq_tag_to_llhw_ctx_idx(hctx, rq->tag);
+
+               ret = q->mq_ops->queue_rq(&hctx->llhw_ctxs[llhw_ctx_idx], &bd);
                switch (ret) {
                case BLK_MQ_RQ_QUEUE_OK:
                        queued++;
@@ -1260,13 +1263,14 @@ static int blk_mq_direct_issue_request(struct request 
*rq, blk_qc_t *cookie)
                .last = 1
        };
        blk_qc_t new_cookie = blk_tag_to_qc_t(rq->tag, hctx->queue_num);
+       int llhw_ctx_idx = blk_mq_tag_to_llhw_ctx_idx(hctx, rq->tag);
 
        /*
         * For OK queue, we are done. For error, kill it. Any other
         * error (busy), just add it to our list as we previously
         * would have done
         */
-       ret = q->mq_ops->queue_rq(&hctx->llhw_ctxs[0], &bd);
+       ret = q->mq_ops->queue_rq(&hctx->llhw_ctxs[llhw_ctx_idx], &bd);
        if (ret == BLK_MQ_RQ_QUEUE_OK) {
                *cookie = new_cookie;
                return 0;
@@ -1741,6 +1745,7 @@ static struct blk_mq_hw_ctx *blk_mq_init_hctx(struct 
request_queue *q,
        hctx->queue_num = hctx_idx;
        hctx->nr_ctx = 0;
        hctx->nr_llhw_ctx = nr_llhw_ctx;
+       hctx->llhw_queue_depth = set->queue_depth;
        hctx->flags = set->flags & ~BLK_MQ_F_TAG_SHARED;
        hctx->tags = set->tags[hctx_idx];
 
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 2c3392b..52a9e7c 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -67,6 +67,7 @@ struct blk_mq_hw_ctx {
        unsigned long           poll_invoked;
        unsigned long           poll_success;
 
+       unsigned int            llhw_queue_depth;
        unsigned int            nr_llhw_ctx;
        struct blk_mq_llhw_ctx  llhw_ctxs[0];
 };
@@ -79,6 +80,12 @@ struct blk_mq_hw_ctx *blk_mq_to_hctx(struct blk_mq_llhw_ctx 
*llhw_ctx)
        return (void *)llhw_ctx_0 - offsetof(struct blk_mq_hw_ctx, llhw_ctxs);
 }
 
+static inline
+int blk_mq_tag_to_llhw_ctx_idx(struct blk_mq_hw_ctx *hctx, unsigned int tag)
+{
+       return tag / hctx->llhw_queue_depth;
+}
+
 struct blk_mq_tag_set {
        struct blk_mq_ops       *ops;
        unsigned int            nr_hw_queues;
-- 
1.8.3.1

Reply via email to