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.
This commit is contained in:
kiyohara 2010-08-31 14:33:41 +00:00
parent 4edbb19773
commit 8e229474be
1 changed files with 22 additions and 8 deletions

View File

@ -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 <sys/cdefs.h>
__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 <sys/param.h>
@ -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);