diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-24 07:01:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-24 07:01:18 -0400 |
commit | 78fea6334f725f1a55cb5761730ceab64255cf1a (patch) | |
tree | 5413075a2bc54583d18b79a698bdd7b539c00cd6 | |
parent | e0bc833d108e8caba1918218a0b2be7a71080d17 (diff) | |
parent | bed9df97b39e73a4607189f2c4b9fb89cc3f7f59 (diff) |
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fixes from Thomas Gleixner:
"A set of fixes mostly for the ARM/GIC world:
- Fix the MSI affinity handling in the ls-scfg irq chip driver so it
updates and uses the effective affinity mask correctly
- Prevent binding LPIs to offline CPUs and respect the Cavium erratum
which requires that LPIs which belong to an offline NUMA node are
not bound to a CPU on a different NUMA node.
- Free only the amount of allocated interrupts in the GIC-V2M driver
instead of trying to free log2(nrirqs).
- Prevent emitting SYNC and VSYNC targetting non existing interrupt
collections in the GIC-V3 ITS driver
- Ensure that the GIV-V3 interrupt redistributor is correctly
reprogrammed on CPU hotplug
- Remove a stale unused helper function"
* 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
irqdesc: Delete irq_desc_get_msi_desc()
irqchip/gic-v3-its: Fix reprogramming of redistributors on CPU hotplug
irqchip/gic-v3-its: Only emit VSYNC if targetting a valid collection
irqchip/gic-v3-its: Only emit SYNC if targetting a valid collection
irqchip/gic-v3-its: Don't bind LPI to unavailable NUMA node
irqchip/gic-v2m: Fix SPI release on error path
irqchip/ls-scfg-msi: Fix MSI affinity handling
genirq/debugfs: Add missing IRQCHIP_SUPPORTS_LEVEL_MSI debug
-rw-r--r-- | drivers/irqchip/irq-gic-v2m.c | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 62 | ||||
-rw-r--r-- | drivers/irqchip/irq-ls-scfg-msi.c | 10 | ||||
-rw-r--r-- | include/linux/irq.h | 1 | ||||
-rw-r--r-- | include/linux/irqdesc.h | 5 | ||||
-rw-r--r-- | kernel/irq/debugfs.c | 1 |
6 files changed, 60 insertions, 21 deletions
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index 0f52d44b3f69..f5fe0100f9ff 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c | |||
@@ -199,7 +199,7 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, | |||
199 | 199 | ||
200 | fail: | 200 | fail: |
201 | irq_domain_free_irqs_parent(domain, virq, nr_irqs); | 201 | irq_domain_free_irqs_parent(domain, virq, nr_irqs); |
202 | gicv2m_unalloc_msi(v2m, hwirq, get_count_order(nr_irqs)); | 202 | gicv2m_unalloc_msi(v2m, hwirq, nr_irqs); |
203 | return err; | 203 | return err; |
204 | } | 204 | } |
205 | 205 | ||
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 5377d7e2afba..d7842d312d3e 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c | |||
@@ -182,6 +182,22 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev, | |||
182 | return its->collections + its_dev->event_map.col_map[event]; | 182 | return its->collections + its_dev->event_map.col_map[event]; |
183 | } | 183 | } |
184 | 184 | ||
185 | static struct its_collection *valid_col(struct its_collection *col) | ||
186 | { | ||
187 | if (WARN_ON_ONCE(col->target_address & GENMASK_ULL(0, 15))) | ||
188 | return NULL; | ||
189 | |||
190 | return col; | ||
191 | } | ||
192 | |||
193 | static struct its_vpe *valid_vpe(struct its_node *its, struct its_vpe *vpe) | ||
194 | { | ||
195 | if (valid_col(its->collections + vpe->col_idx)) | ||
196 | return vpe; | ||
197 | |||
198 | return NULL; | ||
199 | } | ||
200 | |||
185 | /* | 201 | /* |
186 | * ITS command descriptors - parameters to be encoded in a command | 202 | * ITS command descriptors - parameters to be encoded in a command |
187 | * block. | 203 | * block. |
@@ -439,7 +455,7 @@ static struct its_collection *its_build_mapti_cmd(struct its_node *its, | |||
439 | 455 | ||
440 | its_fixup_cmd(cmd); | 456 | its_fixup_cmd(cmd); |
441 | 457 | ||
442 | return col; | 458 | return valid_col(col); |
443 | } | 459 | } |
444 | 460 | ||
445 | static struct its_collection *its_build_movi_cmd(struct its_node *its, | 461 | static struct its_collection *its_build_movi_cmd(struct its_node *its, |
@@ -458,7 +474,7 @@ static struct its_collection *its_build_movi_cmd(struct its_node *its, | |||
458 | 474 | ||
459 | its_fixup_cmd(cmd); | 475 | its_fixup_cmd(cmd); |
460 | 476 | ||
461 | return col; | 477 | return valid_col(col); |
462 | } | 478 | } |
463 | 479 | ||
464 | static struct its_collection *its_build_discard_cmd(struct its_node *its, | 480 | static struct its_collection *its_build_discard_cmd(struct its_node *its, |
@@ -476,7 +492,7 @@ static struct its_collection *its_build_discard_cmd(struct its_node *its, | |||
476 | 492 | ||
477 | its_fixup_cmd(cmd); | 493 | its_fixup_cmd(cmd); |
478 | 494 | ||
479 | return col; | 495 | return valid_col(col); |
480 | } | 496 | } |
481 | 497 | ||
482 | static struct its_collection *its_build_inv_cmd(struct its_node *its, | 498 | static struct its_collection *its_build_inv_cmd(struct its_node *its, |
@@ -494,7 +510,7 @@ static struct its_collection *its_build_inv_cmd(struct its_node *its, | |||
494 | 510 | ||
495 | its_fixup_cmd(cmd); | 511 | its_fixup_cmd(cmd); |
496 | 512 | ||
497 | return col; | 513 | return valid_col(col); |
498 | } | 514 | } |
499 | 515 | ||
500 | static struct its_collection *its_build_int_cmd(struct its_node *its, | 516 | static struct its_collection *its_build_int_cmd(struct its_node *its, |
@@ -512,7 +528,7 @@ static struct its_collection *its_build_int_cmd(struct its_node *its, | |||
512 | 528 | ||
513 | its_fixup_cmd(cmd); | 529 | its_fixup_cmd(cmd); |
514 | 530 | ||
515 | return col; | 531 | return valid_col(col); |
516 | } | 532 | } |
517 | 533 | ||
518 | static struct its_collection *its_build_clear_cmd(struct its_node *its, | 534 | static struct its_collection *its_build_clear_cmd(struct its_node *its, |
@@ -530,7 +546,7 @@ static struct its_collection *its_build_clear_cmd(struct its_node *its, | |||
530 | 546 | ||
531 | its_fixup_cmd(cmd); | 547 | its_fixup_cmd(cmd); |
532 | 548 | ||
533 | return col; | 549 | return valid_col(col); |
534 | } | 550 | } |
535 | 551 | ||
536 | static struct its_collection *its_build_invall_cmd(struct its_node *its, | 552 | static struct its_collection *its_build_invall_cmd(struct its_node *its, |
@@ -554,7 +570,7 @@ static struct its_vpe *its_build_vinvall_cmd(struct its_node *its, | |||
554 | 570 | ||
555 | its_fixup_cmd(cmd); | 571 | its_fixup_cmd(cmd); |
556 | 572 | ||
557 | return desc->its_vinvall_cmd.vpe; | 573 | return valid_vpe(its, desc->its_vinvall_cmd.vpe); |
558 | } | 574 | } |
559 | 575 | ||
560 | static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, | 576 | static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, |
@@ -576,7 +592,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, | |||
576 | 592 | ||
577 | its_fixup_cmd(cmd); | 593 | its_fixup_cmd(cmd); |
578 | 594 | ||
579 | return desc->its_vmapp_cmd.vpe; | 595 | return valid_vpe(its, desc->its_vmapp_cmd.vpe); |
580 | } | 596 | } |
581 | 597 | ||
582 | static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, | 598 | static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, |
@@ -599,7 +615,7 @@ static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, | |||
599 | 615 | ||
600 | its_fixup_cmd(cmd); | 616 | its_fixup_cmd(cmd); |
601 | 617 | ||
602 | return desc->its_vmapti_cmd.vpe; | 618 | return valid_vpe(its, desc->its_vmapti_cmd.vpe); |
603 | } | 619 | } |
604 | 620 | ||
605 | static struct its_vpe *its_build_vmovi_cmd(struct its_node *its, | 621 | static struct its_vpe *its_build_vmovi_cmd(struct its_node *its, |
@@ -622,7 +638,7 @@ static struct its_vpe *its_build_vmovi_cmd(struct its_node *its, | |||
622 | 638 | ||
623 | its_fixup_cmd(cmd); | 639 | its_fixup_cmd(cmd); |
624 | 640 | ||
625 | return desc->its_vmovi_cmd.vpe; | 641 | return valid_vpe(its, desc->its_vmovi_cmd.vpe); |
626 | } | 642 | } |
627 | 643 | ||
628 | static struct its_vpe *its_build_vmovp_cmd(struct its_node *its, | 644 | static struct its_vpe *its_build_vmovp_cmd(struct its_node *its, |
@@ -640,7 +656,7 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its, | |||
640 | 656 | ||
641 | its_fixup_cmd(cmd); | 657 | its_fixup_cmd(cmd); |
642 | 658 | ||
643 | return desc->its_vmovp_cmd.vpe; | 659 | return valid_vpe(its, desc->its_vmovp_cmd.vpe); |
644 | } | 660 | } |
645 | 661 | ||
646 | static u64 its_cmd_ptr_to_offset(struct its_node *its, | 662 | static u64 its_cmd_ptr_to_offset(struct its_node *its, |
@@ -1824,11 +1840,16 @@ static int its_alloc_tables(struct its_node *its) | |||
1824 | 1840 | ||
1825 | static int its_alloc_collections(struct its_node *its) | 1841 | static int its_alloc_collections(struct its_node *its) |
1826 | { | 1842 | { |
1843 | int i; | ||
1844 | |||
1827 | its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections), | 1845 | its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections), |
1828 | GFP_KERNEL); | 1846 | GFP_KERNEL); |
1829 | if (!its->collections) | 1847 | if (!its->collections) |
1830 | return -ENOMEM; | 1848 | return -ENOMEM; |
1831 | 1849 | ||
1850 | for (i = 0; i < nr_cpu_ids; i++) | ||
1851 | its->collections[i].target_address = ~0ULL; | ||
1852 | |||
1832 | return 0; | 1853 | return 0; |
1833 | } | 1854 | } |
1834 | 1855 | ||
@@ -2310,7 +2331,14 @@ static int its_irq_domain_activate(struct irq_domain *domain, | |||
2310 | cpu_mask = cpumask_of_node(its_dev->its->numa_node); | 2331 | cpu_mask = cpumask_of_node(its_dev->its->numa_node); |
2311 | 2332 | ||
2312 | /* Bind the LPI to the first possible CPU */ | 2333 | /* Bind the LPI to the first possible CPU */ |
2313 | cpu = cpumask_first(cpu_mask); | 2334 | cpu = cpumask_first_and(cpu_mask, cpu_online_mask); |
2335 | if (cpu >= nr_cpu_ids) { | ||
2336 | if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) | ||
2337 | return -EINVAL; | ||
2338 | |||
2339 | cpu = cpumask_first(cpu_online_mask); | ||
2340 | } | ||
2341 | |||
2314 | its_dev->event_map.col_map[event] = cpu; | 2342 | its_dev->event_map.col_map[event] = cpu; |
2315 | irq_data_update_effective_affinity(d, cpumask_of(cpu)); | 2343 | irq_data_update_effective_affinity(d, cpumask_of(cpu)); |
2316 | 2344 | ||
@@ -3399,6 +3427,16 @@ static int redist_disable_lpis(void) | |||
3399 | u64 timeout = USEC_PER_SEC; | 3427 | u64 timeout = USEC_PER_SEC; |
3400 | u64 val; | 3428 | u64 val; |
3401 | 3429 | ||
3430 | /* | ||
3431 | * If coming via a CPU hotplug event, we don't need to disable | ||
3432 | * LPIs before trying to re-enable them. They are already | ||
3433 | * configured and all is well in the world. Detect this case | ||
3434 | * by checking the allocation of the pending table for the | ||
3435 | * current CPU. | ||
3436 | */ | ||
3437 | if (gic_data_rdist()->pend_page) | ||
3438 | return 0; | ||
3439 | |||
3402 | if (!gic_rdists_supports_plpis()) { | 3440 | if (!gic_rdists_supports_plpis()) { |
3403 | pr_info("CPU%d: LPIs not supported\n", smp_processor_id()); | 3441 | pr_info("CPU%d: LPIs not supported\n", smp_processor_id()); |
3404 | return -ENXIO; | 3442 | return -ENXIO; |
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c index 1ec3bfe56693..c671b3212010 100644 --- a/drivers/irqchip/irq-ls-scfg-msi.c +++ b/drivers/irqchip/irq-ls-scfg-msi.c | |||
@@ -93,8 +93,12 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) | |||
93 | msg->address_lo = lower_32_bits(msi_data->msiir_addr); | 93 | msg->address_lo = lower_32_bits(msi_data->msiir_addr); |
94 | msg->data = data->hwirq; | 94 | msg->data = data->hwirq; |
95 | 95 | ||
96 | if (msi_affinity_flag) | 96 | if (msi_affinity_flag) { |
97 | msg->data |= cpumask_first(data->common->affinity); | 97 | const struct cpumask *mask; |
98 | |||
99 | mask = irq_data_get_effective_affinity_mask(data); | ||
100 | msg->data |= cpumask_first(mask); | ||
101 | } | ||
98 | 102 | ||
99 | iommu_dma_map_msi_msg(data->irq, msg); | 103 | iommu_dma_map_msi_msg(data->irq, msg); |
100 | } | 104 | } |
@@ -121,7 +125,7 @@ static int ls_scfg_msi_set_affinity(struct irq_data *irq_data, | |||
121 | return -EINVAL; | 125 | return -EINVAL; |
122 | } | 126 | } |
123 | 127 | ||
124 | cpumask_copy(irq_data->common->affinity, mask); | 128 | irq_data_update_effective_affinity(irq_data, cpumask_of(cpu)); |
125 | 129 | ||
126 | return IRQ_SET_MASK_OK; | 130 | return IRQ_SET_MASK_OK; |
127 | } | 131 | } |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 4bd2f34947f4..201de12a9957 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -503,6 +503,7 @@ struct irq_chip { | |||
503 | * IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip | 503 | * IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip |
504 | * IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask | 504 | * IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask |
505 | * IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode | 505 | * IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode |
506 | * IRQCHIP_SUPPORTS_LEVEL_MSI Chip can provide two doorbells for Level MSIs | ||
506 | */ | 507 | */ |
507 | enum { | 508 | enum { |
508 | IRQCHIP_SET_TYPE_MASKED = (1 << 0), | 509 | IRQCHIP_SET_TYPE_MASKED = (1 << 0), |
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 25b33b664537..dd1e40ddac7d 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h | |||
@@ -145,11 +145,6 @@ static inline void *irq_desc_get_handler_data(struct irq_desc *desc) | |||
145 | return desc->irq_common_data.handler_data; | 145 | return desc->irq_common_data.handler_data; |
146 | } | 146 | } |
147 | 147 | ||
148 | static inline struct msi_desc *irq_desc_get_msi_desc(struct irq_desc *desc) | ||
149 | { | ||
150 | return desc->irq_common_data.msi_desc; | ||
151 | } | ||
152 | |||
153 | /* | 148 | /* |
154 | * Architectures call this to let the generic IRQ layer | 149 | * Architectures call this to let the generic IRQ layer |
155 | * handle an interrupt. | 150 | * handle an interrupt. |
diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c index 4dadeb3d6666..6f636136cccc 100644 --- a/kernel/irq/debugfs.c +++ b/kernel/irq/debugfs.c | |||
@@ -55,6 +55,7 @@ static const struct irq_bit_descr irqchip_flags[] = { | |||
55 | BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE), | 55 | BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE), |
56 | BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE), | 56 | BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE), |
57 | BIT_MASK_DESCR(IRQCHIP_EOI_THREADED), | 57 | BIT_MASK_DESCR(IRQCHIP_EOI_THREADED), |
58 | BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI), | ||
58 | }; | 59 | }; |
59 | 60 | ||
60 | static void | 61 | static void |