Introduce blk_mq_dev_map_queues so that we can remove all kinds of map_queues implementation(pci, virtio, rdma, ...) out of block layer. Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx> --- block/blk-mq-map.c | 53 ++++++++++++++++++++++++++++++++++++++++++ include/linux/blk-mq.h | 5 ++++ 2 files changed, 58 insertions(+) diff --git a/block/blk-mq-map.c b/block/blk-mq-map.c index 3db84d3197f1..e3ba2ef1e9e2 100644 --- a/block/blk-mq-map.c +++ b/block/blk-mq-map.c @@ -94,3 +94,56 @@ int blk_mq_hw_queue_to_node(struct blk_mq_queue_map *qmap, unsigned int index) return NUMA_NO_NODE; } + +/** + * blk_mq_dev_map_queues - provide generic queue mapping + * @qmap: CPU to hardware queue map. + * @dev_off: Offset to use for the device + * @get_queue_affinity: Callback to retrieve queue affinity + * @dev_data: Device data passed to get_queue_affinity() + * @fallback: If true, fallback to default blk-mq mapping in case of + * any failure + * + * Generic function to setup each queue mapping in @qmap. It will query + * each queue's affinity via @get_queue_affinity and built queue mapping + * that maps a queue to the CPUs in the queue affinity. + * + * Driver has to set correct @dev_data, so that the driver callback + * of @get_queue_affinity can work correctly. + */ +int blk_mq_dev_map_queues(struct blk_mq_queue_map *qmap, void *dev_data, + int dev_off, get_queue_affinty_fn *get_queue_affinity, + bool fallback) +{ + const struct cpumask *mask; + unsigned int queue, cpu; + + /* + * fallback to default mapping if driver doesn't provide + * get_queue_affinity callback + */ + if (!get_queue_affinity) { + fallback = true; + goto fallback; + } + + for (queue = 0; queue < qmap->nr_queues; queue++) { + mask = get_queue_affinity(dev_data, dev_off, queue); + if (!mask) + goto fallback; + + for_each_cpu(cpu, mask) + qmap->mq_map[cpu] = qmap->queue_offset + queue; + } + + return 0; + +fallback: + if (!fallback) { + WARN_ON_ONCE(qmap->nr_queues > 1); + blk_mq_clear_mq_map(qmap); + return 0; + } + return blk_mq_map_queues(qmap); +} +EXPORT_SYMBOL_GPL(blk_mq_dev_map_queues); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index fd2de2b422ed..b6090d691594 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -553,7 +553,12 @@ void blk_mq_freeze_queue_wait(struct request_queue *q); int blk_mq_freeze_queue_wait_timeout(struct request_queue *q, unsigned long timeout); +typedef const struct cpumask * (get_queue_affinty_fn)(void *dev_data, + int dev_off, int queue_idx); int blk_mq_map_queues(struct blk_mq_queue_map *qmap); +int blk_mq_dev_map_queues(struct blk_mq_queue_map *qmap, void *dev_data, + int dev_off, get_queue_affinty_fn *get_queue_affinity, + bool fallback); void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues); void blk_mq_quiesce_queue_nowait(struct request_queue *q); -- 2.31.1