diff options
Diffstat (limited to 'arch/arc/kernel')
-rw-r--r-- | arch/arc/kernel/entry-arcv2.S | 24 | ||||
-rw-r--r-- | arch/arc/kernel/entry-compact.S | 2 | ||||
-rw-r--r-- | arch/arc/kernel/intc-arcv2.c | 10 |
3 files changed, 23 insertions, 13 deletions
diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S index 7a1c124ff021..0b6388a5f0b8 100644 --- a/arch/arc/kernel/entry-arcv2.S +++ b/arch/arc/kernel/entry-arcv2.S @@ -67,12 +67,23 @@ ENTRY(handle_interrupt) INTERRUPT_PROLOGUE irq - clri ; To make status32.IE agree with CPU internal state - -#ifdef CONFIG_TRACE_IRQFLAGS - TRACE_ASM_IRQ_DISABLE -#endif - + # irq control APIs local_irq_save/restore/disable/enable fiddle with + # global interrupt enable bits in STATUS32 (.IE for 1 prio, .E[] for 2 prio) + # However a taken interrupt doesn't clear these bits. Thus irqs_disabled() + # query in hard ISR path would return false (since .IE is set) which would + # trips genirq interrupt handling asserts. + # + # So do a "soft" disable of interrutps here. + # + # Note this disable is only for consistent book-keeping as further interrupts + # will be disabled anyways even w/o this. Hardware tracks active interrupts + # seperately in AUX_IRQ_ACTIVE.active and will not take new interrupts + # unless this one returns (or higher prio becomes pending in 2-prio scheme) + + IRQ_DISABLE + + ; icause is banked: one per priority level + ; so a higher prio interrupt taken here won't clobber prev prio icause lr r0, [ICAUSE] mov blink, ret_from_exception @@ -171,6 +182,7 @@ END(EV_TLBProtV) ; All 2 entry points to here already disable interrupts .Lrestore_regs: +restore_regs: # Interrpts are actually disabled from this point on, but will get # reenabled after we return from interrupt/exception. diff --git a/arch/arc/kernel/entry-compact.S b/arch/arc/kernel/entry-compact.S index 98812c1248df..9211707634dc 100644 --- a/arch/arc/kernel/entry-compact.S +++ b/arch/arc/kernel/entry-compact.S @@ -259,7 +259,7 @@ ENTRY(EV_TLBProtV) EXCEPTION_PROLOGUE - lr r2, [ecr] + mov r2, r9 ; ECR set into r9 already lr r0, [efa] ; Faulting Data address (not part of pt_regs saved above) ; Exception auto-disables further Intr/exceptions. diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c index 62b59409a5d9..994dca7014db 100644 --- a/arch/arc/kernel/intc-arcv2.c +++ b/arch/arc/kernel/intc-arcv2.c @@ -14,8 +14,6 @@ #include <linux/irqchip.h> #include <asm/irq.h> -static int irq_prio; - /* * Early Hardware specific Interrupt setup * -Called very early (start_kernel -> setup_arch -> setup_processor) @@ -24,7 +22,7 @@ static int irq_prio; */ void arc_init_IRQ(void) { - unsigned int tmp; + unsigned int tmp, irq_prio; struct irq_build { #ifdef CONFIG_CPU_BIG_ENDIAN @@ -67,12 +65,12 @@ void arc_init_IRQ(void) irq_prio = irq_bcr.prio; /* Encoded as N-1 for N levels */ pr_info("archs-intc\t: %d priority levels (default %d)%s\n", - irq_prio + 1, irq_prio, + irq_prio + 1, ARCV2_IRQ_DEF_PRIO, irq_bcr.firq ? " FIRQ (not used)":""); /* setup status32, don't enable intr yet as kernel doesn't want */ tmp = read_aux_reg(0xa); - tmp |= STATUS_AD_MASK | (irq_prio << 1); + tmp |= STATUS_AD_MASK | (ARCV2_IRQ_DEF_PRIO << 1); tmp &= ~STATUS_IE_MASK; asm volatile("kflag %0 \n"::"r"(tmp)); } @@ -93,7 +91,7 @@ void arcv2_irq_enable(struct irq_data *data) { /* set default priority */ write_aux_reg(AUX_IRQ_SELECT, data->irq); - write_aux_reg(AUX_IRQ_PRIORITY, irq_prio); + write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO); /* * hw auto enables (linux unmask) all by default |