Skip to content

Commit

Permalink
ARC: IRQ: Do not use hwirq as virq and vice versa
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yuriy Kolerov authored and Vineet Gupta committed Nov 8, 2016
1 parent 19dbc76 commit 34e71e4
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 16 deletions.
4 changes: 2 additions & 2 deletions arch/arc/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ extern const char *arc_platform_smp_cpuinfo(void);
* API expected BY platform smp code (FROM arch smp code)
*
* 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
Expand Down
19 changes: 9 additions & 10 deletions arch/arc/kernel/mcip.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
struct irq_domain *domain = irq_desc_get_handler_data(desc);
unsigned int core_irq = irq_desc_get_irq(desc);
unsigned int idu_irq;
struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;

idu_irq = core_irq - idu_first_irq;
generic_handle_irq(irq_find_mapping(domain, idu_irq));
generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
}

static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hwirq)
Expand Down Expand Up @@ -282,7 +281,7 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
struct irq_domain *domain;
/* Read IDU BCR to confirm nr_irqs */
int nr_irqs = of_irq_count(intc);
int i, irq;
int i, virq;
struct mcip_bcr mp;

READ_BCR(ARC_REG_MCIP_BCR, mp);
Expand All @@ -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
* as first level isr
*/
irq = irq_of_parse_and_map(intc, i);
virq = irq_of_parse_and_map(intc, 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);
Expand Down
13 changes: 9 additions & 4 deletions arch/arc/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <linux/atomic.h>
#include <linux/cpumask.h>
#include <linux/reboot.h>
#include <linux/irqdomain.h>
#include <asm/processor.h>
#include <asm/setup.h>
#include <asm/mach_desc.h>
Expand Down Expand Up @@ -353,20 +354,24 @@ irqreturn_t do_IPI(int irq, void *dev_id)
*/
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);
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 */
if (!cpu) {
int rc;

rc = request_percpu_irq(irq, do_IPI, "IPI Interrupt", dev);
rc = request_percpu_irq(virq, do_IPI, "IPI Interrupt", dev);
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;
}

0 comments on commit 34e71e4

Please sign in to comment.