Merge branch irq/remove-handle-domain-irq-20211026 into irq/irqchip-next
* irq/remove-handle-domain-irq-20211026: : Large rework of the architecture entry code from Mark Rutland. : From the cover letter: : : <quote> : The handle_domain_{irq,nmi}() functions were oringally intended as a : convenience, but recent rework to entry code across the kernel tree has : demonstrated that they cause more pain than they're worth and prevent : architectures from being able to write robust entry code. : : This series reworks the irq code to remove them, handling the necessary : entry work consistently in entry code (be it architectural or generic). : </quote> MIPS: irq: Avoid an unused-variable error irq: remove handle_domain_{irq,nmi}() irq: remove CONFIG_HANDLE_DOMAIN_IRQ_IRQENTRY irq: riscv: perform irqentry in entry code irq: openrisc: perform irqentry in entry code irq: csky: perform irqentry in entry code irq: arm64: perform irqentry in entry code irq: arm: perform irqentry in entry code irq: add a (temporary) CONFIG_HANDLE_DOMAIN_IRQ_IRQENTRY irq: nds32: avoid CONFIG_HANDLE_DOMAIN_IRQ irq: arc: avoid CONFIG_HANDLE_DOMAIN_IRQ irq: add generic_handle_arch_irq() irq: unexport handle_irq_desc() irq: simplify handle_domain_{irq,nmi}() irq: mips: simplify do_domain_IRQ() irq: mips: stop (ab)using handle_domain_irq() irq: mips: simplify bcm6345_l1_irq_handle() irq: mips: avoid nested irq_enter() Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
Коммит
c6dca712f6
|
@ -67,9 +67,6 @@ variety of methods:
|
|||
deprecated
|
||||
- generic_handle_domain_irq() handles an interrupt described by a
|
||||
domain and a hwirq number
|
||||
- handle_domain_irq() does the same thing for root interrupt
|
||||
controllers and deals with the set_irq_reg()/irq_enter() sequences
|
||||
that most architecture requires
|
||||
|
||||
Note that irq domain lookups must happen in contexts that are
|
||||
compatible with a RCU read-side critical section.
|
||||
|
|
|
@ -40,7 +40,6 @@ config ARC
|
|||
select HAVE_KRETPROBES
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select HAVE_PERF_EVENTS
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select IRQ_DOMAIN
|
||||
select MODULES_USE_ELF_RELA
|
||||
select OF
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <asm/mach_desc.h>
|
||||
|
||||
#include <asm/irq_regs.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
/*
|
||||
|
@ -39,5 +41,11 @@ void __init init_IRQ(void)
|
|||
*/
|
||||
void arch_do_IRQ(unsigned int hwirq, struct pt_regs *regs)
|
||||
{
|
||||
handle_domain_irq(NULL, hwirq, regs);
|
||||
struct pt_regs *old_regs;
|
||||
|
||||
irq_enter();
|
||||
old_regs = set_irq_regs(regs);
|
||||
generic_handle_domain_irq(NULL, hwirq);
|
||||
set_irq_regs(old_regs);
|
||||
irq_exit();
|
||||
}
|
||||
|
|
|
@ -64,7 +64,6 @@ config ARM
|
|||
select GENERIC_PCI_IOMAP
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HARDIRQS_SW_RESEND
|
||||
select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT
|
||||
select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6
|
||||
|
|
|
@ -38,14 +38,11 @@
|
|||
*/
|
||||
.macro irq_handler
|
||||
#ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
|
||||
ldr r1, =handle_arch_irq
|
||||
mov r0, sp
|
||||
badr lr, 9997f
|
||||
ldr pc, [r1]
|
||||
bl generic_handle_arch_irq
|
||||
#else
|
||||
arch_irq_handler_default
|
||||
#endif
|
||||
9997:
|
||||
.endm
|
||||
|
||||
.macro pabt_helper
|
||||
|
|
|
@ -63,11 +63,8 @@ int arch_show_interrupts(struct seq_file *p, int prec)
|
|||
*/
|
||||
void handle_IRQ(unsigned int irq, struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
struct irq_desc *desc;
|
||||
|
||||
irq_enter();
|
||||
|
||||
/*
|
||||
* Some hardware gives randomly wrong interrupts. Rather
|
||||
* than crashing, do something sensible.
|
||||
|
@ -81,9 +78,6 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
|
|||
handle_irq_desc(desc);
|
||||
else
|
||||
ack_bad_irq(irq);
|
||||
|
||||
irq_exit();
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -92,7 +86,15 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
|
|||
asmlinkage void __exception_irq_entry
|
||||
asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs;
|
||||
|
||||
irq_enter();
|
||||
old_regs = set_irq_regs(regs);
|
||||
|
||||
handle_IRQ(irq, regs);
|
||||
|
||||
set_irq_regs(old_regs);
|
||||
irq_exit();
|
||||
}
|
||||
|
||||
void __init init_IRQ(void)
|
||||
|
|
|
@ -154,7 +154,7 @@ static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
|
|||
if (nivector == 0xffff)
|
||||
break;
|
||||
|
||||
handle_domain_irq(domain, nivector, regs);
|
||||
generic_handle_domain_irq(domain, nivector);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ static void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
|
|||
while (stat) {
|
||||
handled = 1;
|
||||
irqofs = fls(stat) - 1;
|
||||
handle_domain_irq(domain, irqofs + i * 32, regs);
|
||||
generic_handle_domain_irq(domain, irqofs + i * 32);
|
||||
stat &= ~(1 << irqofs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ asmlinkage void __exception_irq_entry omap1_handle_irq(struct pt_regs *regs)
|
|||
}
|
||||
irq:
|
||||
if (irqnr)
|
||||
handle_domain_irq(domain, irqnr, regs);
|
||||
generic_handle_domain_irq(domain, irqnr);
|
||||
else
|
||||
break;
|
||||
} while (irqnr);
|
||||
|
|
|
@ -354,7 +354,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
|
|||
if (!(pnd & (1 << offset)))
|
||||
offset = __ffs(pnd);
|
||||
|
||||
handle_domain_irq(intc->domain, intc_offset + offset, regs);
|
||||
generic_handle_domain_irq(intc->domain, intc_offset + offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,6 @@ config ARM64
|
|||
select GENERIC_TIME_VSYSCALL
|
||||
select GENERIC_GETTIMEOFDAY
|
||||
select GENERIC_VDSO_TIME_NS
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HARDIRQS_SW_RESEND
|
||||
select HAVE_MOVE_PMD
|
||||
select HAVE_MOVE_PUD
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <asm/daifflags.h>
|
||||
#include <asm/esr.h>
|
||||
#include <asm/exception.h>
|
||||
#include <asm/irq_regs.h>
|
||||
#include <asm/kprobes.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/processor.h>
|
||||
|
@ -219,22 +220,6 @@ static void noinstr arm64_exit_el1_dbg(struct pt_regs *regs)
|
|||
lockdep_hardirqs_on(CALLER_ADDR0);
|
||||
}
|
||||
|
||||
static void noinstr enter_el1_irq_or_nmi(struct pt_regs *regs)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && !interrupts_enabled(regs))
|
||||
arm64_enter_nmi(regs);
|
||||
else
|
||||
enter_from_kernel_mode(regs);
|
||||
}
|
||||
|
||||
static void noinstr exit_el1_irq_or_nmi(struct pt_regs *regs)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && !interrupts_enabled(regs))
|
||||
arm64_exit_nmi(regs);
|
||||
else
|
||||
exit_to_kernel_mode(regs);
|
||||
}
|
||||
|
||||
static void __sched arm64_preempt_schedule_irq(void)
|
||||
{
|
||||
lockdep_assert_irqs_disabled();
|
||||
|
@ -263,10 +248,14 @@ static void __sched arm64_preempt_schedule_irq(void)
|
|||
static void do_interrupt_handler(struct pt_regs *regs,
|
||||
void (*handler)(struct pt_regs *))
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
|
||||
if (on_thread_stack())
|
||||
call_on_irq_stack(regs, handler);
|
||||
else
|
||||
handler(regs);
|
||||
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
extern void (*handle_arch_irq)(struct pt_regs *);
|
||||
|
@ -432,13 +421,22 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
|
|||
}
|
||||
}
|
||||
|
||||
static void noinstr el1_interrupt(struct pt_regs *regs,
|
||||
void (*handler)(struct pt_regs *))
|
||||
static __always_inline void __el1_pnmi(struct pt_regs *regs,
|
||||
void (*handler)(struct pt_regs *))
|
||||
{
|
||||
write_sysreg(DAIF_PROCCTX_NOIRQ, daif);
|
||||
|
||||
enter_el1_irq_or_nmi(regs);
|
||||
arm64_enter_nmi(regs);
|
||||
do_interrupt_handler(regs, handler);
|
||||
arm64_exit_nmi(regs);
|
||||
}
|
||||
|
||||
static __always_inline void __el1_irq(struct pt_regs *regs,
|
||||
void (*handler)(struct pt_regs *))
|
||||
{
|
||||
enter_from_kernel_mode(regs);
|
||||
|
||||
irq_enter_rcu();
|
||||
do_interrupt_handler(regs, handler);
|
||||
irq_exit_rcu();
|
||||
|
||||
/*
|
||||
* Note: thread_info::preempt_count includes both thread_info::count
|
||||
|
@ -449,7 +447,17 @@ static void noinstr el1_interrupt(struct pt_regs *regs,
|
|||
READ_ONCE(current_thread_info()->preempt_count) == 0)
|
||||
arm64_preempt_schedule_irq();
|
||||
|
||||
exit_el1_irq_or_nmi(regs);
|
||||
exit_to_kernel_mode(regs);
|
||||
}
|
||||
static void noinstr el1_interrupt(struct pt_regs *regs,
|
||||
void (*handler)(struct pt_regs *))
|
||||
{
|
||||
write_sysreg(DAIF_PROCCTX_NOIRQ, daif);
|
||||
|
||||
if (IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && !interrupts_enabled(regs))
|
||||
__el1_pnmi(regs, handler);
|
||||
else
|
||||
__el1_irq(regs, handler);
|
||||
}
|
||||
|
||||
asmlinkage void noinstr el1h_64_irq_handler(struct pt_regs *regs)
|
||||
|
@ -667,7 +675,9 @@ static void noinstr el0_interrupt(struct pt_regs *regs,
|
|||
if (regs->pc & BIT(55))
|
||||
arm64_apply_bp_hardening();
|
||||
|
||||
irq_enter_rcu();
|
||||
do_interrupt_handler(regs, handler);
|
||||
irq_exit_rcu();
|
||||
|
||||
exit_to_user_mode(regs);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ config CSKY
|
|||
select CSKY_APB_INTC
|
||||
select DMA_DIRECT_REMAP
|
||||
select IRQ_DOMAIN
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select DW_APB_TIMER_OF
|
||||
select GENERIC_IOREMAP
|
||||
select GENERIC_LIB_ASHLDI3
|
||||
|
|
|
@ -249,7 +249,7 @@ ENTRY(csky_irq)
|
|||
|
||||
|
||||
mov a0, sp
|
||||
jbsr csky_do_IRQ
|
||||
jbsr generic_handle_arch_irq
|
||||
|
||||
jmpi ret_from_exception
|
||||
|
||||
|
|
|
@ -15,8 +15,3 @@ void __init init_IRQ(void)
|
|||
setup_smp_ipi();
|
||||
#endif
|
||||
}
|
||||
|
||||
asmlinkage void __irq_entry csky_do_IRQ(struct pt_regs *regs)
|
||||
{
|
||||
handle_arch_irq(regs);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ config MIPS
|
|||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select GUP_GET_PTE_LOW_HIGH if CPU_MIPS32 && PHYS_ADDR_T_64BIT
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HAVE_ARCH_COMPILER_H
|
||||
select HAVE_ARCH_JUMP_LABEL
|
||||
select HAVE_ARCH_KGDB if MIPS_FP_SUPPORT
|
||||
|
|
|
@ -2609,7 +2609,10 @@ static void octeon_irq_ciu3_ip2(void)
|
|||
else
|
||||
hw = intsn;
|
||||
|
||||
ret = handle_domain_irq(domain, hw, NULL);
|
||||
irq_enter();
|
||||
ret = generic_handle_domain_irq(domain, hw);
|
||||
irq_exit();
|
||||
|
||||
if (ret < 0) {
|
||||
union cvmx_ciu3_iscx_w1c isc_w1c;
|
||||
u64 isc_w1c_addr = ciu3_addr + CIU3_ISC_W1C(intsn);
|
||||
|
|
|
@ -111,15 +111,9 @@ void __irq_entry do_IRQ(unsigned int irq)
|
|||
#ifdef CONFIG_IRQ_DOMAIN
|
||||
void __irq_entry do_domain_IRQ(struct irq_domain *domain, unsigned int hwirq)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
|
||||
irq_enter();
|
||||
check_stack_overflow();
|
||||
|
||||
desc = irq_resolve_mapping(domain, hwirq);
|
||||
if (likely(desc))
|
||||
handle_irq_desc(desc);
|
||||
|
||||
generic_handle_domain_irq(domain, hwirq);
|
||||
irq_exit();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -27,7 +27,6 @@ config NDS32
|
|||
select GENERIC_LIB_MULDI3
|
||||
select GENERIC_LIB_UCMPDI2
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_DEBUG_KMEMLEAK
|
||||
select HAVE_EXIT_THREAD
|
||||
|
|
|
@ -13,7 +13,6 @@ config OPENRISC
|
|||
select OF
|
||||
select OF_EARLY_FLATTREE
|
||||
select IRQ_DOMAIN
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select GPIOLIB
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select SPARSE_IRQ
|
||||
|
|
|
@ -569,8 +569,8 @@ EXCEPTION_ENTRY(_external_irq_handler)
|
|||
#endif
|
||||
CLEAR_LWA_FLAG(r3)
|
||||
l.addi r3,r1,0
|
||||
l.movhi r8,hi(do_IRQ)
|
||||
l.ori r8,r8,lo(do_IRQ)
|
||||
l.movhi r8,hi(generic_handle_arch_irq)
|
||||
l.ori r8,r8,lo(generic_handle_arch_irq)
|
||||
l.jalr r8
|
||||
l.nop
|
||||
l.j _ret_from_intr
|
||||
|
|
|
@ -36,8 +36,3 @@ void __init init_IRQ(void)
|
|||
{
|
||||
irqchip_init();
|
||||
}
|
||||
|
||||
void __irq_entry do_IRQ(struct pt_regs *regs)
|
||||
{
|
||||
handle_arch_irq(regs);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,6 @@ config RISCV
|
|||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE if !XIP_KERNEL
|
||||
|
|
|
@ -130,8 +130,7 @@ skip_context_tracking:
|
|||
|
||||
/* Handle interrupts */
|
||||
move a0, sp /* pt_regs */
|
||||
la a1, handle_arch_irq
|
||||
REG_L a1, (a1)
|
||||
la a1, generic_handle_arch_irq
|
||||
jr a1
|
||||
1:
|
||||
/*
|
||||
|
|
|
@ -140,12 +140,9 @@ void arch_irq_work_raise(void)
|
|||
|
||||
void handle_IPI(struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
|
||||
unsigned long *stats = ipi_data[smp_processor_id()].stats;
|
||||
|
||||
irq_enter();
|
||||
|
||||
riscv_clear_ipi();
|
||||
|
||||
while (true) {
|
||||
|
@ -156,7 +153,7 @@ void handle_IPI(struct pt_regs *regs)
|
|||
|
||||
ops = xchg(pending_ipis, 0);
|
||||
if (ops == 0)
|
||||
goto done;
|
||||
return;
|
||||
|
||||
if (ops & (1 << IPI_RESCHEDULE)) {
|
||||
stats[IPI_RESCHEDULE]++;
|
||||
|
@ -189,10 +186,6 @@ void handle_IPI(struct pt_regs *regs)
|
|||
/* Order data access and bit testing. */
|
||||
mb();
|
||||
}
|
||||
|
||||
done:
|
||||
irq_exit();
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
static const char * const ipi_names[] = {
|
||||
|
|
|
@ -245,7 +245,7 @@ static void __exception_irq_entry aic_handle_irq(struct pt_regs *regs)
|
|||
irq = FIELD_GET(AIC_EVENT_NUM, event);
|
||||
|
||||
if (type == AIC_EVENT_TYPE_HW)
|
||||
handle_domain_irq(aic_irqc->hw_domain, irq, regs);
|
||||
generic_handle_domain_irq(aic_irqc->hw_domain, irq);
|
||||
else if (type == AIC_EVENT_TYPE_IPI && irq == 1)
|
||||
aic_handle_ipi(regs);
|
||||
else if (event != 0)
|
||||
|
@ -392,25 +392,25 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs)
|
|||
}
|
||||
|
||||
if (TIMER_FIRING(read_sysreg(cntp_ctl_el0)))
|
||||
handle_domain_irq(aic_irqc->hw_domain,
|
||||
aic_irqc->nr_hw + AIC_TMR_EL0_PHYS, regs);
|
||||
generic_handle_domain_irq(aic_irqc->hw_domain,
|
||||
aic_irqc->nr_hw + AIC_TMR_EL0_PHYS);
|
||||
|
||||
if (TIMER_FIRING(read_sysreg(cntv_ctl_el0)))
|
||||
handle_domain_irq(aic_irqc->hw_domain,
|
||||
aic_irqc->nr_hw + AIC_TMR_EL0_VIRT, regs);
|
||||
generic_handle_domain_irq(aic_irqc->hw_domain,
|
||||
aic_irqc->nr_hw + AIC_TMR_EL0_VIRT);
|
||||
|
||||
if (is_kernel_in_hyp_mode()) {
|
||||
uint64_t enabled = read_sysreg_s(SYS_IMP_APL_VM_TMR_FIQ_ENA_EL2);
|
||||
|
||||
if ((enabled & VM_TMR_FIQ_ENABLE_P) &&
|
||||
TIMER_FIRING(read_sysreg_s(SYS_CNTP_CTL_EL02)))
|
||||
handle_domain_irq(aic_irqc->hw_domain,
|
||||
aic_irqc->nr_hw + AIC_TMR_EL02_PHYS, regs);
|
||||
generic_handle_domain_irq(aic_irqc->hw_domain,
|
||||
aic_irqc->nr_hw + AIC_TMR_EL02_PHYS);
|
||||
|
||||
if ((enabled & VM_TMR_FIQ_ENABLE_V) &&
|
||||
TIMER_FIRING(read_sysreg_s(SYS_CNTV_CTL_EL02)))
|
||||
handle_domain_irq(aic_irqc->hw_domain,
|
||||
aic_irqc->nr_hw + AIC_TMR_EL02_VIRT, regs);
|
||||
generic_handle_domain_irq(aic_irqc->hw_domain,
|
||||
aic_irqc->nr_hw + AIC_TMR_EL02_VIRT);
|
||||
}
|
||||
|
||||
if ((read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & (PMCR0_IMODE | PMCR0_IACT)) ==
|
||||
|
@ -674,7 +674,7 @@ static void aic_handle_ipi(struct pt_regs *regs)
|
|||
firing = atomic_fetch_andnot(enabled, this_cpu_ptr(&aic_vipi_flag)) & enabled;
|
||||
|
||||
for_each_set_bit(i, &firing, AIC_NR_SWIPI)
|
||||
handle_domain_irq(aic_irqc->ipi_domain, i, regs);
|
||||
generic_handle_domain_irq(aic_irqc->ipi_domain, i);
|
||||
|
||||
/*
|
||||
* No ordering needed here; at worst this just changes the timing of
|
||||
|
|
|
@ -589,12 +589,7 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
|
|||
|
||||
irq = msinr - PCI_MSI_DOORBELL_START;
|
||||
|
||||
if (is_chained)
|
||||
generic_handle_domain_irq(armada_370_xp_msi_inner_domain,
|
||||
irq);
|
||||
else
|
||||
handle_domain_irq(armada_370_xp_msi_inner_domain,
|
||||
irq, regs);
|
||||
generic_handle_domain_irq(armada_370_xp_msi_inner_domain, irq);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -646,8 +641,8 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
|
|||
break;
|
||||
|
||||
if (irqnr > 1) {
|
||||
handle_domain_irq(armada_370_xp_mpic_domain,
|
||||
irqnr, regs);
|
||||
generic_handle_domain_irq(armada_370_xp_mpic_domain,
|
||||
irqnr);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -666,7 +661,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
|
|||
& IPI_DOORBELL_MASK;
|
||||
|
||||
for_each_set_bit(ipi, &ipimask, IPI_DOORBELL_END)
|
||||
handle_domain_irq(ipi_domain, ipi, regs);
|
||||
generic_handle_domain_irq(ipi_domain, ipi);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
|
|||
if (stat == 0)
|
||||
break;
|
||||
irq += ffs(stat) - 1;
|
||||
handle_domain_irq(vic->dom, irq, regs);
|
||||
generic_handle_domain_irq(vic->dom, irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <nds32_intrinsic.h>
|
||||
|
||||
#include <asm/irq_regs.h>
|
||||
|
||||
unsigned long wake_mask;
|
||||
|
||||
static void ativic32_ack_irq(struct irq_data *data)
|
||||
|
@ -103,10 +106,25 @@ static irq_hw_number_t get_intr_src(void)
|
|||
- NDS32_VECTOR_offINTERRUPT;
|
||||
}
|
||||
|
||||
asmlinkage void asm_do_IRQ(struct pt_regs *regs)
|
||||
static void ativic32_handle_irq(struct pt_regs *regs)
|
||||
{
|
||||
irq_hw_number_t hwirq = get_intr_src();
|
||||
handle_domain_irq(root_domain, hwirq, regs);
|
||||
generic_handle_domain_irq(root_domain, hwirq);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: convert nds32 to GENERIC_IRQ_MULTI_HANDLER so that this entry logic
|
||||
* can live in arch code.
|
||||
*/
|
||||
asmlinkage void asm_do_IRQ(struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs;
|
||||
|
||||
irq_enter();
|
||||
old_regs = set_irq_regs(regs);
|
||||
ativic32_handle_irq(regs);
|
||||
set_irq_regs(old_regs);
|
||||
irq_exit();
|
||||
}
|
||||
|
||||
int __init ativic32_init_irq(struct device_node *node, struct device_node *parent)
|
||||
|
|
|
@ -71,7 +71,7 @@ aic_handle(struct pt_regs *regs)
|
|||
if (!irqstat)
|
||||
irq_reg_writel(gc, 0, AT91_AIC_EOICR);
|
||||
else
|
||||
handle_domain_irq(aic_domain, irqnr, regs);
|
||||
generic_handle_domain_irq(aic_domain, irqnr);
|
||||
}
|
||||
|
||||
static int aic_retrigger(struct irq_data *d)
|
||||
|
|
|
@ -80,7 +80,7 @@ aic5_handle(struct pt_regs *regs)
|
|||
if (!irqstat)
|
||||
irq_reg_writel(bgc, 0, AT91_AIC5_EOICR);
|
||||
else
|
||||
handle_domain_irq(aic5_domain, irqnr, regs);
|
||||
generic_handle_domain_irq(aic5_domain, irqnr);
|
||||
}
|
||||
|
||||
static void aic5_mask(struct irq_data *d)
|
||||
|
|
|
@ -246,7 +246,7 @@ static void __exception_irq_entry bcm2835_handle_irq(
|
|||
u32 hwirq;
|
||||
|
||||
while ((hwirq = get_next_armctrl_hwirq()) != ~0)
|
||||
handle_domain_irq(intc.domain, hwirq, regs);
|
||||
generic_handle_domain_irq(intc.domain, hwirq);
|
||||
}
|
||||
|
||||
static void bcm2836_chained_handle_irq(struct irq_desc *desc)
|
||||
|
|
|
@ -143,7 +143,7 @@ __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
|
|||
if (stat) {
|
||||
u32 hwirq = ffs(stat) - 1;
|
||||
|
||||
handle_domain_irq(intc.domain, hwirq, regs);
|
||||
generic_handle_domain_irq(intc.domain, hwirq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -132,16 +132,12 @@ static void bcm6345_l1_irq_handle(struct irq_desc *desc)
|
|||
int base = idx * IRQS_PER_WORD;
|
||||
unsigned long pending;
|
||||
irq_hw_number_t hwirq;
|
||||
unsigned int irq;
|
||||
|
||||
pending = __raw_readl(cpu->map_base + reg_status(intc, idx));
|
||||
pending &= __raw_readl(cpu->map_base + reg_enable(intc, idx));
|
||||
|
||||
for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) {
|
||||
irq = irq_linear_revmap(intc->domain, base + hwirq);
|
||||
if (irq)
|
||||
do_IRQ(irq);
|
||||
else
|
||||
if (generic_handle_domain_irq(intc->domain, base + hwirq))
|
||||
spurious_interrupt();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,14 +77,14 @@ static asmlinkage void __exception_irq_entry clps711x_irqh(struct pt_regs *regs)
|
|||
irqstat = readw_relaxed(clps711x_intc->intmr[0]) &
|
||||
readw_relaxed(clps711x_intc->intsr[0]);
|
||||
if (irqstat)
|
||||
handle_domain_irq(clps711x_intc->domain,
|
||||
fls(irqstat) - 1, regs);
|
||||
generic_handle_domain_irq(clps711x_intc->domain,
|
||||
fls(irqstat) - 1);
|
||||
|
||||
irqstat = readw_relaxed(clps711x_intc->intmr[1]) &
|
||||
readw_relaxed(clps711x_intc->intsr[1]);
|
||||
if (irqstat)
|
||||
handle_domain_irq(clps711x_intc->domain,
|
||||
fls(irqstat) - 1 + 16, regs);
|
||||
generic_handle_domain_irq(clps711x_intc->domain,
|
||||
fls(irqstat) - 1 + 16);
|
||||
} while (irqstat);
|
||||
}
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ static inline bool handle_irq_perbit(struct pt_regs *regs, u32 hwirq,
|
|||
if (hwirq == 0)
|
||||
return 0;
|
||||
|
||||
handle_domain_irq(root_domain, irq_base + __fls(hwirq), regs);
|
||||
generic_handle_domain_irq(root_domain, irq_base + __fls(hwirq));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -74,8 +74,8 @@ static void csky_mpintc_handler(struct pt_regs *regs)
|
|||
{
|
||||
void __iomem *reg_base = this_cpu_read(intcl_reg);
|
||||
|
||||
handle_domain_irq(root_domain,
|
||||
readl_relaxed(reg_base + INTCL_RDYIR), regs);
|
||||
generic_handle_domain_irq(root_domain,
|
||||
readl_relaxed(reg_base + INTCL_RDYIR));
|
||||
}
|
||||
|
||||
static void csky_mpintc_enable(struct irq_data *d)
|
||||
|
|
|
@ -73,7 +73,7 @@ davinci_aintc_handle_irq(struct pt_regs *regs)
|
|||
irqnr >>= 2;
|
||||
irqnr -= 1;
|
||||
|
||||
handle_domain_irq(davinci_aintc_irq_domain, irqnr, regs);
|
||||
generic_handle_domain_irq(davinci_aintc_irq_domain, irqnr);
|
||||
}
|
||||
|
||||
/* ARM Interrupt Controller Initialization */
|
||||
|
|
|
@ -135,7 +135,7 @@ davinci_cp_intc_handle_irq(struct pt_regs *regs)
|
|||
return;
|
||||
}
|
||||
|
||||
handle_domain_irq(davinci_cp_intc_irq_domain, irqnr, regs);
|
||||
generic_handle_domain_irq(davinci_cp_intc_irq_domain, irqnr);
|
||||
}
|
||||
|
||||
static int davinci_cp_intc_host_map(struct irq_domain *h, unsigned int virq,
|
||||
|
|
|
@ -50,7 +50,7 @@ static void __exception_irq_entry digicolor_handle_irq(struct pt_regs *regs)
|
|||
return;
|
||||
}
|
||||
|
||||
handle_domain_irq(digicolor_irq_domain, hwirq, regs);
|
||||
generic_handle_domain_irq(digicolor_irq_domain, hwirq);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ static void __irq_entry dw_apb_ictl_handle_irq(struct pt_regs *regs)
|
|||
while (stat) {
|
||||
u32 hwirq = ffs(stat) - 1;
|
||||
|
||||
handle_domain_irq(d, hwirq, regs);
|
||||
generic_handle_domain_irq(d, hwirq);
|
||||
stat &= ~BIT(hwirq);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ asmlinkage void __exception_irq_entry ft010_irqchip_handle_irq(struct pt_regs *r
|
|||
|
||||
while ((status = readl(FT010_IRQ_STATUS(f->base)))) {
|
||||
irq = ffs(status) - 1;
|
||||
handle_domain_irq(f->domain, irq, regs);
|
||||
generic_handle_domain_irq(f->domain, irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -660,7 +660,7 @@ static inline void gic_handle_nmi(u32 irqnr, struct pt_regs *regs)
|
|||
* PSR.I will be restored when we ERET to the
|
||||
* interrupted context.
|
||||
*/
|
||||
err = handle_domain_nmi(gic_data.domain, irqnr, regs);
|
||||
err = generic_handle_domain_nmi(gic_data.domain, irqnr);
|
||||
if (err)
|
||||
gic_deactivate_unhandled(irqnr);
|
||||
|
||||
|
@ -728,7 +728,7 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
|
|||
else
|
||||
isb();
|
||||
|
||||
if (handle_domain_irq(gic_data.domain, irqnr, regs)) {
|
||||
if (generic_handle_domain_irq(gic_data.domain, irqnr)) {
|
||||
WARN_ONCE(true, "Unexpected interrupt received!\n");
|
||||
gic_deactivate_unhandled(irqnr);
|
||||
}
|
||||
|
|
|
@ -369,7 +369,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
|
|||
this_cpu_write(sgi_intid, irqstat);
|
||||
}
|
||||
|
||||
handle_domain_irq(gic->domain, irqnr, regs);
|
||||
generic_handle_domain_irq(gic->domain, irqnr);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ static void __exception_irq_entry hip04_handle_irq(struct pt_regs *regs)
|
|||
irqnr = irqstat & GICC_IAR_INT_ID_MASK;
|
||||
|
||||
if (irqnr <= HIP04_MAX_IRQS)
|
||||
handle_domain_irq(hip04_data.domain, irqnr, regs);
|
||||
generic_handle_domain_irq(hip04_data.domain, irqnr);
|
||||
} while (irqnr > HIP04_MAX_IRQS);
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ asmlinkage void __exception_irq_entry ixp4xx_handle_irq(struct pt_regs *regs)
|
|||
|
||||
status = __raw_readl(ixi->irqbase + IXP4XX_ICIP);
|
||||
for_each_set_bit(i, &status, 32)
|
||||
handle_domain_irq(ixi->domain, i, regs);
|
||||
generic_handle_domain_irq(ixi->domain, i);
|
||||
|
||||
/*
|
||||
* IXP465/IXP435 has an upper IRQ status register
|
||||
|
@ -122,7 +122,7 @@ asmlinkage void __exception_irq_entry ixp4xx_handle_irq(struct pt_regs *regs)
|
|||
if (ixi->is_356) {
|
||||
status = __raw_readl(ixi->irqbase + IXP4XX_ICIP2);
|
||||
for_each_set_bit(i, &status, 32)
|
||||
handle_domain_irq(ixi->domain, i + 32, regs);
|
||||
generic_handle_domain_irq(ixi->domain, i + 32);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ static void __exception_irq_entry lpc32xx_handle_irq(struct pt_regs *regs)
|
|||
while (hwirq) {
|
||||
irq = __ffs(hwirq);
|
||||
hwirq &= ~BIT(irq);
|
||||
handle_domain_irq(lpc32xx_mic_irqc->domain, irq, regs);
|
||||
generic_handle_domain_irq(lpc32xx_mic_irqc->domain, irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
|
|||
if (!(hwirq & SEL_INT_PENDING))
|
||||
return;
|
||||
hwirq &= SEL_INT_NUM_MASK;
|
||||
handle_domain_irq(icu_data[0].domain, hwirq, regs);
|
||||
generic_handle_domain_irq(icu_data[0].domain, hwirq);
|
||||
}
|
||||
|
||||
static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs)
|
||||
|
@ -241,7 +241,7 @@ static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs)
|
|||
if (!(hwirq & SEL_INT_PENDING))
|
||||
return;
|
||||
hwirq &= SEL_INT_NUM_MASK;
|
||||
handle_domain_irq(icu_data[0].domain, hwirq, regs);
|
||||
generic_handle_domain_irq(icu_data[0].domain, hwirq);
|
||||
}
|
||||
|
||||
/* MMP (ARMv5) */
|
||||
|
|
|
@ -136,7 +136,7 @@ asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
|
|||
|
||||
irqnr = __raw_readl(icoll_priv.stat);
|
||||
__raw_writel(irqnr, icoll_priv.vector);
|
||||
handle_domain_irq(icoll_domain, irqnr, regs);
|
||||
generic_handle_domain_irq(icoll_domain, irqnr);
|
||||
}
|
||||
|
||||
static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
|
||||
|
|
|
@ -37,10 +37,25 @@
|
|||
|
||||
static struct irq_domain *nvic_irq_domain;
|
||||
|
||||
static void __nvic_handle_irq(irq_hw_number_t hwirq)
|
||||
{
|
||||
generic_handle_domain_irq(nvic_irq_domain, hwirq);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: restructure the ARMv7M entry logic so that this entry logic can live
|
||||
* in arch code.
|
||||
*/
|
||||
asmlinkage void __exception_irq_entry
|
||||
nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
|
||||
{
|
||||
handle_domain_irq(nvic_irq_domain, hwirq, regs);
|
||||
struct pt_regs *old_regs;
|
||||
|
||||
irq_enter();
|
||||
old_regs = set_irq_regs(regs);
|
||||
__nvic_handle_irq(hwirq);
|
||||
set_irq_regs(old_regs);
|
||||
irq_exit();
|
||||
}
|
||||
|
||||
static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
|
|
|
@ -357,7 +357,7 @@ omap_intc_handle_irq(struct pt_regs *regs)
|
|||
}
|
||||
|
||||
irqnr &= ACTIVEIRQ_MASK;
|
||||
handle_domain_irq(domain, irqnr, regs);
|
||||
generic_handle_domain_irq(domain, irqnr);
|
||||
}
|
||||
|
||||
static int __init intc_of_init(struct device_node *node,
|
||||
|
|
|
@ -116,7 +116,7 @@ static void or1k_pic_handle_irq(struct pt_regs *regs)
|
|||
int irq = -1;
|
||||
|
||||
while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
|
||||
handle_domain_irq(root_domain, irq, regs);
|
||||
generic_handle_domain_irq(root_domain, irq);
|
||||
}
|
||||
|
||||
static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
|
||||
|
|
|
@ -42,8 +42,8 @@ __exception_irq_entry orion_handle_irq(struct pt_regs *regs)
|
|||
gc->mask_cache;
|
||||
while (stat) {
|
||||
u32 hwirq = __fls(stat);
|
||||
handle_domain_irq(orion_irq_domain,
|
||||
gc->irq_base + hwirq, regs);
|
||||
generic_handle_domain_irq(orion_irq_domain,
|
||||
gc->irq_base + hwirq);
|
||||
stat &= ~(1 << hwirq);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ static void __exception_irq_entry rda_handle_irq(struct pt_regs *regs)
|
|||
|
||||
while (stat) {
|
||||
hwirq = __fls(stat);
|
||||
handle_domain_irq(rda_irq_domain, hwirq, regs);
|
||||
generic_handle_domain_irq(rda_irq_domain, hwirq);
|
||||
stat &= ~BIT(hwirq);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
|
|||
break;
|
||||
#endif
|
||||
default:
|
||||
handle_domain_irq(intc_domain, cause, regs);
|
||||
generic_handle_domain_irq(intc_domain, cause);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,8 +140,8 @@ sa1100_handle_irq(struct pt_regs *regs)
|
|||
if (mask == 0)
|
||||
break;
|
||||
|
||||
handle_domain_irq(sa1100_normal_irqdomain,
|
||||
ffs(mask) - 1, regs);
|
||||
generic_handle_domain_irq(sa1100_normal_irqdomain,
|
||||
ffs(mask) - 1);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs)
|
|||
return;
|
||||
|
||||
do {
|
||||
handle_domain_irq(irq_ic_data->irq_domain, hwirq, regs);
|
||||
generic_handle_domain_irq(irq_ic_data->irq_domain, hwirq);
|
||||
hwirq = readl(irq_ic_data->irq_base +
|
||||
SUN4I_IRQ_VECTOR_REG) >> 2;
|
||||
} while (hwirq != 0);
|
||||
|
|
|
@ -105,7 +105,7 @@ static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs)
|
|||
|
||||
while ((status = readl(f->base + IRQ_STATUS))) {
|
||||
irq = ffs(status) - 1;
|
||||
handle_domain_irq(f->domain, irq, regs);
|
||||
generic_handle_domain_irq(f->domain, irq);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
|
|||
|
||||
while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
|
||||
irq = ffs(stat) - 1;
|
||||
handle_domain_irq(vic->domain, irq, regs);
|
||||
generic_handle_domain_irq(vic->domain, irq);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -183,7 +183,7 @@ static void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
|
|||
continue;
|
||||
}
|
||||
|
||||
handle_domain_irq(intc[i].domain, irqnr, regs);
|
||||
generic_handle_domain_irq(intc[i].domain, irqnr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ static void __exception_irq_entry wpcm450_aic_handle_irq(struct pt_regs *regs)
|
|||
/* Read IPER to signal that nIRQ can be de-asserted */
|
||||
hwirq = readl(aic->regs + AIC_IPER) / 4;
|
||||
|
||||
handle_domain_irq(aic->domain, hwirq, regs);
|
||||
generic_handle_domain_irq(aic->domain, hwirq);
|
||||
}
|
||||
|
||||
static void wpcm450_aic_eoi(struct irq_data *d)
|
||||
|
|
|
@ -50,7 +50,7 @@ static void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs)
|
|||
|
||||
while (readl(zevio_irq_io + IO_STATUS)) {
|
||||
irqnr = readl(zevio_irq_io + IO_CURRENT);
|
||||
handle_domain_irq(zevio_irq_domain, irqnr, regs);
|
||||
generic_handle_domain_irq(zevio_irq_domain, irqnr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1261,6 +1261,7 @@ int __init set_handle_irq(void (*handle_irq)(struct pt_regs *));
|
|||
* top-level IRQ handler.
|
||||
*/
|
||||
extern void (*handle_arch_irq)(struct pt_regs *) __ro_after_init;
|
||||
asmlinkage void generic_handle_arch_irq(struct pt_regs *regs);
|
||||
#else
|
||||
#ifndef set_handle_irq
|
||||
#define set_handle_irq(handle_irq) \
|
||||
|
|
|
@ -168,14 +168,7 @@ int generic_handle_irq(unsigned int irq);
|
|||
* conversion failed.
|
||||
*/
|
||||
int generic_handle_domain_irq(struct irq_domain *domain, unsigned int hwirq);
|
||||
|
||||
#ifdef CONFIG_HANDLE_DOMAIN_IRQ
|
||||
int handle_domain_irq(struct irq_domain *domain,
|
||||
unsigned int hwirq, struct pt_regs *regs);
|
||||
|
||||
int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
|
||||
struct pt_regs *regs);
|
||||
#endif
|
||||
int generic_handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq);
|
||||
#endif
|
||||
|
||||
/* Test to see if a driver has successfully requested an irq */
|
||||
|
|
|
@ -97,9 +97,6 @@ config GENERIC_MSI_IRQ_DOMAIN
|
|||
config IRQ_MSI_IOMMU
|
||||
bool
|
||||
|
||||
config HANDLE_DOMAIN_IRQ
|
||||
bool
|
||||
|
||||
config IRQ_TIMINGS
|
||||
bool
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
|
||||
#include <asm/irq_regs.h>
|
||||
|
||||
#include <trace/events/irq.h>
|
||||
|
||||
#include "internals.h"
|
||||
|
@ -226,4 +228,20 @@ int __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
|
|||
handle_arch_irq = handle_irq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* generic_handle_arch_irq - root irq handler for architectures which do no
|
||||
* entry accounting themselves
|
||||
* @regs: Register file coming from the low-level handling code
|
||||
*/
|
||||
asmlinkage void noinstr generic_handle_arch_irq(struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs;
|
||||
|
||||
irq_enter();
|
||||
old_regs = set_irq_regs(regs);
|
||||
handle_arch_irq(regs);
|
||||
set_irq_regs(old_regs);
|
||||
irq_exit();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -646,13 +646,16 @@ int handle_irq_desc(struct irq_desc *desc)
|
|||
generic_handle_irq_desc(desc);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(handle_irq_desc);
|
||||
|
||||
/**
|
||||
* generic_handle_irq - Invoke the handler for a particular irq
|
||||
* @irq: The irq number to handle
|
||||
*
|
||||
*/
|
||||
* Returns: 0 on success, or -EINVAL if conversion has failed
|
||||
*
|
||||
* This function must be called from an IRQ context with irq regs
|
||||
* initialized.
|
||||
*/
|
||||
int generic_handle_irq(unsigned int irq)
|
||||
{
|
||||
return handle_irq_desc(irq_to_desc(irq));
|
||||
|
@ -662,89 +665,39 @@ EXPORT_SYMBOL_GPL(generic_handle_irq);
|
|||
#ifdef CONFIG_IRQ_DOMAIN
|
||||
/**
|
||||
* generic_handle_domain_irq - Invoke the handler for a HW irq belonging
|
||||
* to a domain, usually for a non-root interrupt
|
||||
* controller
|
||||
* to a domain.
|
||||
* @domain: The domain where to perform the lookup
|
||||
* @hwirq: The HW irq number to convert to a logical one
|
||||
*
|
||||
* Returns: 0 on success, or -EINVAL if conversion has failed
|
||||
*
|
||||
* This function must be called from an IRQ context with irq regs
|
||||
* initialized.
|
||||
*/
|
||||
int generic_handle_domain_irq(struct irq_domain *domain, unsigned int hwirq)
|
||||
{
|
||||
WARN_ON_ONCE(!in_irq());
|
||||
return handle_irq_desc(irq_resolve_mapping(domain, hwirq));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(generic_handle_domain_irq);
|
||||
|
||||
#ifdef CONFIG_HANDLE_DOMAIN_IRQ
|
||||
/**
|
||||
* handle_domain_irq - Invoke the handler for a HW irq belonging to a domain,
|
||||
* usually for a root interrupt controller
|
||||
* generic_handle_domain_nmi - Invoke the handler for a HW nmi belonging
|
||||
* to a domain.
|
||||
* @domain: The domain where to perform the lookup
|
||||
* @hwirq: The HW irq number to convert to a logical one
|
||||
* @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, struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
struct irq_desc *desc;
|
||||
int ret = 0;
|
||||
|
||||
irq_enter();
|
||||
|
||||
/* The irqdomain code provides boundary checks */
|
||||
desc = irq_resolve_mapping(domain, hwirq);
|
||||
if (likely(desc))
|
||||
handle_irq_desc(desc);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
irq_exit();
|
||||
set_irq_regs(old_regs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle_domain_nmi - 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
|
||||
* @regs: Register file coming from the low-level handling code
|
||||
*
|
||||
* This function must be called from an NMI context.
|
||||
*
|
||||
* Returns: 0 on success, or -EINVAL if conversion has failed
|
||||
*/
|
||||
int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
|
||||
struct pt_regs *regs)
|
||||
* This function must be called from an NMI context with irq regs
|
||||
* initialized.
|
||||
**/
|
||||
int generic_handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
struct irq_desc *desc;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* NMI context needs to be setup earlier in order to deal with tracing.
|
||||
*/
|
||||
WARN_ON(!in_nmi());
|
||||
|
||||
desc = irq_resolve_mapping(domain, hwirq);
|
||||
|
||||
/*
|
||||
* ack_bad_irq is not NMI-safe, just report
|
||||
* an invalid interrupt.
|
||||
*/
|
||||
if (likely(desc))
|
||||
handle_irq_desc(desc);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
set_irq_regs(old_regs);
|
||||
return ret;
|
||||
WARN_ON_ONCE(!in_nmi());
|
||||
return handle_irq_desc(irq_resolve_mapping(domain, hwirq));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Dynamic interrupt handling */
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче