Skip to content

Commit

Permalink
virtio: handle interrupts after callbacks turned off
Browse files Browse the repository at this point in the history
Anthony Liguori found double interrupt suppression in the virtio_net
driver, triggered by two skb_recv_done's in a row.  This is because
virtio_ring's interrupt suppression is a best-effort optimization: it
contains no synchronization so the host can miss it and still send
interrupts.

But it's certainly nicer for virtio users if calling disable_cb
actually disables callbacks, so we check for the race in the interrupt
routine.

Note: SMP guests might require syncronization here, but since
disable_cb is actually called from interrupt context, there has to be
some form of synchronization before the next same interrupt handler is
called (Linux guarantees that the same device's irq handler will never
run simultanously on multiple CPUs).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
Rusty Russell committed Feb 4, 2008
1 parent 6e5aa7e commit 81a8dea
Showing 1 changed file with 7 additions and 0 deletions.
7 changes: 7 additions & 0 deletions drivers/virtio/virtio_ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,13 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
if (unlikely(vq->broken))
return IRQ_HANDLED;

/* Other side may have missed us turning off the interrupt,
* but we should preserve disable semantic for virtio users. */
if (unlikely(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) {
pr_debug("virtqueue interrupt after disable for %p\n", vq);
return IRQ_HANDLED;
}

pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback);
if (vq->vq.callback)
vq->vq.callback(&vq->vq);
Expand Down

0 comments on commit 81a8dea

Please sign in to comment.