aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/virtio/virtio_ring.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 99dc9480f3fe..36bb6a613728 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -251,9 +251,20 @@ add_head:
251 251
252 /* Put entry in available array (but don't update avail->idx until they 252 /* Put entry in available array (but don't update avail->idx until they
253 * do sync). */ 253 * do sync). */
254 avail = ((vq->vring.avail->idx + vq->num_added++) & (vq->vring.num-1)); 254 avail = (vq->vring.avail->idx & (vq->vring.num-1));
255 vq->vring.avail->ring[avail] = head; 255 vq->vring.avail->ring[avail] = head;
256 256
257 /* Descriptors and available array need to be set before we expose the
258 * new available array entries. */
259 virtio_wmb(vq);
260 vq->vring.avail->idx++;
261 vq->num_added++;
262
263 /* This is very unlikely, but theoretically possible. Kick
264 * just in case. */
265 if (unlikely(vq->num_added == (1 << 16) - 1))
266 virtqueue_kick(_vq);
267
257 pr_debug("Added buffer head %i to %p\n", head, vq); 268 pr_debug("Added buffer head %i to %p\n", head, vq);
258 END_USE(vq); 269 END_USE(vq);
259 270
@@ -283,13 +294,10 @@ bool virtqueue_kick_prepare(struct virtqueue *_vq)
283 * new available array entries. */ 294 * new available array entries. */
284 virtio_wmb(vq); 295 virtio_wmb(vq);
285 296
286 old = vq->vring.avail->idx; 297 old = vq->vring.avail->idx - vq->num_added;
287 new = vq->vring.avail->idx = old + vq->num_added; 298 new = vq->vring.avail->idx;
288 vq->num_added = 0; 299 vq->num_added = 0;
289 300
290 /* Need to update avail index before checking if we should notify */
291 virtio_mb(vq);
292
293 if (vq->event) { 301 if (vq->event) {
294 needs_kick = vring_need_event(vring_avail_event(&vq->vring), 302 needs_kick = vring_need_event(vring_avail_event(&vq->vring),
295 new, old); 303 new, old);