Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 12e3d3cd authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-4.9/block-irq' of git://git.kernel.dk/linux-block

Pull blk-mq irq/cpu mapping updates from Jens Axboe:
 "This is the block-irq topic branch for 4.9-rc. It's mostly from
  Christoph, and it allows drivers to specify their own mappings, and
  more importantly, to share the blk-mq mappings with the IRQ affinity
  mappings. It's a good step towards making this work better out of the
  box"

* 'for-4.9/block-irq' of git://git.kernel.dk/linux-block:
  blk_mq: linux/blk-mq.h does not include all the headers it depends on
  blk-mq: kill unused blk_mq_create_mq_map()
  blk-mq: get rid of the cpumask in struct blk_mq_tags
  nvme: remove the post_scan callout
  nvme: switch to use pci_alloc_irq_vectors
  blk-mq: provide a default queue mapping for PCI device
  blk-mq: allow the driver to pass in a queue mapping
  blk-mq: remove ->map_queue
  blk-mq: only allocate a single mq_map per tag_set
  blk-mq: don't redistribute hardware queues on a CPU hotplug event
parents 48915c2c 8ec2ef2b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -125,4 +125,9 @@ config BLOCK_COMPAT
	depends on BLOCK && COMPAT
	default y

config BLK_MQ_PCI
	bool
	depends on BLOCK && PCI
	default y

source block/Kconfig.iosched
+1 −1
Original line number Diff line number Diff line
@@ -22,4 +22,4 @@ obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
obj-$(CONFIG_BLOCK_COMPAT)	+= compat_ioctl.o
obj-$(CONFIG_BLK_CMDLINE_PARSER)	+= cmdline-parser.o
obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o
obj-$(CONFIG_BLK_MQ_PCI)	+= blk-mq-pci.o
+3 −3
Original line number Diff line number Diff line
@@ -232,7 +232,7 @@ static void flush_end_io(struct request *flush_rq, int error)

		/* release the tag's ownership to the req cloned from */
		spin_lock_irqsave(&fq->mq_flush_lock, flags);
		hctx = q->mq_ops->map_queue(q, flush_rq->mq_ctx->cpu);
		hctx = blk_mq_map_queue(q, flush_rq->mq_ctx->cpu);
		blk_mq_tag_set_rq(hctx, flush_rq->tag, fq->orig_rq);
		flush_rq->tag = -1;
	}
@@ -325,7 +325,7 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq)
		flush_rq->tag = first_rq->tag;
		fq->orig_rq = first_rq;

		hctx = q->mq_ops->map_queue(q, first_rq->mq_ctx->cpu);
		hctx = blk_mq_map_queue(q, first_rq->mq_ctx->cpu);
		blk_mq_tag_set_rq(hctx, first_rq->tag, flush_rq);
	}

@@ -358,7 +358,7 @@ static void mq_flush_data_end_io(struct request *rq, int error)
	unsigned long flags;
	struct blk_flush_queue *fq = blk_get_flush_queue(q, ctx);

	hctx = q->mq_ops->map_queue(q, ctx->cpu);
	hctx = blk_mq_map_queue(q, ctx->cpu);

	/*
	 * After populating an empty queue, kick it to avoid stall.  Read
+5 −20
Original line number Diff line number Diff line
@@ -31,14 +31,16 @@ static int get_first_sibling(unsigned int cpu)
	return cpu;
}

int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues,
			    const struct cpumask *online_mask)
int blk_mq_map_queues(struct blk_mq_tag_set *set)
{
	unsigned int *map = set->mq_map;
	unsigned int nr_queues = set->nr_hw_queues;
	const struct cpumask *online_mask = cpu_online_mask;
	unsigned int i, nr_cpus, nr_uniq_cpus, queue, first_sibling;
	cpumask_var_t cpus;

	if (!alloc_cpumask_var(&cpus, GFP_ATOMIC))
		return 1;
		return -ENOMEM;

	cpumask_clear(cpus);
	nr_cpus = nr_uniq_cpus = 0;
@@ -86,23 +88,6 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues,
	return 0;
}

unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set)
{
	unsigned int *map;

	/* If cpus are offline, map them to first hctx */
	map = kzalloc_node(sizeof(*map) * nr_cpu_ids, GFP_KERNEL,
				set->numa_node);
	if (!map)
		return NULL;

	if (!blk_mq_update_queue_map(map, set->nr_hw_queues, cpu_online_mask))
		return map;

	kfree(map);
	return NULL;
}

/*
 * We have no quick way of doing reverse lookups. This is only used at
 * queue init time, so runtime isn't important.

block/blk-mq-pci.c

0 → 100644
+47 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2016 Christoph Hellwig.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 */
#include <linux/kobject.h>
#include <linux/blkdev.h>
#include <linux/blk-mq.h>
#include <linux/blk-mq-pci.h>
#include <linux/pci.h>
#include <linux/module.h>

/**
 * blk_mq_pci_map_queues - provide a default queue mapping for PCI device
 * @set:	tagset to provide the mapping for
 * @pdev:	PCI device associated with @set.
 *
 * This function assumes the PCI device @pdev has at least as many available
 * interrupt vetors as @set has queues.  It will then queuery the vector
 * corresponding to each queue for it's affinity mask and built queue mapping
 * that maps a queue to the CPUs that have irq affinity for the corresponding
 * vector.
 */
int blk_mq_pci_map_queues(struct blk_mq_tag_set *set, struct pci_dev *pdev)
{
	const struct cpumask *mask;
	unsigned int queue, cpu;

	for (queue = 0; queue < set->nr_hw_queues; queue++) {
		mask = pci_irq_get_affinity(pdev, queue);
		if (!mask)
			return -EINVAL;

		for_each_cpu(cpu, mask)
			set->mq_map[cpu] = queue;
	}

	return 0;
}
EXPORT_SYMBOL_GPL(blk_mq_pci_map_queues);
Loading