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