Skip to content

Commit 06ee6d5

Browse files
committed
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 <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Thomas Gleixner <[email protected]>
1 parent 9c25558 commit 06ee6d5

File tree

9 files changed

+41
-25
lines changed

9 files changed

+41
-25
lines changed

arch/sparc/kernel/irq_64.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ unsigned int irq_alloc(unsigned int dev_handle, unsigned int dev_ino)
242242
{
243243
int irq;
244244

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);
246246
if (irq <= 0)
247247
goto out;
248248

arch/x86/kernel/apic/io_apic.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,7 @@ static int alloc_irq_from_domain(struct irq_domain *domain, int ioapic, u32 gsi,
981981

982982
return __irq_domain_alloc_irqs(domain, irq, 1,
983983
ioapic_alloc_attr_node(info),
984-
info, legacy);
984+
info, legacy, NULL);
985985
}
986986

987987
/*
@@ -1014,7 +1014,8 @@ static int alloc_isa_irq_from_domain(struct irq_domain *domain,
10141014
info->ioapic_pin))
10151015
return -ENOMEM;
10161016
} 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);
10181019
if (irq >= 0) {
10191020
irq_data = irq_domain_get_irq_data(domain, irq);
10201021
data = irq_data->chip_data;

include/linux/irq.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -708,11 +708,11 @@ static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
708708
unsigned int arch_dynirq_lower_bound(unsigned int from);
709709

710710
int __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);
712712

713713
/* use macros to avoid needing export.h for THIS_MODULE */
714714
#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)
716716

717717
#define irq_alloc_desc(node) \
718718
irq_alloc_descs(-1, 0, 1, node)

include/linux/irqdomain.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct irq_domain;
3939
struct of_device_id;
4040
struct irq_chip;
4141
struct irq_data;
42+
struct cpumask;
4243

4344
/* Number of irqs reserved for a legacy isa controller */
4445
#define NUM_ISA_INTERRUPTS 16
@@ -217,7 +218,8 @@ extern struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec,
217218
enum irq_domain_bus_token bus_token);
218219
extern void irq_set_default_host(struct irq_domain *host);
219220
extern 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);
221223

222224
static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
223225
{
@@ -389,15 +391,16 @@ static inline struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *par
389391

390392
extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
391393
unsigned int nr_irqs, int node, void *arg,
392-
bool realloc);
394+
bool realloc, const struct cpumask *affinity);
393395
extern void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs);
394396
extern void irq_domain_activate_irq(struct irq_data *irq_data);
395397
extern void irq_domain_deactivate_irq(struct irq_data *irq_data);
396398

397399
static inline int irq_domain_alloc_irqs(struct irq_domain *domain,
398400
unsigned int nr_irqs, int node, void *arg)
399401
{
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);
401404
}
402405

403406
extern int irq_domain_alloc_irqs_recursive(struct irq_domain *domain,

kernel/irq/ipi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ int irq_reserve_ipi(struct irq_domain *domain,
7676
}
7777
}
7878

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);
8080
if (virq <= 0) {
8181
pr_warn("Can't reserve IPI, failed to alloc descs\n");
8282
return -ENOMEM;

kernel/irq/irqdesc.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ static void free_desc(unsigned int irq)
223223
}
224224

225225
static int alloc_descs(unsigned int start, unsigned int cnt, int node,
226-
struct module *owner)
226+
const struct cpumask *affinity, struct module *owner)
227227
{
228228
struct irq_desc *desc;
229229
int i;
@@ -333,6 +333,7 @@ static void free_desc(unsigned int irq)
333333
}
334334

