ARC: IRQ: Do not use hwirq as virq and vice versa
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 Signed-off-by: Yuriy Kolerov <yuriy.kolerov@synopsys.com> [vgupta: made changelog a bit concise a bit] Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
This commit is contained in:
committed by
Vineet Gupta
parent
19dbc76228
commit
34e71e4cbb
@@ -37,9 +37,9 @@ extern const char *arc_platform_smp_cpuinfo(void);
|
|||||||
* API expected BY platform smp code (FROM arch smp code)
|
* API expected BY platform smp code (FROM arch smp code)
|
||||||
*
|
*
|
||||||
* smp_ipi_irq_setup:
|
* smp_ipi_irq_setup:
|
||||||
* Takes @cpu and @irq to which the arch-common ISR is hooked up
|
* Takes @cpu and @hwirq to which the arch-common ISR is hooked up
|
||||||
*/
|
*/
|
||||||
extern int smp_ipi_irq_setup(int cpu, int irq);
|
extern int smp_ipi_irq_setup(int cpu, irq_hw_number_t hwirq);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct plat_smp_ops - SMP callbacks provided by platform to ARC SMP
|
* struct plat_smp_ops - SMP callbacks provided by platform to ARC SMP
|
||||||
|
|||||||
+9
-10
@@ -207,16 +207,15 @@ static struct irq_chip idu_irq_chip = {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int idu_first_irq;
|
static irq_hw_number_t idu_first_hwirq;
|
||||||
|
|
||||||
static void idu_cascade_isr(struct irq_desc *desc)
|
static void idu_cascade_isr(struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
struct irq_domain *domain = irq_desc_get_handler_data(desc);
|
struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
|
||||||
unsigned int core_irq = irq_desc_get_irq(desc);
|
irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
|
||||||
unsigned int idu_irq;
|
irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
|
||||||
|
|
||||||
idu_irq = core_irq - idu_first_irq;
|
generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
|
||||||
generic_handle_irq(irq_find_mapping(domain, idu_irq));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hwirq)
|
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)
|
|||||||
struct irq_domain *domain;
|
struct irq_domain *domain;
|
||||||
/* Read IDU BCR to confirm nr_irqs */
|
/* Read IDU BCR to confirm nr_irqs */
|
||||||
int nr_irqs = of_irq_count(intc);
|
int nr_irqs = of_irq_count(intc);
|
||||||
int i, irq;
|
int i, virq;
|
||||||
struct mcip_bcr mp;
|
struct mcip_bcr mp;
|
||||||
|
|
||||||
READ_BCR(ARC_REG_MCIP_BCR, mp);
|
READ_BCR(ARC_REG_MCIP_BCR, mp);
|
||||||
@@ -303,11 +302,11 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
|
|||||||
* however we need it to get the parent virq and set IDU handler
|
* however we need it to get the parent virq and set IDU handler
|
||||||
* as first level isr
|
* as first level isr
|
||||||
*/
|
*/
|
||||||
irq = irq_of_parse_and_map(intc, i);
|
virq = irq_of_parse_and_map(intc, i);
|
||||||
if (!i)
|
if (!i)
|
||||||
idu_first_irq = irq;
|
idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq));
|
||||||
|
|
||||||
irq_set_chained_handler_and_data(irq, idu_cascade_isr, domain);
|
irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
__mcip_cmd(CMD_IDU_ENABLE, 0);
|
__mcip_cmd(CMD_IDU_ENABLE, 0);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
#include <linux/reboot.h>
|
#include <linux/reboot.h>
|
||||||
|
#include <linux/irqdomain.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/mach_desc.h>
|
#include <asm/mach_desc.h>
|
||||||
@@ -353,20 +354,24 @@ irqreturn_t do_IPI(int irq, void *dev_id)
|
|||||||
*/
|
*/
|
||||||
static DEFINE_PER_CPU(int, ipi_dev);
|
static DEFINE_PER_CPU(int, ipi_dev);
|
||||||
|
|
||||||
int smp_ipi_irq_setup(int cpu, int irq)
|
int smp_ipi_irq_setup(int cpu, irq_hw_number_t hwirq)
|
||||||
{
|
{
|
||||||
int *dev = per_cpu_ptr(&ipi_dev, cpu);
|
int *dev = per_cpu_ptr(&ipi_dev, cpu);
|
||||||
|
unsigned int virq = irq_find_mapping(NULL, hwirq);
|
||||||
|
|
||||||
|
if (!virq)
|
||||||
|
panic("Cannot find virq for root domain and hwirq=%lu", hwirq);
|
||||||
|
|
||||||
/* Boot cpu calls request, all call enable */
|
/* Boot cpu calls request, all call enable */
|
||||||
if (!cpu) {
|
if (!cpu) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = request_percpu_irq(irq, do_IPI, "IPI Interrupt", dev);
|
rc = request_percpu_irq(virq, do_IPI, "IPI Interrupt", dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
panic("Percpu IRQ request failed for %d\n", irq);
|
panic("Percpu IRQ request failed for %u\n", virq);
|
||||||
}
|
}
|
||||||
|
|
||||||
enable_percpu_irq(irq, 0);
|
enable_percpu_irq(virq, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user