diff options
author | gonzo <gonzo@FreeBSD.org> | 2015-11-11 00:41:02 +0000 |
---|---|---|
committer | gonzo <gonzo@FreeBSD.org> | 2015-11-11 00:41:02 +0000 |
commit | 2d514663ea6496496cc10c38c52f3af98d57ac43 (patch) | |
tree | ba4bfcde67062b71299af47c6d99608e40bde937 /sys/arm/broadcom/bcm2835/bcm2835_mbox.c | |
parent | 8772a4364f8d7098f28bd70c0a487908364be1ec (diff) | |
download | FreeBSD-src-2d514663ea6496496cc10c38c52f3af98d57ac43.zip FreeBSD-src-2d514663ea6496496cc10c38c52f3af98d57ac43.tar.gz |
- Set have_message in interrupt to handle "response before READ" case
- Serialize access to property channel when using bcm2835_mbox_property
Diffstat (limited to 'sys/arm/broadcom/bcm2835/bcm2835_mbox.c')
-rw-r--r-- | sys/arm/broadcom/bcm2835/bcm2835_mbox.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c index 5f75fd4..221bccc 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/module.h> #include <sys/mutex.h> +#include <sys/sx.h> #include <sys/rman.h> #include <machine/bus.h> @@ -83,6 +84,7 @@ struct bcm_mbox_softc { bus_space_handle_t bsh; int msg[BCM2835_MBOX_CHANS]; int have_message[BCM2835_MBOX_CHANS]; + struct sx property_chan_lock; }; #define mbox_read_4(sc, reg) \ @@ -122,8 +124,10 @@ bcm_mbox_intr(void *arg) MBOX_LOCK(sc); while (!(mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY)) - if (bcm_mbox_read_msg(sc, &chan) == 0) + if (bcm_mbox_read_msg(sc, &chan) == 0) { + sc->have_message[chan] = 1; wakeup(&sc->have_message[chan]); + } MBOX_UNLOCK(sc); } @@ -179,6 +183,8 @@ bcm_mbox_attach(device_t dev) sc->have_message[i] = 0; } + sx_init(&sc->property_chan_lock, "mboxprop"); + /* Read all pending messages */ while ((mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY) == 0) (void)mbox_read_4(sc, REG_READ); @@ -366,6 +372,7 @@ bcm2835_mbox_err(device_t dev, bus_addr_t msg_phys, uint32_t resp_phys, int bcm2835_mbox_property(void *msg, size_t msg_size) { + struct bcm_mbox_softc *sc; struct msg_set_power_state *buf; bus_dma_tag_t msg_tag; bus_dmamap_t msg_map; @@ -379,11 +386,16 @@ bcm2835_mbox_property(void *msg, size_t msg_size) if (mbox == NULL) return (ENXIO); + sc = device_get_softc(mbox); + sx_xlock(&sc->property_chan_lock); + /* Allocate memory for the message */ buf = bcm2835_mbox_init_dma(mbox, msg_size, &msg_tag, &msg_map, &msg_phys); - if (buf == NULL) - return (ENOMEM); + if (buf == NULL) { + err = ENOMEM; + goto out; + } memcpy(buf, msg, msg_size); @@ -404,7 +416,8 @@ bcm2835_mbox_property(void *msg, size_t msg_size) bus_dmamap_unload(msg_tag, msg_map); bus_dmamem_free(msg_tag, buf, msg_map); bus_dma_tag_destroy(msg_tag); - +out: + sx_xunlock(&sc->property_chan_lock); return (err); } |