diff options
author | Yinghai Lu <yinghai@kernel.org> | 2009-04-27 21:02:23 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-04-28 06:21:18 -0400 |
commit | d047f53a2ecce37e3bdf79eac5a326fbaadb3628 (patch) | |
tree | 1097e49b711d07c77071c93d2c3a5f7f63d5cf05 | |
parent | 024154cfdd802654cb236a18c78b6e37351e2c49 (diff) |
x86/irq: change MSI irq_desc to be more numa aware
Try to get irq_desc on the home node in create_irq_nr().
v2: don't check if we can move it when sparse_irq is not used
v3: use move_irq_des, if that node is not what we want
[ Impact: optimization, make MSI IRQ descriptors more NUMA aware ]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
LKML-Reference: <49F6559F.7070005@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 17 | ||||
-rw-r--r-- | include/linux/irq.h | 2 |
2 files changed, 14 insertions, 5 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 82376e021b5d..9cd4806cdf5f 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -3172,14 +3172,13 @@ static int nr_irqs_gsi = NR_IRQS_LEGACY; | |||
3172 | /* | 3172 | /* |
3173 | * Dynamic irq allocate and deallocation | 3173 | * Dynamic irq allocate and deallocation |
3174 | */ | 3174 | */ |
3175 | unsigned int create_irq_nr(unsigned int irq_want) | 3175 | unsigned int create_irq_nr(unsigned int irq_want, int node) |
3176 | { | 3176 | { |
3177 | /* Allocate an unused irq */ | 3177 | /* Allocate an unused irq */ |
3178 | unsigned int irq; | 3178 | unsigned int irq; |
3179 | unsigned int new; | 3179 | unsigned int new; |
3180 | unsigned long flags; | 3180 | unsigned long flags; |
3181 | struct irq_cfg *cfg_new = NULL; | 3181 | struct irq_cfg *cfg_new = NULL; |
3182 | int node = cpu_to_node(boot_cpu_id); | ||
3183 | struct irq_desc *desc_new = NULL; | 3182 | struct irq_desc *desc_new = NULL; |
3184 | 3183 | ||
3185 | irq = 0; | 3184 | irq = 0; |
@@ -3197,6 +3196,13 @@ unsigned int create_irq_nr(unsigned int irq_want) | |||
3197 | 3196 | ||
3198 | if (cfg_new->vector != 0) | 3197 | if (cfg_new->vector != 0) |
3199 | continue; | 3198 | continue; |
3199 | |||
3200 | #ifdef CONFIG_NUMA_IRQ_DESC | ||
3201 | /* different node ?*/ | ||
3202 | if (desc_new->node != node) | ||
3203 | desc = move_irq_desc(desc, node); | ||
3204 | #endif | ||
3205 | |||
3200 | if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0) | 3206 | if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0) |
3201 | irq = new; | 3207 | irq = new; |
3202 | break; | 3208 | break; |
@@ -3214,11 +3220,12 @@ unsigned int create_irq_nr(unsigned int irq_want) | |||
3214 | 3220 | ||
3215 | int create_irq(void) | 3221 | int create_irq(void) |
3216 | { | 3222 | { |
3223 | int node = cpu_to_node(boot_cpu_id); | ||
3217 | unsigned int irq_want; | 3224 | unsigned int irq_want; |
3218 | int irq; | 3225 | int irq; |
3219 | 3226 | ||
3220 | irq_want = nr_irqs_gsi; | 3227 | irq_want = nr_irqs_gsi; |
3221 | irq = create_irq_nr(irq_want); | 3228 | irq = create_irq_nr(irq_want, node); |
3222 | 3229 | ||
3223 | if (irq == 0) | 3230 | if (irq == 0) |
3224 | irq = -1; | 3231 | irq = -1; |
@@ -3476,15 +3483,17 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
3476 | unsigned int irq_want; | 3483 | unsigned int irq_want; |
3477 | struct intel_iommu *iommu = NULL; | 3484 | struct intel_iommu *iommu = NULL; |
3478 | int index = 0; | 3485 | int index = 0; |
3486 | int node; | ||
3479 | 3487 | ||
3480 | /* x86 doesn't support multiple MSI yet */ | 3488 | /* x86 doesn't support multiple MSI yet */ |
3481 | if (type == PCI_CAP_ID_MSI && nvec > 1) | 3489 | if (type == PCI_CAP_ID_MSI && nvec > 1) |
3482 | return 1; | 3490 | return 1; |
3483 | 3491 | ||
3492 | node = dev_to_node(&dev->dev); | ||
3484 | irq_want = nr_irqs_gsi; | 3493 | irq_want = nr_irqs_gsi; |
3485 | sub_handle = 0; | 3494 | sub_handle = 0; |
3486 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 3495 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
3487 | irq = create_irq_nr(irq_want); | 3496 | irq = create_irq_nr(irq_want, node); |
3488 | if (irq == 0) | 3497 | if (irq == 0) |
3489 | return -1; | 3498 | return -1; |
3490 | irq_want = irq + 1; | 3499 | irq_want = irq + 1; |
diff --git a/include/linux/irq.h b/include/linux/irq.h index a09baf8f9d99..4b95ddb5304b 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -376,7 +376,7 @@ extern void set_irq_noprobe(unsigned int irq); | |||
376 | extern void set_irq_probe(unsigned int irq); | 376 | extern void set_irq_probe(unsigned int irq); |
377 | 377 | ||
378 | /* Handle dynamic irq creation and destruction */ | 378 | /* Handle dynamic irq creation and destruction */ |
379 | extern unsigned int create_irq_nr(unsigned int irq_want); | 379 | extern unsigned int create_irq_nr(unsigned int irq_want, int node); |
380 | extern int create_irq(void); | 380 | extern int create_irq(void); |
381 | extern void destroy_irq(unsigned int irq); | 381 | extern void destroy_irq(unsigned int irq); |
382 | 382 | ||