aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rpmsg
diff options
context:
space:
mode:
authorDan Murphy <dmurphy@ti.com>2011-08-29 07:32:46 -0500
committerDan Murphy <dmurphy@ti.com>2011-08-29 07:32:46 -0500
commitf8264deb79e97dc8d4cc926fe708996ac8018d6c (patch)
treef036cd0a7479081f37a116f6ecbad59937610bf4 /drivers/rpmsg
parent0c00ff0fab16d85b94ff213b3f9fa0c7abaf6a40 (diff)
parentd5ea29096af4b41cf8b04f82fd6836b8c04ebd15 (diff)
downloadkernel_samsung_espresso10-f8264deb79e97dc8d4cc926fe708996ac8018d6c.zip
kernel_samsung_espresso10-f8264deb79e97dc8d4cc926fe708996ac8018d6c.tar.gz
kernel_samsung_espresso10-f8264deb79e97dc8d4cc926fe708996ac8018d6c.tar.bz2
Merge branch 'android-omap-3.0' into p-android-omap-3.0
* android-omap-3.0: rpmsg: serialize transmissions and add proper barriers gpu: pvr: Update to DDK 1.8@279068 gpu: pvr: Update to DDK 1.8@278427 gpu: pvr: Update to DDK 1.8@277528 netfilter: xt_qtaguid: fix dev_stats for missing NETDEV_UNREGISTER fuse: Freeze client on suspend when request sent to userspace Conflicts: drivers/gpu/pvr/pvrversion.h Change-Id: I7f9c4cae75fc6b70c1a330b471802149ecde2370
Diffstat (limited to 'drivers/rpmsg')
-rw-r--r--drivers/rpmsg/virtio_rpmsg_bus.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 33d3a49..bd6408a 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -420,9 +420,8 @@ static void *get_a_buf(struct virtproc_info *vrp)
unsigned int len;
void *buf = NULL;
- /* protect svq from simultaneous concurrent manipulations */
- mutex_lock(&vrp->svq_lock);
-
+ /* make sure the descriptors are updated before reading */
+ rmb();
/* either pick the next unused buffer */
if (vrp->last_sbuf < vrp->num_bufs / 2)
buf = vrp->sbufs + vrp->buf_size * vrp->last_sbuf++;
@@ -430,7 +429,6 @@ static void *get_a_buf(struct virtproc_info *vrp)
else
buf = virtqueue_get_buf(vrp->svq, &len);
- mutex_unlock(&vrp->svq_lock);
return buf;
}
@@ -457,10 +455,18 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
return -EMSGSIZE;
}
+ /*
+ * protect svq from simultaneous concurrent manipulations,
+ * and serialize the sending of messages
+ */
+ if (mutex_lock_interruptible(&vrp->svq_lock))
+ return -ERESTARTSYS;
/* grab a buffer */
msg = get_a_buf(vrp);
- if (!msg && !wait)
- return -ENOMEM;
+ if (!msg && !wait) {
+ err = -ENOMEM;
+ goto out;
+ }
/* no free buffer ? wait for one (but bail after 15 seconds) */
if (!msg) {
@@ -480,12 +486,15 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
/* on success, suppress "tx-complete" interrupts again */
virtqueue_disable_cb(vrp->svq);
- if (err < 0)
- return -ERESTARTSYS;
+ if (err < 0) {
+ err = -ERESTARTSYS;
+ goto out;
+ }
if (!msg) {
dev_err(dev, "timeout waiting for buffer\n");
- return -ETIMEDOUT;
+ err = -ETIMEDOUT;
+ goto out;
}
}
@@ -506,15 +515,14 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
sim_addr = vrp->sim_base + offset;
sg_init_one(&sg, sim_addr, sizeof(*msg) + len);
- /* protect svq from simultaneous concurrent manipulations */
- mutex_lock(&vrp->svq_lock);
-
/* add message to the remote processor's virtqueue */
err = virtqueue_add_buf_gfp(vrp->svq, &sg, 1, 0, msg, GFP_KERNEL);
if (err < 0) {
dev_err(dev, "virtqueue_add_buf_gfp failed: %d\n", err);
goto out;
}
+ /* descriptors must be written before kicking remote processor */
+ wmb();
/* tell the remote processor it has a pending message to read */
virtqueue_kick(vrp->svq);
@@ -538,6 +546,8 @@ static void rpmsg_recv_done(struct virtqueue *rvq)
struct device *dev = &rvq->vdev->dev;
int err;
+ /* make sure the descriptors are updated before reading */
+ rmb();
msg = virtqueue_get_buf(rvq, &len);
if (!msg) {
dev_err(dev, "uhm, incoming signal, but no used buffer ?\n");
@@ -570,6 +580,8 @@ static void rpmsg_recv_done(struct virtqueue *rvq)
dev_err(dev, "failed to add a virtqueue buffer: %d\n", err);
return;
}
+ /* descriptors must be written before kicking remote processor */
+ wmb();
/* tell the remote processor we added another available rx buffer */
virtqueue_kick(vrp->rvq);