This came up when reviewing code to address missing IRQ affinity setting in AXS103 platform and/or implementing hierarchical IRQ domains - smp_ipi_irq_setup() callers pass hwirq but in turn calls request_percpu_irq() which expects a linux virq. So invoke irq_find_mapping() to do the conversion (also explicitify this in code by renaming the args appropriately) - idu_of_init()/idu_cascade_isr() were similarly using linux virq where hwirq is expected, so do the conversion using irqd_to_hwirq() helper
Unified · Split
| @@ -37,9 +37,9 @@ extern const char *arc_platform_smp_cpuinfo(void); · 36 unmodified lines | ||
| 37 | 37 | * API expected BY platform smp code (FROM arch smp code) |
| 38 | 38 | * |
| 39 | 39 | * smp_ipi_irq_setup: |
| 40 | − * Takes @cpu and @irq to which the arch-common ISR is hooked up | |
| 40 | + * Takes @cpu and @hwirq to which the arch-common ISR is hooked up | |
| 41 | 41 | */ |
| 42 | −extern int smp_ipi_irq_setup(int cpu, int irq); | |
| 42 | +extern int smp_ipi_irq_setup(int cpu, irq_hw_number_t hwirq); | |
| 43 | 43 | |
| 44 | 44 | /* |
| 45 | 45 | * struct plat_smp_ops - SMP callbacks provided by platform to ARC SMP |
| @@ -207,16 +207,15 @@ static struct irq_chip idu_irq_chip = { · 206 unmodified lines | ||
| 207 | 207 | |
| 208 | 208 | }; |
| 209 | 209 | |
| 210 | −static int idu_first_irq; | |
| 210 | +static irq_hw_number_t idu_first_hwirq; | |
| 211 | 211 | |
| 212 | 212 | static void idu_cascade_isr(struct irq_desc *desc) |
| 213 | 213 | { |
| 214 | − struct irq_domain *domain = irq_desc_get_handler_data(desc); | |
| 215 | − unsigned int core_irq = irq_desc_get_irq(desc); | |
| 216 | − unsigned int idu_irq; | |
| 214 | + struct irq_domain *idu_domain = irq_desc_get_handler_data(desc); | |
| 215 | + irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc)); | |
| 216 | + irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq; | |
| 217 | 217 | |
| 218 | − idu_irq = core_irq - idu_first_irq; | |
| 219 | − generic_handle_irq(irq_find_mapping(domain, idu_irq)); | |
| 218 | + generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq)); | |
| 220 | 219 | } |
| 221 | 220 | |
| 222 | 221 | static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hwirq) |
| @@ -282,7 +281,7 @@ idu_of_init(struct device_node *intc, struct device_node *parent) · 59 unmodified lines | ||
| 282 | 281 | struct irq_domain *domain; |
| 283 | 282 | /* Read IDU BCR to confirm nr_irqs */ |
| 284 | 283 | int nr_irqs = of_irq_count(intc); |
| 285 | − int i, irq; | |
| 284 | + int i, virq; | |
| 286 | 285 | struct mcip_bcr mp; |
| 287 | 286 | |
| 288 | 287 | READ_BCR(ARC_REG_MCIP_BCR, mp); |
| @@ -303,11 +302,11 @@ idu_of_init(struct device_node *intc, struct device_node *parent) · 14 unmodified lines | ||
| 303 | 302 | * however we need it to get the parent virq and set IDU handler |
| 304 | 303 | * as first level isr |
| 305 | 304 | */ |
| 306 | − irq = irq_of_parse_and_map(intc, i); | |
| 305 | + virq = irq_of_parse_and_map(intc, i); | |
| 307 | 306 | if (!i) |
| 308 | − idu_first_irq = irq; | |
| 307 | + idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq)); | |
| 309 | 308 | |
| 310 | − irq_set_chained_handler_and_data(irq, idu_cascade_isr, domain); | |
| 309 | + irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain); | |
| 311 | 310 | } |
| 312 | 311 | |
| 313 | 312 | __mcip_cmd(CMD_IDU_ENABLE, 0); |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <linux/atomic.h> |
| 23 | 23 | #include <linux/cpumask.h> |
| 24 | 24 | #include <linux/reboot.h> |
| 25 | +#include <linux/irqdomain.h> | |
| 25 | 26 | #include <asm/processor.h> |
| 26 | 27 | #include <asm/setup.h> |
| 27 | 28 | #include <asm/mach_desc.h> |
| @@ -353,20 +354,24 @@ irqreturn_t do_IPI(int irq, void *dev_id) · 325 unmodified lines | ||
| 353 | 354 | */ |
| 354 | 355 | static DEFINE_PER_CPU(int, ipi_dev); |
| 355 | 356 | |
| 356 | −int smp_ipi_irq_setup(int cpu, int irq) | |
| 357 | +int smp_ipi_irq_setup(int cpu, irq_hw_number_t hwirq) | |
| 357 | 358 | { |
| 358 | 359 | int *dev = per_cpu_ptr(&ipi_dev, cpu); |
| 360 | + unsigned int virq = irq_find_mapping(NULL, hwirq); | |
| 361 | + | |
| 362 | + if (!virq) | |
| 363 | + panic("Cannot find virq for root domain and hwirq=%lu", hwirq); | |
| 359 | 364 | |
| 360 | 365 | /* Boot cpu calls request, all call enable */ |
| 361 | 366 | if (!cpu) { |
| 362 | 367 | int rc; |
| 363 | 368 | |
| 364 | − rc = request_percpu_irq(irq, do_IPI, "IPI Interrupt", dev); | |
| 369 | + rc = request_percpu_irq(virq, do_IPI, "IPI Interrupt", dev); | |
| 365 | 370 | if (rc) |
| 366 | − panic("Percpu IRQ request failed for %d\n", irq); | |
| 371 | + panic("Percpu IRQ request failed for %u\n", virq); | |
| 367 | 372 | } |
| 368 | 373 | |
| 369 | − enable_percpu_irq(irq, 0); | |
| 374 | + enable_percpu_irq(virq, 0); | |
| 370 | 375 | |
| 371 | 376 | return 0; |
| 372 | 377 | } |