aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLadi Prosek <lprosek@redhat.com>2016-08-31 08:00:04 -0400
committerMichael S. Tsirkin <mst@redhat.com>2016-10-30 18:21:40 -0400
commit0ea1e4a6d9b62cf29e210d2b4ba9fd43917522e3 (patch)
tree7f5b50b9c99b4b2a3278951f69b1222a8e4b2d85
parenta0be1db4304f51c99af6b6e515549794182a94df (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.c14
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. */