diff options
author | nwhitehorn <nwhitehorn@FreeBSD.org> | 2011-06-23 04:35:45 +0000 |
---|---|---|
committer | nwhitehorn <nwhitehorn@FreeBSD.org> | 2011-06-23 04:35:45 +0000 |
commit | 6d4918e45e29c8527fe3383af8f33ef6ed977e35 (patch) | |
tree | 96caa0b0bc52f149e1c9f7b542b967489b0a21e8 /sys/powerpc | |
parent | b51f0413bb9eea9e7f306823369257ccace21801 (diff) | |
download | FreeBSD-src-6d4918e45e29c8527fe3383af8f33ef6ed977e35.zip FreeBSD-src-6d4918e45e29c8527fe3383af8f33ef6ed977e35.tar.gz |
Use atomic operations to mask and unmask IRQs. This prevents a problem
(obvious in retrospect) in which interrupts on one CPU that are temporarily
masked can end up permanently masked when a handler on another CPU clobbers
the interrupt mask register with an old copy.
Diffstat (limited to 'sys/powerpc')
-rw-r--r-- | sys/powerpc/ps3/ps3pic.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/sys/powerpc/ps3/ps3pic.c b/sys/powerpc/ps3/ps3pic.c index c00585b..3a62e3c 100644 --- a/sys/powerpc/ps3/ps3pic.c +++ b/sys/powerpc/ps3/ps3pic.c @@ -56,10 +56,10 @@ static void ps3pic_mask(device_t, u_int); static void ps3pic_unmask(device_t, u_int); struct ps3pic_softc { - uint64_t *bitmap_thread0; - uint64_t *mask_thread0; - uint64_t *bitmap_thread1; - uint64_t *mask_thread1; + volatile uint64_t *bitmap_thread0; + volatile uint64_t *mask_thread0; + volatile uint64_t *bitmap_thread1; + volatile uint64_t *mask_thread1; uint64_t sc_ipi_outlet[2]; int sc_vector[64]; @@ -219,8 +219,8 @@ ps3pic_mask(device_t dev, u_int irq) if (irq == sc->sc_ipi_outlet[0]) return; - sc->mask_thread0[0] &= ~(1UL << (63 - irq)); - sc->mask_thread1[0] &= ~(1UL << (63 - irq)); + atomic_clear_64(&sc->mask_thread0[0], 1UL << (63 - irq)); + atomic_clear_64(&sc->mask_thread1[0], 1UL << (63 - irq)); lv1_get_logical_ppe_id(&ppe); lv1_did_update_interrupt_mask(ppe, 0); @@ -234,8 +234,8 @@ ps3pic_unmask(device_t dev, u_int irq) uint64_t ppe; sc = device_get_softc(dev); - sc->mask_thread0[0] |= (1UL << (63 - irq)); - sc->mask_thread1[0] |= (1UL << (63 - irq)); + atomic_set_64(&sc->mask_thread0[0], 1UL << (63 - irq)); + atomic_set_64(&sc->mask_thread1[0], 1UL << (63 - irq)); lv1_get_logical_ppe_id(&ppe); lv1_did_update_interrupt_mask(ppe, 0); |