From 8e229474be145dc9694dec9a4a16c0c08061f7f7 Mon Sep 17 00:00:00 2001 From: kiyohara Date: Tue, 31 Aug 2010 14:33:41 +0000 Subject: [PATCH] Fix lost interrupt. (2/2) + It is likely to lose sight of interrupt when the interrupt of irq_base that is smaller than the same at the level is generated if PIC_MAXSOURCES is 33 or more. --- sys/arch/arm/pic/pic.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/sys/arch/arm/pic/pic.c b/sys/arch/arm/pic/pic.c index 83934a14871f..a087efffdd3f 100644 --- a/sys/arch/arm/pic/pic.c +++ b/sys/arch/arm/pic/pic.c @@ -1,4 +1,4 @@ -/* $NetBSD: pic.c,v 1.5 2010/08/31 14:23:27 kiyohara Exp $ */ +/* $NetBSD: pic.c,v 1.6 2010/08/31 14:33:41 kiyohara Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. * All rights reserved. @@ -28,7 +28,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include -__KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.5 2010/08/31 14:23:27 kiyohara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.6 2010/08/31 14:33:41 kiyohara Exp $"); #define _INTR_PRIVATE #include @@ -193,6 +193,7 @@ pic_deliver_irqs(struct pic_softc *pic, int ipl, void *frame) size_t irq_base; #if PIC_MAXSOURCES > 32 size_t irq_count; + int poi = 0; /* Possibility of interrupting */ #endif uint32_t pending_irqs; uint32_t blocked_irqs; @@ -214,14 +215,20 @@ pic_deliver_irqs(struct pic_softc *pic, int ipl, void *frame) if (pending_irqs == 0) { #if PIC_MAXSOURCES > 32 irq_count += 32; - if (__predict_true(irq_count >= pic->pic_maxsources)) - break; - irq_base += 32; - ipending++; - iblocked++; - if (irq_base >= pic->pic_maxsources) { + if (__predict_true(irq_count >= pic->pic_maxsources)) { + if (!poi) + /*Interrupt at this level was handled.*/ + break; + irq_base = 0; + irq_count = 0; + poi = 0; ipending = pic->pic_pending_irqs; iblocked = pic->pic_blocked_irqs; + } else { + irq_base += 32; + ipending++; + iblocked++; + KASSERT(irq_base <= pic->pic_maxsources); } continue; #else @@ -240,6 +247,13 @@ pic_deliver_irqs(struct pic_softc *pic, int ipl, void *frame) cpsie(I32_bit); pic_dispatch(is, frame); cpsid(I32_bit); +#if PIC_MAXSOURCES > 32 + /* + * There is a possibility of interrupting + * from cpsie() to cpsid(). + */ + poi = 1; +#endif blocked_irqs |= __BIT(irq); } else { KASSERT(0);