aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2015-12-17 05:20:39 -0500
committerMichael S. Tsirkin <mst@redhat.com>2016-01-12 13:47:02 -0500
commit788e5b3a5da24cc8d93ce2f7c6508181cd7d7fb6 (patch)
tree7e54e74c3f7373a04780ad14cb157089c76abeb2
parent9e3f84ce416663c84a191cb3ead300fc1a4adadc (diff)
virtio_ring: use virt_store_mb
We need a full barrier after writing out event index, using virt_store_mb there seems better than open-coding. As usual, we need a wrapper to account for strong barriers. It's tempting to use this in vhost as well, for that, we'll need a variant of smp_store_mb that works on __user pointers. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
-rw-r--r--drivers/virtio/virtio_ring.c15
-rw-r--r--include/linux/virtio_ring.h11
2 files changed, 20 insertions, 6 deletions
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index ee663c458b20..e12e385f7ac3 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -517,10 +517,10 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
517 /* If we expect an interrupt for the next entry, tell host 517 /* If we expect an interrupt for the next entry, tell host
518 * by writing event index and flush out the write before 518 * by writing event index and flush out the write before
519 * the read in the next get_buf call. */ 519 * the read in the next get_buf call. */
520 if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) { 520 if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT))
521 vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx); 521 virtio_store_mb(vq->weak_barriers,
522 virtio_mb(vq->weak_barriers); 522 &vring_used_event(&vq->vring),
523 } 523 cpu_to_virtio16(_vq->vdev, vq->last_used_idx));
524 524
525#ifdef DEBUG 525#ifdef DEBUG
526 vq->last_add_time_valid = false; 526 vq->last_add_time_valid = false;
@@ -653,8 +653,11 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
653 } 653 }
654 /* TODO: tune this threshold */ 654 /* TODO: tune this threshold */
655 bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4; 655 bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4;
656 vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx + bufs); 656
657 virtio_mb(vq->weak_barriers); 657 virtio_store_mb(vq->weak_barriers,
658 &vring_used_event(&vq->vring),
659 cpu_to_virtio16(_vq->vdev, vq->last_used_idx + bufs));
660
658 if (unlikely((u16)(virtio16_to_cpu(_vq->vdev, vq->vring.used->idx) - vq->last_used_idx) > bufs)) { 661 if (unlikely((u16)(virtio16_to_cpu(_vq->vdev, vq->vring.used->idx) - vq->last_used_idx) > bufs)) {
659 END_USE(vq); 662 END_USE(vq);
660 return false; 663 return false;
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index f3fa55bdd6ce..a156e2b6ccfe 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -45,6 +45,17 @@ static inline void virtio_wmb(bool weak_barriers)
45 wmb(); 45 wmb();
46} 46}
47 47
48static inline void virtio_store_mb(bool weak_barriers,
49 __virtio16 *p, __virtio16 v)
50{
51 if (weak_barriers) {
52 virt_store_mb(*p, v);
53 } else {
54 WRITE_ONCE(*p, v);
55 mb();
56 }
57}
58
48struct virtio_device; 59struct virtio_device;
49struct virtqueue; 60struct virtqueue;
50 61