diff options
| author | Michael S. Tsirkin <mst@redhat.com> | 2015-12-17 05:20:39 -0500 |
|---|---|---|
| committer | Michael S. Tsirkin <mst@redhat.com> | 2016-01-12 13:47:02 -0500 |
| commit | 788e5b3a5da24cc8d93ce2f7c6508181cd7d7fb6 (patch) | |
| tree | 7e54e74c3f7373a04780ad14cb157089c76abeb2 | |
| parent | 9e3f84ce416663c84a191cb3ead300fc1a4adadc (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.c | 15 | ||||
| -rw-r--r-- | include/linux/virtio_ring.h | 11 |
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 | ||
| 48 | static 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 | |||
| 48 | struct virtio_device; | 59 | struct virtio_device; |
| 49 | struct virtqueue; | 60 | struct virtqueue; |
| 50 | 61 | ||
