summaryrefslogtreecommitdiffstats
path: root/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2015-11-11 00:41:02 +0000
committergonzo <gonzo@FreeBSD.org>2015-11-11 00:41:02 +0000
commit2d514663ea6496496cc10c38c52f3af98d57ac43 (patch)
treeba4bfcde67062b71299af47c6d99608e40bde937 /sys/arm/broadcom/bcm2835/bcm2835_mbox.c
parent8772a4364f8d7098f28bd70c0a487908364be1ec (diff)
downloadFreeBSD-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.c21
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);
}
OpenPOWER on IntegriCloud