Commit 468a903c authored by Jason Cooper's avatar Jason Cooper

Merge branch 'irqchip/handle_domain' into irqchip/core

parents ce92bfe8 087fe000
...@@ -24,6 +24,7 @@ config ARM ...@@ -24,6 +24,7 @@ config ARM
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER select GENERIC_STRNLEN_USER
select HANDLE_DOMAIN_IRQ
select HARDIRQS_SW_RESEND select HARDIRQS_SW_RESEND
select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT) select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT)
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
......
...@@ -65,24 +65,7 @@ int arch_show_interrupts(struct seq_file *p, int prec) ...@@ -65,24 +65,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
*/ */
void handle_IRQ(unsigned int irq, struct pt_regs *regs) void handle_IRQ(unsigned int irq, struct pt_regs *regs)
{ {
struct pt_regs *old_regs = set_irq_regs(regs); __handle_domain_irq(NULL, irq, false, regs);
irq_enter();
/*
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
*/
if (unlikely(irq >= nr_irqs)) {
if (printk_ratelimit())
printk(KERN_WARNING "Bad IRQ%u\n", irq);
ack_bad_irq(irq);
} else {
generic_handle_irq(irq);
}
irq_exit();
set_irq_regs(old_regs);
} }
/* /*
......
...@@ -144,7 +144,7 @@ static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs) ...@@ -144,7 +144,7 @@ static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
if (nivector == 0xffff) if (nivector == 0xffff)
break; break;
handle_IRQ(irq_find_mapping(domain, nivector), regs); handle_domain_irq(domain, nivector, regs);
} while (1); } while (1);
} }
......
...@@ -141,8 +141,7 @@ static void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs) ...@@ -141,8 +141,7 @@ static void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
while (stat) { while (stat) {
handled = 1; handled = 1;
irqofs = fls(stat) - 1; irqofs = fls(stat) - 1;
handle_IRQ(irq_find_mapping(domain, handle_domain_irq(domain, irqofs + i * 32, regs);
irqofs + i * 32), regs);
stat &= ~(1 << irqofs); stat &= ~(1 << irqofs);
} }
} }
......
...@@ -248,8 +248,7 @@ static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs ...@@ -248,8 +248,7 @@ static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs
irqnr &= ACTIVEIRQ_MASK; irqnr &= ACTIVEIRQ_MASK;
if (irqnr) { if (irqnr) {
irqnr = irq_find_mapping(domain, irqnr); handle_domain_irq(domain, irqnr, regs);
handle_IRQ(irqnr, regs);
handled_irq = 1; handled_irq = 1;
} }
} while (irqnr); } while (irqnr);
......
...@@ -30,6 +30,7 @@ config ARM64 ...@@ -30,6 +30,7 @@ config ARM64
select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER select GENERIC_STRNLEN_USER
select GENERIC_TIME_VSYSCALL select GENERIC_TIME_VSYSCALL
select HANDLE_DOMAIN_IRQ
select HARDIRQS_SW_RESEND select HARDIRQS_SW_RESEND
select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_JUMP_LABEL
......
...@@ -47,8 +47,6 @@ static inline void ack_bad_irq(unsigned int irq) ...@@ -47,8 +47,6 @@ static inline void ack_bad_irq(unsigned int irq)
irq_err_count++; irq_err_count++;
} }
extern void handle_IRQ(unsigned int, struct pt_regs *);
/* /*
* No arch-specific IRQ flags. * No arch-specific IRQ flags.
*/ */
......
...@@ -40,33 +40,6 @@ int arch_show_interrupts(struct seq_file *p, int prec) ...@@ -40,33 +40,6 @@ int arch_show_interrupts(struct seq_file *p, int prec)
return 0; return 0;
} }
/*
* handle_IRQ handles all hardware IRQ's. Decoded IRQs should
* not come via this function. Instead, they should provide their
* own 'handler'. Used by platform code implementing C-based 1st
* level decoding.
*/
void handle_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
irq_enter();
/*
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
*/
if (unlikely(irq >= nr_irqs)) {
pr_warn_ratelimited("Bad IRQ%u\n", irq);
ack_bad_irq(irq);
} else {
generic_handle_irq(irq);
}
irq_exit();
set_irq_regs(old_regs);
}
void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
{ {
if (handle_arch_irq) if (handle_arch_irq)
......
...@@ -8,6 +8,7 @@ config OPENRISC ...@@ -8,6 +8,7 @@ config OPENRISC
select OF select OF
select OF_EARLY_FLATTREE select OF_EARLY_FLATTREE
select IRQ_DOMAIN select IRQ_DOMAIN
select HANDLE_DOMAIN_IRQ
select HAVE_MEMBLOCK select HAVE_MEMBLOCK
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#define NO_IRQ (-1) #define NO_IRQ (-1)
void handle_IRQ(unsigned int, struct pt_regs *);
extern void set_handle_irq(void (*handle_irq)(struct pt_regs *)); extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
#endif /* __ASM_OPENRISC_IRQ_H__ */ #endif /* __ASM_OPENRISC_IRQ_H__ */
...@@ -48,18 +48,6 @@ void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) ...@@ -48,18 +48,6 @@ void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
handle_arch_irq = handle_irq; handle_arch_irq = handle_irq;
} }
void handle_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
irq_enter();
generic_handle_irq(irq);
irq_exit();
set_irq_regs(old_regs);
}
void __irq_entry do_IRQ(struct pt_regs *regs) void __irq_entry do_IRQ(struct pt_regs *regs)
{ {
handle_arch_irq(regs); handle_arch_irq(regs);
......
...@@ -393,13 +393,15 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained) ...@@ -393,13 +393,15 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
if (!(msimask & BIT(msinr))) if (!(msimask & BIT(msinr)))
continue; continue;
if (is_chained) {
irq = irq_find_mapping(armada_370_xp_msi_domain, irq = irq_find_mapping(armada_370_xp_msi_domain,
msinr - 16); msinr - 16);
if (is_chained)
generic_handle_irq(irq); generic_handle_irq(irq);
else } else {
handle_IRQ(irq, regs); irq = msinr - 16;
handle_domain_irq(armada_370_xp_msi_domain,
irq, regs);
}
} }
} }
#else #else
...@@ -444,9 +446,8 @@ armada_370_xp_handle_irq(struct pt_regs *regs) ...@@ -444,9 +446,8 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
break; break;
if (irqnr > 1) { if (irqnr > 1) {
irqnr = irq_find_mapping(armada_370_xp_mpic_domain, handle_domain_irq(armada_370_xp_mpic_domain,
irqnr); irqnr, regs);
handle_IRQ(irqnr, regs);
continue; continue;
} }
......
...@@ -68,12 +68,10 @@ aic_handle(struct pt_regs *regs) ...@@ -68,12 +68,10 @@ aic_handle(struct pt_regs *regs)
irqnr = irq_reg_readl(gc->reg_base + AT91_AIC_IVR); irqnr = irq_reg_readl(gc->reg_base + AT91_AIC_IVR);
irqstat = irq_reg_readl(gc->reg_base + AT91_AIC_ISR); irqstat = irq_reg_readl(gc->reg_base + AT91_AIC_ISR);
irqnr = irq_find_mapping(aic_domain, irqnr);
if (!irqstat) if (!irqstat)
irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR); irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR);
else else
handle_IRQ(irqnr, regs); handle_domain_irq(aic_domain, irqnr, regs);
} }
static int aic_retrigger(struct irq_data *d) static int aic_retrigger(struct irq_data *d)
......
...@@ -78,12 +78,10 @@ aic5_handle(struct pt_regs *regs) ...@@ -78,12 +78,10 @@ aic5_handle(struct pt_regs *regs)
irqnr = irq_reg_readl(gc->reg_base + AT91_AIC5_IVR); irqnr = irq_reg_readl(gc->reg_base + AT91_AIC5_IVR);
irqstat = irq_reg_readl(gc->reg_base + AT91_AIC5_ISR); irqstat = irq_reg_readl(gc->reg_base + AT91_AIC5_ISR);
irqnr = irq_find_mapping(aic5_domain, irqnr);
if (!irqstat) if (!irqstat)
irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR); irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR);
else else
handle_IRQ(irqnr, regs); handle_domain_irq(aic5_domain, irqnr, regs);
} }
static void aic5_mask(struct irq_data *d) static void aic5_mask(struct irq_data *d)
......
...@@ -76,24 +76,20 @@ static struct { ...@@ -76,24 +76,20 @@ static struct {
static asmlinkage void __exception_irq_entry clps711x_irqh(struct pt_regs *regs) static asmlinkage void __exception_irq_entry clps711x_irqh(struct pt_regs *regs)
{ {
u32 irqnr, irqstat; u32 irqstat;
do { do {
irqstat = readw_relaxed(clps711x_intc->intmr[0]) & irqstat = readw_relaxed(clps711x_intc->intmr[0]) &
readw_relaxed(clps711x_intc->intsr[0]); readw_relaxed(clps711x_intc->intsr[0]);
if (irqstat) { if (irqstat)
irqnr = irq_find_mapping(clps711x_intc->domain, handle_domain_irq(clps711x_intc->domain,
fls(irqstat) - 1); fls(irqstat) - 1, regs);
handle_IRQ(irqnr, regs);
}
irqstat = readw_relaxed(clps711x_intc->intmr[1]) & irqstat = readw_relaxed(clps711x_intc->intmr[1]) &
readw_relaxed(clps711x_intc->intsr[1]); readw_relaxed(clps711x_intc->intsr[1]);
if (irqstat) { if (irqstat)
irqnr = irq_find_mapping(clps711x_intc->domain, handle_domain_irq(clps711x_intc->domain,
fls(irqstat) - 1 + 16); fls(irqstat) - 1 + 16, regs);
handle_IRQ(irqnr, regs);
}
} while (irqstat); } while (irqstat);
} }
......
...@@ -274,15 +274,14 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs ...@@ -274,15 +274,14 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
irqnr = gic_read_iar(); irqnr = gic_read_iar();
if (likely(irqnr > 15 && irqnr < 1020)) { if (likely(irqnr > 15 && irqnr < 1020)) {
u64 irq = irq_find_mapping(gic_data.domain, irqnr); int err;
if (likely(irq)) { err = handle_domain_irq(gic_data.domain, irqnr, regs);
handle_IRQ(irq, regs); if (err) {
continue;
}
WARN_ONCE(true, "Unexpected SPI received!\n"); WARN_ONCE(true, "Unexpected SPI received!\n");
gic_write_eoir(irqnr); gic_write_eoir(irqnr);
} }
continue;
}
if (irqnr < 16) { if (irqnr < 16) {
gic_write_eoir(irqnr); gic_write_eoir(irqnr);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
......
...@@ -270,8 +270,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) ...@@ -270,8 +270,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
irqnr = irqstat & GICC_IAR_INT_ID_MASK; irqnr = irqstat & GICC_IAR_INT_ID_MASK;
if (likely(irqnr > 15 && irqnr < 1021)) { if (likely(irqnr > 15 && irqnr < 1021)) {
irqnr = irq_find_mapping(gic->domain, irqnr); handle_domain_irq(gic->domain, irqnr, regs);
handle_IRQ(irqnr, regs);
continue; continue;
} }
if (irqnr < 16) { if (irqnr < 16) {
......
...@@ -196,26 +196,24 @@ static struct mmp_intc_conf mmp2_conf = { ...@@ -196,26 +196,24 @@ static struct mmp_intc_conf mmp2_conf = {
static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs) static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
{ {
int irq, hwirq; int hwirq;
hwirq = readl_relaxed(mmp_icu_base + PJ1_INT_SEL); hwirq = readl_relaxed(mmp_icu_base + PJ1_INT_SEL);
if (!(hwirq & SEL_INT_PENDING)) if (!(hwirq & SEL_INT_PENDING))
return; return;
hwirq &= SEL_INT_NUM_MASK; hwirq &= SEL_INT_NUM_MASK;
irq = irq_find_mapping(icu_data[0].domain, hwirq); handle_domain_irq(icu_data[0].domain, hwirq, regs);
handle_IRQ(irq, regs);
} }
static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs) static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs)
{ {
int irq, hwirq; int hwirq;
hwirq = readl_relaxed(mmp_icu_base + PJ4_INT_SEL); hwirq = readl_relaxed(mmp_icu_base + PJ4_INT_SEL);
if (!(hwirq & SEL_INT_PENDING)) if (!(hwirq & SEL_INT_PENDING))
return; return;
hwirq &= SEL_INT_NUM_MASK; hwirq &= SEL_INT_NUM_MASK;
irq = irq_find_mapping(icu_data[0].domain, hwirq); handle_domain_irq(icu_data[0].domain, hwirq, regs);
handle_IRQ(irq, regs);
} }
/* MMP (ARMv5) */ /* MMP (ARMv5) */
......
...@@ -78,8 +78,7 @@ asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs) ...@@ -78,8 +78,7 @@ asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET); irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET);
__raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR); __raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR);
irqnr = irq_find_mapping(icoll_domain, irqnr); handle_domain_irq(icoll_domain, irqnr, regs);
handle_IRQ(irqnr, regs);
} }
static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq, static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
......
...@@ -113,7 +113,7 @@ static inline int pic_get_irq(int first) ...@@ -113,7 +113,7 @@ static inline int pic_get_irq(int first)
else else
hwirq = hwirq + first - 1; hwirq = hwirq + first - 1;
return irq_find_mapping(root_domain, hwirq); return hwirq;
} }
static void or1k_pic_handle_irq(struct pt_regs *regs) static void or1k_pic_handle_irq(struct pt_regs *regs)
...@@ -121,7 +121,7 @@ static void or1k_pic_handle_irq(struct pt_regs *regs) ...@@ -121,7 +121,7 @@ static void or1k_pic_handle_irq(struct pt_regs *regs)
int irq = -1; int irq = -1;
while ((irq = pic_get_irq(irq + 1)) != NO_IRQ) while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
handle_IRQ(irq, regs); handle_domain_irq(root_domain, irq, regs);
} }
static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
......
...@@ -43,9 +43,8 @@ __exception_irq_entry orion_handle_irq(struct pt_regs *regs) ...@@ -43,9 +43,8 @@ __exception_irq_entry orion_handle_irq(struct pt_regs *regs)
gc->mask_cache; gc->mask_cache;
while (stat) { while (stat) {
u32 hwirq = __fls(stat); u32 hwirq = __fls(stat);
u32 irq = irq_find_mapping(orion_irq_domain, handle_domain_irq(orion_irq_domain,
gc->irq_base + hwirq); gc->irq_base + hwirq, regs);
handle_IRQ(irq, regs);
stat &= ~(1 << hwirq); stat &= ~(1 << hwirq);
} }
} }
......
...@@ -339,7 +339,6 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc, ...@@ -339,7 +339,6 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
{ {
int pnd; int pnd;
int offset; int offset;
int irq;
pnd = __raw_readl(intc->reg_intpnd); pnd = __raw_readl(intc->reg_intpnd);
if (!pnd) if (!pnd)
...@@ -365,8 +364,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc, ...@@ -365,8 +364,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
if (!(pnd & (1 << offset))) if (!(pnd & (1 << offset)))
offset = __ffs(pnd); offset = __ffs(pnd);
irq = irq_find_mapping(intc->domain, intc_offset + offset); handle_domain_irq(intc->domain, intc_offset + offset, regs);
handle_IRQ(irq, regs);
return true; return true;
} }
......
...@@ -50,12 +50,10 @@ sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) ...@@ -50,12 +50,10 @@ sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
static void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs) static void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs)
{ {
void __iomem *base = sirfsoc_irqdomain->host_data; void __iomem *base = sirfsoc_irqdomain->host_data;
u32 irqstat, irqnr; u32 irqstat;
irqstat = readl_relaxed(base + SIRFSOC_INIT_IRQ_ID); irqstat = readl_relaxed(base + SIRFSOC_INIT_IRQ_ID);
irqnr = irq_find_mapping(sirfsoc_irqdomain, irqstat & 0xff); handle_domain_irq(sirfsoc_irqdomain, irqstat & 0xff, regs);
handle_IRQ(irqnr, regs);
} }
static int __init sirfsoc_irq_init(struct device_node *np, static int __init sirfsoc_irq_init(struct device_node *np,
......
...@@ -136,7 +136,7 @@ IRQCHIP_DECLARE(allwinner_sun4i_ic, "allwinner,sun4i-a10-ic", sun4i_of_init); ...@@ -136,7 +136,7 @@ IRQCHIP_DECLARE(allwinner_sun4i_ic, "allwinner,sun4i-a10-ic", sun4i_of_init);
static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs) static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs)
{ {
u32 irq, hwirq; u32 hwirq;
/* /*
* hwirq == 0 can mean one of 3 things: * hwirq == 0 can mean one of 3 things:
...@@ -154,8 +154,7 @@ static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs) ...@@ -154,8 +154,7 @@ static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs)
return; return;
do { do {
irq = irq_find_mapping(sun4i_irq_domain, hwirq); handle_domain_irq(sun4i_irq_domain, hwirq, regs);
handle_IRQ(irq, regs);
hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
} while (hwirq != 0); } while (hwirq != 0);
} }
...@@ -96,7 +96,7 @@ static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs) ...@@ -96,7 +96,7 @@ static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs)
while ((status = readl(f->base + IRQ_STATUS))) { while ((status = readl(f->base + IRQ_STATUS))) {
irq = ffs(status) - 1; irq = ffs(status) - 1;
handle_IRQ(irq_find_mapping(f->domain, irq), regs); handle_domain_irq(f->domain, irq, regs);
handled = 1; handled = 1;
} }
......
...@@ -219,7 +219,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) ...@@ -219,7 +219,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) { while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
irq = ffs(stat) - 1; irq = ffs(stat) - 1;
handle_IRQ(irq_find_mapping(vic->domain, irq), regs); handle_domain_irq(vic->domain, irq, regs);
handled = 1; handled = 1;
} }
......
...@@ -181,7 +181,7 @@ static struct irq_domain_ops vt8500_irq_domain_ops = { ...@@ -181,7 +181,7 @@ static struct irq_domain_ops vt8500_irq_domain_ops = {
static void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) static void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
{ {
u32 stat, i; u32 stat, i;
int irqnr, virq; int irqnr;
void __iomem *base; void __iomem *base;
/* Loop through each active controller */ /* Loop through each active controller */
...@@ -198,8 +198,7 @@ static void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) ...@@ -198,8 +198,7 @@ static void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
continue; continue;
} }
virq = irq_find_mapping(intc[i].domain, irqnr); handle_domain_irq(intc[i].domain, irqnr, regs);
handle_IRQ(virq, regs);
} }
} }
......
...@@ -56,8 +56,7 @@ static void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs) ...@@ -56,8 +56,7 @@ static void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs)
while (readl(zevio_irq_io + IO_STATUS)) { while (readl(zevio_irq_io + IO_STATUS)) {
irqnr = readl(zevio_irq_io + IO_CURRENT); irqnr = readl(zevio_irq_io + IO_CURRENT);
irqnr = irq_find_mapping(zevio_irq_domain, irqnr); handle_domain_irq(zevio_irq_domain, irqnr, regs);
handle_IRQ(irqnr, regs);
}; };
} }
......
...@@ -12,6 +12,8 @@ struct irq_affinity_notify; ...@@ -12,6 +12,8 @@ struct irq_affinity_notify;
struct proc_dir_entry; struct proc_dir_entry;
struct module; struct module;
struct irq_desc; struct irq_desc;
struct irq_domain;
struct pt_regs;
/** /**
* struct irq_desc - interrupt descriptor * struct irq_desc - interrupt descriptor
...@@ -118,6 +120,23 @@ static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *de ...@@ -118,6 +120,23 @@ static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *de
int generic_handle_irq(unsigned int irq); int generic_handle_irq(unsigned int irq);
#ifdef CONFIG_HANDLE_DOMAIN_IRQ
/*
* Convert a HW interrupt number to a logical one using a IRQ domain,
* and handle the result interrupt number. Return -EINVAL if
* conversion failed. Providing a NULL domain indicates that the
* conversion has already been done.
*/
int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
bool lookup, struct pt_regs *regs);
static inline int handle_domain_irq(struct irq_domain *domain,
unsigned int hwirq, struct pt_regs *regs)
{
return __handle_domain_irq(domain, hwirq, true, regs);
}
#endif
/* Test to see if a driver has successfully requested an irq */ /* Test to see if a driver has successfully requested an irq */
static inline int irq_has_action(unsigned int irq) static inline int irq_has_action(unsigned int irq)
{ {
......
...@@ -55,6 +55,9 @@ config GENERIC_IRQ_CHIP ...@@ -55,6 +55,9 @@ config GENERIC_IRQ_CHIP
config IRQ_DOMAIN config IRQ_DOMAIN
bool bool
config HANDLE_DOMAIN_IRQ
bool
config IRQ_DOMAIN_DEBUG config IRQ_DOMAIN_DEBUG
bool "Expose hardware/virtual IRQ mapping via debugfs" bool "Expose hardware/virtual IRQ mapping via debugfs"
depends on IRQ_DOMAIN && DEBUG_FS depends on IRQ_DOMAIN && DEBUG_FS
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/radix-tree.h> #include <linux/radix-tree.h>
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <linux/irqdomain.h>
#include "internals.h" #include "internals.h"
...@@ -336,6 +337,47 @@ int generic_handle_irq(unsigned int irq) ...@@ -336,6 +337,47 @@ int generic_handle_irq(unsigned int irq)
} }
EXPORT_SYMBOL_GPL(generic_handle_irq); EXPORT_SYMBOL_GPL(generic_handle_irq);
#ifdef CONFIG_HANDLE_DOMAIN_IRQ
/**
* __handle_domain_irq - Invoke the handler for a HW irq belonging to a domain
* @domain: The domain where to perform the lookup
* @hwirq: The HW irq number to convert to a logical one
* @lookup: Whether to perform the domain lookup or not
* @regs: Register file coming from the low-level handling code
*
* Returns: 0 on success, or -EINVAL if conversion has failed
*/
int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
bool lookup, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
unsigned int irq = hwirq;
int ret = 0;
irq_enter();
#ifdef CONFIG_IRQ_DOMAIN
if (lookup)
irq = irq_find_mapping(domain, hwirq);
#endif
/*
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
*/
if (unlikely(!irq || irq >= nr_irqs)) {
ack_bad_irq(irq);
ret = -EINVAL;
} else {
generic_handle_irq(irq);
}
irq_exit();
set_irq_regs(old_regs);
return ret;
}
#endif
/* Dynamic interrupt handling */ /* Dynamic interrupt handling */
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment