aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-07-04 04:39:24 -0400
committerThomas Gleixner <tglx@linutronix.de>2016-07-04 06:25:13 -0400
commit06ee6d571f0e350253a8fc3492316b2be007fae2 (patch)
treebcabd269ee107044375a331d82334b95c28f915f
parent9c2555835bb3d34dfac52a0be943dcc4bedd650f (diff)
genirq: Add affinity hint to irq allocation
Add an extra argument to the irq(domain) allocation functions, so we can hand down affinity hints to the allocator. Thats necessary to implement proper support for multiqueue devices. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Christoph Hellwig <hch@lst.de> Cc: linux-block@vger.kernel.org Cc: linux-pci@vger.kernel.org Cc: linux-nvme@lists.infradead.org Cc: axboe@fb.com Cc: agordeev@redhat.com Link: http://lkml.kernel.org/r/1467621574-8277-4-git-send-email-hch@lst.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/sparc/kernel/irq_64.c2
-rw-r--r--arch/x86/kernel/apic/io_apic.c5
-rw-r--r--include/linux/irq.h4
-rw-r--r--include/linux/irqdomain.h9
-rw-r--r--kernel/irq/ipi.c2
-rw-r--r--kernel/irq/irqdesc.c12
-rw-r--r--kernel/irq/irqdomain.c22
-rw-r--r--kernel/irq/manage.c7
-rw-r--r--kernel/irq/msi.c3
9 files changed, 41 insertions, 25 deletions
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index e22416ce56ea..34a7930b76ef 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -242,7 +242,7 @@ unsigned int irq_alloc(unsigned int dev_handle, unsigned int dev_ino)
242{ 242{
243 int irq; 243 int irq;
244 244
245 irq = __irq_alloc_descs(-1, 1, 1, numa_node_id(), NULL); 245 irq = __irq_alloc_descs(-1, 1, 1, numa_node_id(), NULL, NULL);
246 if (irq <= 0) 246 if (irq <= 0)
247 goto out; 247 goto out;
248 248
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 446702ed99dc..7c4f90dd4c2a 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -981,7 +981,7 @@ static int alloc_irq_from_domain(struct irq_domain *domain, int ioapic, u32 gsi,
981 981
982 return __irq_domain_alloc_irqs(domain, irq, 1, 982 return __irq_domain_alloc_irqs(domain, irq, 1,
983 ioapic_alloc_attr_node(info), 983 ioapic_alloc_attr_node(info),
984 info, legacy); 984 info, legacy, NULL);
985} 985}
986 986
987/* 987/*
@@ -1014,7 +1014,8 @@ static int alloc_isa_irq_from_domain(struct irq_domain *domain,
1014 info->ioapic_pin)) 1014 info->ioapic_pin))
1015 return -ENOMEM; 1015 return -ENOMEM;
1016 } else { 1016 } else {
1017 irq = __irq_domain_alloc_irqs(domain, irq, 1, node, info, true); 1017 irq = __irq_domain_alloc_irqs(domain, irq, 1, node, info, true,
1018 NULL);
1018 if (irq >= 0) { 1019 if (irq >= 0) {
1019 irq_data = irq_domain_get_irq_data(domain, irq); 1020 irq_data = irq_domain_get_irq_data(domain, irq);
1020 data = irq_data->chip_data; 1021 data = irq_data->chip_data;
diff --git a/include/linux/irq.h b/include/linux/irq.h
index f6074813688d..39ce46ac5c18 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -708,11 +708,11 @@ static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
708unsigned int arch_dynirq_lower_bound(unsigned int from); 708unsigned int arch_dynirq_lower_bound(unsigned int from);
709 709
710int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, 710int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
711 struct module *owner); 711 struct module *owner, const struct cpumask *affinity);
712 712
713/* use macros to avoid needing export.h for THIS_MODULE */ 713/* use macros to avoid needing export.h for THIS_MODULE */
714#define irq_alloc_descs(irq, from, cnt, node) \ 714#define irq_alloc_descs(irq, from, cnt, node) \
715 __irq_alloc_descs(irq, from, cnt, node, THIS_MODULE) 715 __irq_alloc_descs(irq, from, cnt, node, THIS_MODULE, NULL)
716 716
717#define irq_alloc_desc(node) \ 717#define irq_alloc_desc(node) \
718 irq_alloc_descs(-1, 0, 1, node) 718 irq_alloc_descs(-1, 0, 1, node)
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index f1f36e04d885..1aee0fbe900e 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -39,6 +39,7 @@ struct irq_domain;
39struct of_device_id; 39struct of_device_id;
40struct irq_chip; 40struct irq_chip;
41struct irq_data; 41struct irq_data;
42struct cpumask;
42 43
43/* Number of irqs reserved for a legacy isa controller */ 44/* Number of irqs reserved for a legacy isa controller */
44#define NUM_ISA_INTERRUPTS 16 45#define NUM_ISA_INTERRUPTS 16
@@ -217,7 +218,8 @@ extern struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec,
217 enum irq_domain_bus_token bus_token); 218 enum irq_domain_bus_token bus_token);
218extern void irq_set_default_host(struct irq_domain *host); 219extern void irq_set_default_host(struct irq_domain *host);
219extern int irq_domain_alloc_descs(int virq, unsigned int nr_irqs, 220extern int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
220 irq_hw_number_t hwirq, int node); 221 irq_hw_number_t hwirq, int node,
222 const struct cpumask *affinity);
221 223
222static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node) 224static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
223{ 225{
@@ -389,7 +391,7 @@ static inline struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *par
389 391
390extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, 392extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
391 unsigned int nr_irqs, int node, void *arg, 393 unsigned int nr_irqs, int node, void *arg,
392 bool realloc); 394 bool realloc, const struct cpumask *affinity);
393extern void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs); 395extern void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs);
394extern void irq_domain_activate_irq(struct irq_data *irq_data); 396extern void irq_domain_activate_irq(struct irq_data *irq_data);
395extern void irq_domain_deactivate_irq(struct irq_data *irq_data); 397extern void irq_domain_deactivate_irq(struct irq_data *irq_data);
@@ -397,7 +399,8 @@ extern void irq_domain_deactivate_irq(struct irq_data *irq_data);
397static inline int irq_domain_alloc_irqs(struct irq_domain *domain, 399static inline int irq_domain_alloc_irqs(struct irq_domain *domain,
398 unsigned int nr_irqs, int node, void *arg) 400 unsigned int nr_irqs, int node, void *arg)
399{ 401{
400 return __irq_domain_alloc_irqs(domain, -1, nr_irqs, node, arg, false); 402 return __irq_domain_alloc_irqs(domain, -1, nr_irqs, node, arg, false,
403 NULL);
401} 404}
402 405
403extern int irq_domain_alloc_irqs_recursive(struct irq_domain *domain, 406extern int irq_domain_alloc_irqs_recursive(struct irq_domain *domain,
diff --git a/kernel/irq/ipi.c b/kernel/irq/ipi.c
index 89b49f6773f0..4fd23510d5f2 100644
--- a/kernel/irq/ipi.c
+++ b/kernel/irq/ipi.c
@@ -76,7 +76,7 @@ int irq_reserve_ipi(struct irq_domain *domain,
76 } 76 }
77 } 77 }
78 78
79 virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE); 79 virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE, NULL);
80 if (virq <= 0) { 80 if (virq <= 0) {
81 pr_warn("Can't reserve IPI, failed to alloc descs\n"); 81 pr_warn("Can't reserve IPI, failed to alloc descs\n");
82 return -ENOMEM; 82 return -ENOMEM;
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 8731e1c5d1e7..b8df4fcdbb5f 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -223,7 +223,7 @@ static void free_desc(unsigned int irq)
223} 223}
224 224
225static int alloc_descs(unsigned int start, unsigned int cnt, int node, 225static int alloc_descs(unsigned int start, unsigned int cnt, int node,
226 struct module *owner) 226 const struct cpumask *affinity, struct module *owner)
227{ 227{
228 struct irq_desc *desc; 228 struct irq_desc *desc;
229 int i; 229 int i;
@@ -333,6 +333,7 @@ static void free_desc(unsigned int irq)
333} 333}
334 334
335static inline int alloc_descs(unsigned int start, unsigned int cnt, int node, 335static inline int alloc_descs(unsigned int start, unsigned int cnt, int node,
336 const struct cpumask *affinity,
336 struct module *owner) 337 struct module *owner)
337{ 338{
338 u32 i; 339 u32 i;
@@ -453,12 +454,15 @@ EXPORT_SYMBOL_GPL(irq_free_descs);
453 * @cnt: Number of consecutive irqs to allocate. 454 * @cnt: Number of consecutive irqs to allocate.
454 * @node: Preferred node on which the irq descriptor should be allocated 455 * @node: Preferred node on which the irq descriptor should be allocated
455 * @owner: Owning module (can be NULL) 456 * @owner: Owning module (can be NULL)
457 * @affinity: Optional pointer to an affinity mask which hints where the
458 * irq descriptors should be allocated and which default
459 * affinities to use
456 * 460 *
457 * Returns the first irq number or error code 461 * Returns the first irq number or error code
458 */ 462 */
459int __ref 463int __ref
460__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, 464__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
461 struct module *owner) 465 struct module *owner, const struct cpumask *affinity)
462{ 466{
463 int start, ret; 467 int start, ret;
464 468
@@ -494,7 +498,7 @@ __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
494 498
495 bitmap_set(allocated_irqs, start, cnt); 499 bitmap_set(allocated_irqs, start, cnt);
496 mutex_unlock(&sparse_irq_lock); 500 mutex_unlock(&sparse_irq_lock);
497 return alloc_descs(start, cnt, node, owner); 501 return alloc_descs(start, cnt, node, affinity, owner);
498 502
499err: 503err:
500 mutex_unlock(&sparse_irq_lock); 504 mutex_unlock(&sparse_irq_lock);
@@ -512,7 +516,7 @@ EXPORT_SYMBOL_GPL(__irq_alloc_descs);
512 */ 516 */
513unsigned int irq_alloc_hwirqs(int cnt, int node) 517unsigned int irq_alloc_hwirqs(int cnt, int node)
514{ 518{
515 int i, irq = __irq_alloc_descs(-1, 0, cnt, node, NULL); 519 int i, irq = __irq_alloc_descs(-1, 0, cnt, node, NULL, NULL);
516 520
517 if (irq < 0) 521 if (irq < 0)
518 return 0; 522 return 0;
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 8798b6c9e945..79459b732dc9 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -481,7 +481,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
481 } 481 }
482 482
483 /* Allocate a virtual interrupt number */ 483 /* Allocate a virtual interrupt number */
484 virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node)); 484 virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), NULL);
485 if (virq <= 0) { 485 if (virq <= 0) {
486 pr_debug("-> virq allocation failed\n"); 486 pr_debug("-> virq allocation failed\n");
487 return 0; 487 return 0;
@@ -835,19 +835,23 @@ const struct irq_domain_ops irq_domain_simple_ops = {
835EXPORT_SYMBOL_GPL(irq_domain_simple_ops); 835EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
836 836
837int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq, 837int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq,
838 int node) 838 int node, const struct cpumask *affinity)
839{ 839{
840 unsigned int hint; 840 unsigned int hint;
841 841
842 if (virq >= 0) { 842 if (virq >= 0) {
843 virq = irq_alloc_descs(virq, virq, cnt, node); 843 virq = __irq_alloc_descs(virq, virq, cnt, node, THIS_MODULE,
844 affinity);
844 } else { 845 } else {
845 hint = hwirq % nr_irqs; 846 hint = hwirq % nr_irqs;
846 if (hint == 0) 847 if (hint == 0)
847 hint++; 848 hint++;
848 virq = irq_alloc_descs_from(hint, cnt, node); 849 virq = __irq_alloc_descs(-1, hint, cnt, node, THIS_MODULE,
849 if (virq <= 0 && hint > 1) 850 affinity);
850 virq = irq_alloc_descs_from(1, cnt, node); 851 if (virq <= 0 && hint > 1) {
852 virq = __irq_alloc_descs(-1, 1, cnt, node, THIS_MODULE,
853 affinity);
854 }
851 } 855 }
852 856
853 return virq; 857 return virq;
@@ -1160,6 +1164,7 @@ int irq_domain_alloc_irqs_recursive(struct irq_domain *domain,
1160 * @node: NUMA node id for memory allocation 1164 * @node: NUMA node id for memory allocation
1161 * @arg: domain specific argument 1165 * @arg: domain specific argument
1162 * @realloc: IRQ descriptors have already been allocated if true 1166 * @realloc: IRQ descriptors have already been allocated if true
1167 * @affinity: Optional irq affinity mask for multiqueue devices
1163 * 1168 *
1164 * Allocate IRQ numbers and initialized all data structures to support 1169 * Allocate IRQ numbers and initialized all data structures to support
1165 * hierarchy IRQ domains. 1170 * hierarchy IRQ domains.
@@ -1175,7 +1180,7 @@ int irq_domain_alloc_irqs_recursive(struct irq_domain *domain,
1175 */ 1180 */
1176int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, 1181int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
1177 unsigned int nr_irqs, int node, void *arg, 1182 unsigned int nr_irqs, int node, void *arg,
1178 bool realloc) 1183 bool realloc, const struct cpumask *affinity)
1179{ 1184{
1180 int i, ret, virq; 1185 int i, ret, virq;
1181 1186
@@ -1193,7 +1198,8 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
1193 if (realloc && irq_base >= 0) { 1198 if (realloc && irq_base >= 0) {
1194 virq = irq_base; 1199 virq = irq_base;
1195 } else { 1200 } else {
1196 virq = irq_domain_alloc_descs(irq_base, nr_irqs, 0, node); 1201 virq = irq_domain_alloc_descs(irq_base, nr_irqs, 0, node,
1202 affinity);
1197 if (virq < 0) { 1203 if (virq < 0) {
1198 pr_debug("cannot allocate IRQ(base %d, count %d)\n", 1204 pr_debug("cannot allocate IRQ(base %d, count %d)\n",
1199 irq_base, nr_irqs); 1205 irq_base, nr_irqs);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 30658e9827f0..ad0aac6d1248 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -353,10 +353,11 @@ static int setup_affinity(struct irq_desc *desc, struct cpumask *mask)
353 return 0; 353 return 0;
354 354
355 /* 355 /*
356 * Preserve an userspace affinity setup, but make sure that 356 * Preserve the managed affinity setting and an userspace affinity
357 * one of the targets is online. 357 * setup, but make sure that one of the targets is online.
358 */ 358 */
359 if (irqd_has_set(&desc->irq_data, IRQD_AFFINITY_SET)) { 359 if (irqd_affinity_is_managed(&desc->irq_data) ||
360 irqd_has_set(&desc->irq_data, IRQD_AFFINITY_SET)) {
360 if (cpumask_intersects(desc->irq_common_data.affinity, 361 if (cpumask_intersects(desc->irq_common_data.affinity,
361 cpu_online_mask)) 362 cpu_online_mask))
362 set = desc->irq_common_data.affinity; 363 set = desc->irq_common_data.affinity;
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index eb5bf2b50b07..58dbbacc6fbb 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -334,7 +334,8 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
334 ops->set_desc(&arg, desc); 334 ops->set_desc(&arg, desc);
335 335
336 virq = __irq_domain_alloc_irqs(domain, -1, desc->nvec_used, 336 virq = __irq_domain_alloc_irqs(domain, -1, desc->nvec_used,
337 dev_to_node(dev), &arg, false); 337 dev_to_node(dev), &arg, false,
338 NULL);
338 if (virq < 0) { 339 if (virq < 0) {
339 ret = -ENOSPC; 340 ret = -ENOSPC;
340 if (ops->handle_error) 341 if (ops->handle_error)