ARC: [arcompact] don't check for hard isr calling local_irq_enable()

Historically this was done by ARC IDE driver, which is long gone.
IRQ core is pretty robust now and already checks if IRQs are enabled
in hard ISRs. Thus no point in checking this in arch code, for every
call of irq enabled.

Further if some driver does do that - let it bring down the system so we
notice/fix this sooner than covering up for sucker

This makes local_irq_enable() - for L1 only case atleast simple enough
so we can inline it.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
This commit is contained in:
Vineet Gupta 2015-09-05 22:47:30 +05:30
parent c7119d56d2
commit 9dbd3d9bfd
2 changed files with 18 additions and 69 deletions

View File

@ -91,7 +91,19 @@ static inline void arch_local_irq_restore(unsigned long flags)
/*
* Unconditionally Enable IRQs
*/
extern void arch_local_irq_enable(void);
static inline void arch_local_irq_enable(void)
{
unsigned long temp;
__asm__ __volatile__(
" lr %0, [status32] \n"
" or %0, %0, %1 \n"
" flag %0 \n"
: "=&r"(temp)
: "n"((STATUS_E1_MASK | STATUS_E2_MASK))
: "cc", "memory");
}
/*
* Unconditionally Disable IRQs

View File

@ -148,78 +148,15 @@ IRQCHIP_DECLARE(arc_intc, "snps,arc700-intc", init_onchip_IRQ);
void arch_local_irq_enable(void)
{
unsigned long flags = arch_local_save_flags();
/* Allow both L1 and L2 at the onset */
flags |= (STATUS_E1_MASK | STATUS_E2_MASK);
/* Called from hard ISR (between irq_enter and irq_exit) */
if (in_irq()) {
/* If in L2 ISR, don't re-enable any further IRQs as this can
* cause IRQ priorities to get upside down. e.g. it could allow
* L1 be taken while in L2 hard ISR which is wrong not only in
* theory, it can also cause the dreaded L1-L2-L1 scenario
*/
if (flags & STATUS_A2_MASK)
flags &= ~(STATUS_E1_MASK | STATUS_E2_MASK);
/* Even if in L1 ISR, allowe Higher prio L2 IRQs */
else if (flags & STATUS_A1_MASK)
flags &= ~(STATUS_E1_MASK);
}
/* called from soft IRQ, ideally we want to re-enable all levels */
else if (in_softirq()) {
/* However if this is case of L1 interrupted by L2,
* re-enabling both may cause whaco L1-L2-L1 scenario
* because ARC700 allows level 1 to interrupt an active L2 ISR
* Thus we disable both
* However some code, executing in soft ISR wants some IRQs
* to be enabled so we re-enable L2 only
*
* How do we determine L1 intr by L2
* -A2 is set (means in L2 ISR)
* -E1 is set in this ISR's pt_regs->status32 which is
* saved copy of status32_l2 when l2 ISR happened
*/
struct pt_regs *pt = get_irq_regs();
if ((flags & STATUS_A2_MASK) && pt &&
(pt->status32 & STATUS_A1_MASK)) {
/*flags &= ~(STATUS_E1_MASK | STATUS_E2_MASK); */
flags &= ~(STATUS_E1_MASK);
}
}
if (flags & STATUS_A2_MASK)
flags |= STATUS_E2_MASK;
else if (flags & STATUS_A1_MASK)
flags |= STATUS_E1_MASK;
arch_local_irq_restore(flags);
}
#else /* ! CONFIG_ARC_COMPACT_IRQ_LEVELS */
/*
* Simpler version for only 1 level of interrupt
* Here we only Worry about Level 1 Bits
*/
void arch_local_irq_enable(void)
{
unsigned long flags;
/*
* ARC IDE Drivers tries to re-enable interrupts from hard-isr
* context which is simply wrong
*/
if (in_irq()) {
WARN_ONCE(1, "IRQ enabled from hard-isr");
return;
}
flags = arch_local_save_flags();
flags |= (STATUS_E1_MASK | STATUS_E2_MASK);
arch_local_irq_restore(flags);
}
#endif
EXPORT_SYMBOL(arch_local_irq_enable);
#endif