diff --git a/sys/arch/arm/pic/pic.c b/sys/arch/arm/pic/pic.c index fd8cfce038fc..24ca057c9030 100644 --- a/sys/arch/arm/pic/pic.c +++ b/sys/arch/arm/pic/pic.c @@ -1,4 +1,4 @@ -/* $NetBSD: pic.c,v 1.3 2008/04/28 20:23:14 martin Exp $ */ +/* $NetBSD: pic.c,v 1.4 2008/12/30 05:43:14 matt 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.3 2008/04/28 20:23:14 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.4 2008/12/30 05:43:14 matt Exp $"); #define _INTR_PRIVATE #include @@ -36,6 +36,7 @@ __KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.3 2008/04/28 20:23:14 martin Exp $"); #include #include #include +#include #include #include @@ -61,7 +62,6 @@ struct pic_softc *pic_list[PIC_MAXPICS]; volatile uint32_t pic_blocked_pics; volatile uint32_t pic_pending_pics; volatile uint32_t pic_pending_ipls; -volatile uint32_t pic_pending_ipl_refcnt[NIPL]; struct intrsource *pic_sources[PIC_MAXMAXSOURCES]; struct intrsource *pic__iplsources[PIC_MAXMAXSOURCES]; struct intrsource **pic_iplsource[NIPL] = { @@ -91,11 +91,12 @@ pic_mark_pending_source(struct pic_softc *pic, struct intrsource *is) { const uint32_t ipl_mask = __BIT(is->is_ipl); - pic->pic_pending_irqs[is->is_irq >> 5] |= __BIT(is->is_irq & 0x1f); + atomic_or_32(&pic->pic_pending_irqs[is->is_irq >> 5], + __BIT(is->is_irq & 0x1f)); - pic->pic_pending_ipls |= ipl_mask; - pic_pending_ipls |= ipl_mask; - pic_pending_pics |= __BIT(pic->pic_id); + atomic_or_32(&pic->pic_pending_ipls, ipl_mask); + atomic_or_32(&pic_pending_ipls, ipl_mask); + atomic_or_32(&pic_pending_pics, __BIT(pic->pic_id)); } void @@ -115,7 +116,7 @@ pic_mark_pending_sources(struct pic_softc *pic, size_t irq_base, { struct intrsource ** const isbase = &pic->pic_sources[irq_base]; struct intrsource *is; - uint32_t *ipending = &pic->pic_pending_irqs[irq_base >> 5]; + volatile uint32_t *ipending = &pic->pic_pending_irqs[irq_base >> 5]; uint32_t ipl_mask = 0; if (pending == 0) @@ -125,7 +126,7 @@ pic_mark_pending_sources(struct pic_softc *pic, size_t irq_base, (*pic->pic_ops->pic_block_irqs)(pic, irq_base, pending); - *ipending |= pending; + atomic_or_32(ipending, pending); while (pending != 0) { int n = ffs(pending); if (n-- == 0) @@ -137,9 +138,9 @@ pic_mark_pending_sources(struct pic_softc *pic, size_t irq_base, ipl_mask |= __BIT(is->is_ipl); } - pic->pic_pending_ipls |= ipl_mask; - pic_pending_ipls |= ipl_mask; - pic_pending_pics |= __BIT(pic->pic_id); + atomic_or_32(&pic->pic_pending_ipls, ipl_mask); + atomic_or_32(&pic_pending_ipls, ipl_mask); + atomic_or_32(&pic_pending_pics, __BIT(pic->pic_id)); return ipl_mask; } @@ -187,8 +188,8 @@ pic_deliver_irqs(struct pic_softc *pic, int ipl, void *frame) { const uint32_t ipl_mask = __BIT(ipl); struct intrsource *is; - uint32_t *ipending = pic->pic_pending_irqs; - uint32_t *iblocked = pic->pic_blocked_irqs; + volatile uint32_t *ipending = pic->pic_pending_irqs; + volatile uint32_t *iblocked = pic->pic_blocked_irqs; size_t irq_base; #if PIC_MAXSOURCES > 32 size_t irq_count; @@ -233,7 +234,7 @@ pic_deliver_irqs(struct pic_softc *pic, int ipl, void *frame) irq = ffs(pending_irqs) - 1; KASSERT(irq >= 0); - *ipending &= ~__BIT(irq); + atomic_and_32(ipending, ~__BIT(irq)); is = pic->pic_sources[irq_base + irq]; if (is != NULL) { cpsie(I32_bit); @@ -247,8 +248,8 @@ pic_deliver_irqs(struct pic_softc *pic, int ipl, void *frame) irq_base, *ipending, ipl); } while (pending_irqs); if (blocked_irqs) { - *iblocked |= blocked_irqs; - pic_blocked_pics |= __BIT(pic->pic_id); + atomic_or_32(iblocked, blocked_irqs); + atomic_or_32(&pic_blocked_pics, __BIT(pic->pic_id)); } } @@ -257,25 +258,25 @@ pic_deliver_irqs(struct pic_softc *pic, int ipl, void *frame) * Since interrupts are disabled, we don't have to be too careful * about these. */ - pic->pic_pending_ipls &= ~ipl_mask; - if (pic->pic_pending_ipls == 0) - pic_pending_pics &= ~__BIT(pic->pic_id); + if (atomic_and_32_nv(&pic->pic_pending_ipls, ~ipl_mask) == 0) + atomic_and_32(&pic_pending_pics, ~__BIT(pic->pic_id)); } static void pic_list_unblock_irqs(void) { - uint32_t blocked = pic_blocked_pics; + uint32_t blocked_pics = pic_blocked_pics; pic_blocked_pics = 0; for (;;) { struct pic_softc *pic; #if PIC_MAXSOURCES > 32 - uint32_t *iblocked; + volatile uint32_t *iblocked; + uint32_t blocked; size_t irq_base; #endif - int pic_id = ffs(blocked); + int pic_id = ffs(blocked_pics); if (pic_id-- == 0) return; @@ -285,18 +286,19 @@ pic_list_unblock_irqs(void) for (irq_base = 0, iblocked = pic->pic_blocked_irqs; irq_base < pic->pic_maxsources; irq_base += 32, iblocked++) { - if (*iblocked) { + if ((blocked = *iblocked) != 0) { (*pic->pic_ops->pic_unblock_irqs)(pic, - irq_base, *iblocked); - *iblocked = 0; + irq_base, blocked); + atomic_and_32(iblocked, ~blocked); } } - blocked &= ~__BIT(pic_id); #else KASSERT(pic->pic_blocked_irqs[0] != 0); (*pic->pic_ops->pic_unblock_irqs)(pic, 0, pic->pic_blocked_irqs[0]); + pic->pic_blocked_irqs[0] = 0; #endif + blocked_pics &= ~__BIT(pic_id); } } @@ -304,11 +306,11 @@ pic_list_unblock_irqs(void) struct pic_softc * pic_list_find_pic_by_pending_ipl(uint32_t ipl_mask) { - uint32_t pending = pic_pending_pics; + uint32_t pending_pics = pic_pending_pics; struct pic_softc *pic; for (;;) { - int pic_id = ffs(pending); + int pic_id = ffs(pending_pics); if (pic_id-- == 0) return NULL; @@ -316,7 +318,7 @@ pic_list_find_pic_by_pending_ipl(uint32_t ipl_mask) KASSERT(pic != NULL); if (pic->pic_pending_ipls & ipl_mask) return pic; - pending &= ~__BIT(pic_id); + pending_pics &= ~__BIT(pic_id); } } @@ -330,7 +332,7 @@ pic_list_deliver_irqs(register_t psw, int ipl, void *frame) pic_deliver_irqs(pic, ipl, frame); KASSERT((pic->pic_pending_ipls & ipl_mask) == 0); } - pic_pending_ipls &= ~ipl_mask; + atomic_and_32(&pic_pending_ipls, ~ipl_mask); } void diff --git a/sys/arch/arm/pic/picvar.h b/sys/arch/arm/pic/picvar.h index d42bcd636fff..24929bc3292d 100644 --- a/sys/arch/arm/pic/picvar.h +++ b/sys/arch/arm/pic/picvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: picvar.h,v 1.3 2008/04/28 20:23:14 martin Exp $ */ +/* $NetBSD: picvar.h,v 1.4 2008/12/30 05:43:14 matt Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. * All rights reserved. @@ -82,9 +82,9 @@ struct intrsource { struct pic_softc { const struct pic_ops *pic_ops; struct intrsource **pic_sources; - uint32_t pic_pending_irqs[(PIC_MAXSOURCES + 31) / 32]; - uint32_t pic_blocked_irqs[(PIC_MAXSOURCES + 31) / 32]; - uint32_t pic_pending_ipls; + volatile uint32_t pic_pending_irqs[(PIC_MAXSOURCES + 31) / 32]; + volatile uint32_t pic_blocked_irqs[(PIC_MAXSOURCES + 31) / 32]; + volatile uint32_t pic_pending_ipls; size_t pic_maxsources; uint8_t pic_id; int16_t pic_irqbase;