Use atomic ops to manipulate the bitmasks.

This commit is contained in:
matt 2008-12-30 05:43:14 +00:00
parent 9c5307acaa
commit a7cf4e5ecd
2 changed files with 37 additions and 35 deletions

View File

@ -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 <sys/cdefs.h>
__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 <sys/param.h>
@ -36,6 +36,7 @@ __KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.3 2008/04/28 20:23:14 martin Exp $");
#include <sys/atomic.h>
#include <sys/malloc.h>
#include <sys/mallocvar.h>
#include <sys/atomic.h>
#include <arm/armreg.h>
#include <arm/cpu.h>
@ -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

View File

@ -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;