diff options
author | Ladi Prosek <lprosek@redhat.com> | 2016-08-31 08:00:04 -0400 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2016-10-30 18:21:40 -0400 |
commit | 0ea1e4a6d9b62cf29e210d2b4ba9fd43917522e3 (patch) | |
tree | 7f5b50b9c99b4b2a3278951f69b1222a8e4b2d85 | |
parent | a0be1db4304f51c99af6b6e515549794182a94df (diff) |
virtio_ring: Make interrupt suppression spec compliant
According to the spec, if the VIRTIO_RING_F_EVENT_IDX feature bit is
negotiated the driver MUST set flags to 0. Not dirtying the available
ring in virtqueue_disable_cb also has a minor positive performance
impact, improving L1 dcache load missed by ~0.5% in vring_bench.
Writes to the used event field (vring_used_event) are still unconditional.
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: <stable@vger.kernel.org> # f277ec4 virtio_ring: shadow available
Cc: <stable@vger.kernel.org>
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r-- | drivers/virtio/virtio_ring.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index ed9c9eeedfe5..6b2cd922d322 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -732,7 +732,8 @@ void virtqueue_disable_cb(struct virtqueue *_vq) | |||
732 | 732 | ||
733 | if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) { | 733 | if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) { |
734 | vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; | 734 | vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; |
735 | vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); | 735 | if (!vq->event) |
736 | vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); | ||
736 | } | 737 | } |
737 | 738 | ||
738 | } | 739 | } |
@@ -764,7 +765,8 @@ unsigned virtqueue_enable_cb_prepare(struct virtqueue *_vq) | |||
764 | * entry. Always do both to keep code simple. */ | 765 | * entry. Always do both to keep code simple. */ |
765 | if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { | 766 | if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { |
766 | vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; | 767 | vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; |
767 | vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); | 768 | if (!vq->event) |
769 | vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); | ||
768 | } | 770 | } |
769 | vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx); | 771 | vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx); |
770 | END_USE(vq); | 772 | END_USE(vq); |
@@ -832,10 +834,11 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq) | |||
832 | * more to do. */ | 834 | * more to do. */ |
833 | /* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to | 835 | /* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to |
834 | * either clear the flags bit or point the event index at the next | 836 | * either clear the flags bit or point the event index at the next |
835 | * entry. Always do both to keep code simple. */ | 837 | * entry. Always update the event index to keep code simple. */ |
836 | if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { | 838 | if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { |
837 | vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; | 839 | vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; |
838 | vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); | 840 | if (!vq->event) |
841 | vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); | ||
839 | } | 842 | } |
840 | /* TODO: tune this threshold */ | 843 | /* TODO: tune this threshold */ |
841 | bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4; | 844 | bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4; |
@@ -953,7 +956,8 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index, | |||
953 | /* No callback? Tell other side not to bother us. */ | 956 | /* No callback? Tell other side not to bother us. */ |
954 | if (!callback) { | 957 | if (!callback) { |
955 | vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; | 958 | vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; |
956 | vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow); | 959 | if (!vq->event) |
960 | vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow); | ||
957 | } | 961 | } |
958 | 962 | ||
959 | /* Put everything in free lists. */ | 963 | /* Put everything in free lists. */ |