Port-arm archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[PATCH 3/8] Reworked: ARM: fix interrupt depth counting softint breakage
From: Andy Shevchenko <andy.shevchenko%teleca.com@localhost>
The fast soft interrupt handler should be executed when interrupt depth
is equal to 0. So, we need to revert back the depth value before
cpu_dosoftints() call. Without this we have got panic just after Ctrl+C
pressing in the shell when __HAVE_FAST_SOFTINTS is enabled.
---
sys/arch/arm/arm32/irq_dispatch.S | 18 ------------------
sys/arch/arm/ep93xx/ep93xx_intr.c | 4 ++++
sys/arch/arm/footbridge/footbridge_irqhandler.c | 4 ++++
sys/arch/arm/imx/imx31_icu.c | 4 ++++
sys/arch/arm/ixp12x0/ixp12x0_intr.c | 3 +++
sys/arch/arm/omap/omap2430_intr.c | 8 ++++++++
sys/arch/arm/omap/omap_intr.c | 4 ++++
sys/arch/arm/pic/pic.c | 6 ++++++
sys/arch/arm/s3c2xx0/s3c2410_intr.c | 5 ++++-
sys/arch/arm/s3c2xx0/s3c2800_intr.c | 4 ++++
sys/arch/arm/xscale/i80321_icu.c | 4 ++++
sys/arch/arm/xscale/ixp425_intr.c | 4 ++++
sys/arch/arm/xscale/pxa2x0_intr.c | 4 ++++
13 files changed, 53 insertions(+), 19 deletions(-)
diff --git a/sys/arch/arm/arm32/irq_dispatch.S
b/sys/arch/arm/arm32/irq_dispatch.S
index 77d92c3..9ac19c5 100644
--- a/sys/arch/arm/arm32/irq_dispatch.S
+++ b/sys/arch/arm/arm32/irq_dispatch.S
@@ -104,28 +104,10 @@ ASENTRY_NP(irq_entry)
PUSHFRAMEINSVC /* Push an interrupt frame */
ENABLE_ALIGNMENT_FAULTS /* finishes with curcpu() in r4 */
- /*
- * Increment the interrupt nesting depth and call the interrupt
- * dispatch routine. We've pushed a frame, so we can safely use
- * callee-saved regs here. We use the following registers, which
- * we expect to presist:
- *
- * r4 address of current cpu_info
- * r6 old value of `ci_intr_depth'
- */
mov r0, sp /* arg for dispatcher */
- ldr r6, [r4, #CI_INTR_DEPTH]
- add r1, r6, #1
- str r1, [r4, #CI_INTR_DEPTH]
bl ARM_IRQ_HANDLER
- /*
- * Restore the old interrupt depth value (which should be the
- * same as decrementing it at this point).
- */
- str r6, [r4, #CI_INTR_DEPTH]
-
LOCK_CAS_CHECK
DO_AST_AND_RESTORE_ALIGNMENT_FAULTS
diff --git a/sys/arch/arm/ep93xx/ep93xx_intr.c
b/sys/arch/arm/ep93xx/ep93xx_intr.c
index db0cffe..fb4a5ef 100644
--- a/sys/arch/arm/ep93xx/ep93xx_intr.c
+++ b/sys/arch/arm/ep93xx/ep93xx_intr.c
@@ -330,6 +330,8 @@ ep93xx_intr_dispatch(struct irqframe *frame)
pcpl = curcpl();
+ ci->ci_intr_depth++;
+
vic1_hwpend = VIC1REG(EP93XX_VIC_IRQStatus);
vic2_hwpend = VIC2REG(EP93XX_VIC_IRQStatus);
@@ -370,6 +372,8 @@ ep93xx_intr_dispatch(struct irqframe *frame)
hardware_spl_level = pcpl;
ep93xx_set_intrmask(vic1_imask[pcpl], vic2_imask[pcpl]);
+ ci->ci_intr_depth--;
+
#ifdef __HAVE_FAST_SOFTINTS
cpu_dosoftints();
#endif
diff --git a/sys/arch/arm/footbridge/footbridge_irqhandler.c
b/sys/arch/arm/footbridge/footbridge_irqhandler.c
index 6d720bd..8ab5faf 100644
--- a/sys/arch/arm/footbridge/footbridge_irqhandler.c
+++ b/sys/arch/arm/footbridge/footbridge_irqhandler.c
@@ -284,6 +284,8 @@ footbridge_intr_dispatch(struct clockframe *frame)
const int ppl = ci->ci_cpl;
const int imask = footbridge_imask[ppl];
+ ci->ci_intr_depth++;
+
hwpend = footbridge_intstatus();
/*
@@ -334,6 +336,8 @@ footbridge_intr_dispatch(struct clockframe *frame)
hwpend |= (footbridge_ipending & ICU_INT_HWMASK) & ~imask;
}
+ ci->ci_intr_depth--;
+
#ifdef __HAVE_FAST_SOFTINTS
cpu_dosoftints();
#endif /* __HAVE_FAST_SOFTINTS */
diff --git a/sys/arch/arm/imx/imx31_icu.c b/sys/arch/arm/imx/imx31_icu.c
index 77c7e27..adc62d3 100644
--- a/sys/arch/arm/imx/imx31_icu.c
+++ b/sys/arch/arm/imx/imx31_icu.c
@@ -159,6 +159,8 @@ imx31_irq_handler(void *frame)
int32_t irq;
int ipl, newipl, oldipl;
+ ci->ci_intr_depth++;
+
saved_nimask = INTC_READ(avic, IMX31_NIMASK);
for (;;) {
irq = INTC_READ(avic, IMX31_NIVECSR);
@@ -199,6 +201,8 @@ imx31_irq_handler(void *frame)
splx(oldipl);
INTC_WRITE(avic, IMX31_NIMASK, saved_nimask);
}
+
+ ci->ci_intr_depth--;
}
static int avic_match(device_t, cfdata_t, void *);
diff --git a/sys/arch/arm/ixp12x0/ixp12x0_intr.c
b/sys/arch/arm/ixp12x0/ixp12x0_intr.c
index 69a3496..1404f16 100644
--- a/sys/arch/arm/ixp12x0/ixp12x0_intr.c
+++ b/sys/arch/arm/ixp12x0/ixp12x0_intr.c
@@ -388,6 +388,7 @@ ixp12x0_intr_dispatch(struct irqframe *frame)
int irq;
u_int32_t ibit;
+ ci->ci_intr_depth++;
hwpend = ixp12x0_irq_read();
pci_hwpend = ixp12x0_pci_irq_read();
@@ -433,6 +434,8 @@ ixp12x0_intr_dispatch(struct irqframe *frame)
hardware_spl_level = ppl;
ixp12x0_set_intrmask(imask[ppl], pci_imask[ppl]);
+ ci->ci_intr_depth--;
+
#ifdef __HAVE_FAST_SOFTINTS
cpu_dosoftints();
#endif
diff --git a/sys/arch/arm/omap/omap2430_intr.c
b/sys/arch/arm/omap/omap2430_intr.c
index 5cf5e58..18479dd 100644
--- a/sys/arch/arm/omap/omap2430_intr.c
+++ b/sys/arch/arm/omap/omap2430_intr.c
@@ -466,6 +466,8 @@ deliver_irqs(register_t psw, int ipl, void *frame)
static inline void
do_pending_ints(register_t psw, int newipl)
{
+ ci->ci_intr_depth++;
+
while ((pending_ipls & ~__BIT(newipl)) > __BIT(newipl)) {
KASSERT(pending_ipls < __BIT(NIPL));
for (;;) {
@@ -479,6 +481,8 @@ do_pending_ints(register_t psw, int newipl)
}
}
curcpu()->ci_cpl = newipl;
+
+ ci->ci_intr_depth--;
}
int
@@ -536,12 +540,16 @@ omap_irq_handler(void *frame)
* The clock intr will handle being called at IPLs != IPL_CLOCK.
*/
if (__predict_false(pending_ipls & __BIT(IPL_STATCLOCK))) {
+ ci->ci_intr_depth++;
deliver_irqs(0, IPL_STATCLOCK, frame);
pending_ipls &= ~__BIT(IPL_STATCLOCK);
+ ci->ci_intr_depth--;
}
if (__predict_false(pending_ipls & __BIT(IPL_CLOCK))) {
+ ci->ci_intr_depth++;
deliver_irqs(0, IPL_CLOCK, frame);
pending_ipls &= ~__BIT(IPL_CLOCK);
+ ci->ci_intr_depth--;
}
/*
diff --git a/sys/arch/arm/omap/omap_intr.c b/sys/arch/arm/omap/omap_intr.c
index b40ed48..a1c243c 100644
--- a/sys/arch/arm/omap/omap_intr.c
+++ b/sys/arch/arm/omap/omap_intr.c
@@ -217,6 +217,8 @@ omap_irq_handler(void *arg)
int bank;
int level2 = 0;
+ ci->ci_intr_depth++;
+
saved_spl_level = curcpl();
for (bank = 0; bank < OMAP_NBANKS; bank++) {
@@ -297,6 +299,8 @@ omap_irq_handler(void *arg)
/* Restore spl to what it was when this interrupt happened. */
splx(saved_spl_level);
+
+ ci->ci_intr_depth--;
}
static int
diff --git a/sys/arch/arm/pic/pic.c b/sys/arch/arm/pic/pic.c
index aa5118c..c8053a6 100644
--- a/sys/arch/arm/pic/pic.c
+++ b/sys/arch/arm/pic/pic.c
@@ -339,6 +339,9 @@ pic_do_pending_ints(register_t psw, int newipl, void *frame)
struct cpu_info * const ci = curcpu();
if (__predict_false(newipl == IPL_HIGH))
return;
+
+ ci->ci_intr_depth++;
+
while ((pic_pending_ipls & ~__BIT(newipl)) > __BIT(newipl)) {
KASSERT(pic_pending_ipls < __BIT(NIPL));
for (;;) {
@@ -352,6 +355,9 @@ pic_do_pending_ints(register_t psw, int newipl, void *frame)
pic_list_unblock_irqs();
}
}
+
+ ci->ci_intr_depth--;
+
if (ci->ci_cpl != newipl)
ci->ci_cpl = newipl;
#ifdef __HAVE_FAST_SOFTINTS
diff --git a/sys/arch/arm/s3c2xx0/s3c2410_intr.c
b/sys/arch/arm/s3c2xx0/s3c2410_intr.c
index a494717..2455507 100644
--- a/sys/arch/arm/s3c2xx0/s3c2410_intr.c
+++ b/sys/arch/arm/s3c2xx0/s3c2410_intr.c
@@ -98,6 +98,8 @@ s3c2410_irq_handler(struct clockframe *frame)
int irqno;
int saved_spl_level;
+ ci->ci_intr_depth++;
+
saved_spl_level = curcpl();
#ifdef DIAGNOSTIC
@@ -136,9 +138,10 @@ s3c2410_irq_handler(struct clockframe *frame)
/* restore spl to that was when this interrupt happen */
s3c2xx0_setipl(saved_spl_level);
-
}
+ ci->ci_intr_depth--;
+
#ifdef __HAVE_FAST_SOFTINTS
cpu_dosoftints();
#endif
diff --git a/sys/arch/arm/s3c2xx0/s3c2800_intr.c
b/sys/arch/arm/s3c2xx0/s3c2800_intr.c
index 12cc509..b4b41ea 100644
--- a/sys/arch/arm/s3c2xx0/s3c2800_intr.c
+++ b/sys/arch/arm/s3c2xx0/s3c2800_intr.c
@@ -87,6 +87,8 @@ s3c2800_irq_handler(struct clockframe *frame)
int irqno;
int saved_spl_level;
+ ci->ci_intr_depth++;
+
saved_spl_level = curcpl();
while ((irqbits = icreg(INTCTL_IRQPND) & ICU_INT_HWMASK) != 0) {
@@ -117,6 +119,8 @@ s3c2800_irq_handler(struct clockframe *frame)
s3c2xx0_setipl(saved_spl_level);
}
+ ci->ci_intr_depth--;
+
#ifdef __HAVE_FAST_SOFTINTS
cpu_dosoftints();
#endif
diff --git a/sys/arch/arm/xscale/i80321_icu.c b/sys/arch/arm/xscale/i80321_icu.c
index ef759f6..bcfaf6e 100644
--- a/sys/arch/arm/xscale/i80321_icu.c
+++ b/sys/arch/arm/xscale/i80321_icu.c
@@ -373,6 +373,8 @@ i80321_intr_dispatch(struct clockframe *frame)
const int ppl = ci->ci_cpl;
const uint32_t imask = i80321_imask[ppl];
+ ci->ci_intr_depth++;
+
hwpend = i80321_iintsrc_read();
/*
@@ -464,6 +466,8 @@ i80321_intr_dispatch(struct clockframe *frame)
hwpend |= ((i80321_ipending & ICU_INT_HWMASK) & ~imask);
}
+ ci->ci_intr_depth--;
+
#ifdef __HAVE_FAST_SOFTINTS
cpu_dosoftints();
#endif
diff --git a/sys/arch/arm/xscale/ixp425_intr.c
b/sys/arch/arm/xscale/ixp425_intr.c
index 33592c1..803edc2 100644
--- a/sys/arch/arm/xscale/ixp425_intr.c
+++ b/sys/arch/arm/xscale/ixp425_intr.c
@@ -390,6 +390,8 @@ ixp425_intr_dispatch(struct clockframe *frame)
const int ppl = ci->ci_cpl;
const uint32_t imask = ixp425_imask[ppl];
+ ci->ci_intr_depth++;
+
hwpend = ixp425_irq_read();
/*
@@ -452,6 +454,8 @@ ixp425_intr_dispatch(struct clockframe *frame)
hwpend |= ((ixp425_ipending & IXP425_INT_HWMASK) & ~imask);
}
+ ci->ci_intr_depth--;
+
#ifdef __HAVE_FAST_SOFTINTS
cpu_dosoftints();
#endif
diff --git a/sys/arch/arm/xscale/pxa2x0_intr.c
b/sys/arch/arm/xscale/pxa2x0_intr.c
index a2acaad..97f5ce4 100644
--- a/sys/arch/arm/xscale/pxa2x0_intr.c
+++ b/sys/arch/arm/xscale/pxa2x0_intr.c
@@ -164,6 +164,8 @@ pxa2x0_irq_handler(void *arg)
int irqno;
int saved_spl_level;
+ ci->ci_intr_depth++;
+
saved_spl_level = curcpu()->ci_cpl;
/* get pending IRQs */
@@ -198,6 +200,8 @@ pxa2x0_irq_handler(void *arg)
/* restore spl to that was when this interrupt happen */
pxa2x0_setipl(saved_spl_level);
+ ci->ci_intr_depth--;
+
#ifdef __HAVE_FAST_SOFTINTS
cpu_dosoftints();
#endif
--
1.5.6.56.g29b0d
Home |
Main Index |
Thread Index |
Old Index