335335
static inline int alloc_descs(unsigned int start, unsigned int cnt, int node,
336+
const struct cpumask *affinity,
336337
struct module *owner)
337338
{
338339
u32 i;
@@ -453,12 +454,15 @@ EXPORT_SYMBOL_GPL(irq_free_descs);
453454
* @cnt: Number of consecutive irqs to allocate.
454455
* @node: Preferred node on which the irq descriptor should be allocated
455456
* @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
456460
*
457461
* Returns the first irq number or error code
458462
*/
459463
int __ref
460464
__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)
462466
{
463467
int start, ret;
464468

@@ -494,7 +498,7 @@ __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
494498

495499
bitmap_set(allocated_irqs, start, cnt);
496500
mutex_unlock(&sparse_irq_lock);
497-
return alloc_descs(start, cnt, node, owner);
501+
return alloc_descs(start, cnt, node, affinity, owner);
498502

499503
err:
500504
mutex_unlock(&sparse_irq_lock);
@@ -512,7 +516,7 @@ EXPORT_SYMBOL_GPL(__irq_alloc_descs);
512516
*/
513517
unsigned int irq_alloc_hwirqs(int cnt, int node)
514518
{
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);
516520

517521
if (irq < 0)
518522
return 0;

kernel/irq/irqdomain.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
481481
}
482482

483483
/* 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);
485485
if (virq <= 0) {
486486
pr_debug("-> virq allocation failed\n");
487487
return 0;
@@ -835,19 +835,23 @@ const struct irq_domain_ops irq_domain_simple_ops = {
835835
EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
836836

837837
int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq,
838-
int node)
838+
int node, const struct cpumask *affinity)
839839
{
840840
unsigned int hint;
841841

842842
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);
844845
} else {
845846
hint = hwirq % nr_irqs;
846847
if (hint == 0)
847848
hint++;
848-
virq = irq_alloc_descs_from(hint, cnt, node);
849-
if (virq <= 0 && hint > 1)
850-
virq = irq_alloc_descs_from(1, cnt, node);
849+
virq = __irq_alloc_descs(-1, hint, cnt, node, THIS_MODULE,
850+
affinity);
851+
if (virq <= 0 && hint > 1) {
852+
virq = __irq_alloc_descs(-1, 1, cnt, node, THIS_MODULE,
853+
affinity);
854+
}
851855
}
852856

853857
return virq;
@@ -1160,6 +1164,7 @@ int irq_domain_alloc_irqs_recursive(struct irq_domain *domain,
11601164
* @node: NUMA node id for memory allocation
11611165
* @arg: domain specific argument
11621166
* @realloc: IRQ descriptors have already been allocated if true
1167+
* @affinity: Optional irq affinity mask for multiqueue devices
11631168
*
11641169
* Allocate IRQ numbers and initialized all data structures to support
11651170
* hierarchy IRQ domains.
@@ -1175,7 +1180,7 @@ int irq_domain_alloc_irqs_recursive(struct irq_domain *domain,
11751180
*/
11761181
int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
11771182
unsigned int nr_irqs, int node, void *arg,
1178-
bool realloc)
1183+
bool realloc, const struct cpumask *affinity)
11791184
{
11801185
int i, ret, virq;
11811186

@@ -1193,7 +1198,8 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
11931198
if (realloc && irq_base >= 0) {
11941199
virq = irq_base;
11951200
} 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);
11971203
if (virq < 0) {
11981204
pr_debug("cannot allocate IRQ(base %d, count %d)\n",
11991205
irq_base, nr_irqs);

kernel/irq/manage.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,10 +353,11 @@ static int setup_affinity(struct irq_desc *desc, struct cpumask *mask)
353353
return 0;
354354

355355
/*
356-
* Preserve an userspace affinity setup, but make sure that
357-
* one of the targets is online.
356+
* Preserve the managed affinity setting and an userspace affinity
357+
* setup, but make sure that one of the targets is online.
358358
*/
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)) {
360361
if (cpumask_intersects(desc->irq_common_data.affinity,
361362
cpu_online_mask))
362363
set = desc->irq_common_data.affinity;

kernel/irq/msi.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,8 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
334334
ops->set_desc(&arg, desc);
335335

336336
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);
338339
if (virq < 0) {
339340
ret = -ENOSPC;
340341
if (ops->handle_error)

0 commit comments

Comments
 (0)