diff options
| -rw-r--r-- | drivers/net/virtio_net.c | 10 | ||||
| -rw-r--r-- | drivers/virtio/virtio_ring.c | 1 | ||||
| -rw-r--r-- | include/linux/virtio.h | 5 |
3 files changed, 10 insertions, 6 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e575df83e5c2..b58472cf76f8 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -203,8 +203,11 @@ again: | |||
| 203 | if (received < budget) { | 203 | if (received < budget) { |
| 204 | netif_rx_complete(vi->dev, napi); | 204 | netif_rx_complete(vi->dev, napi); |
| 205 | if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) | 205 | if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) |
| 206 | && netif_rx_reschedule(vi->dev, napi)) | 206 | && napi_schedule_prep(napi)) { |
| 207 | vi->rvq->vq_ops->disable_cb(vi->rvq); | ||
| 208 | __netif_rx_schedule(vi->dev, napi); | ||
| 207 | goto again; | 209 | goto again; |
| 210 | } | ||
| 208 | } | 211 | } |
| 209 | 212 | ||
| 210 | return received; | 213 | return received; |
| @@ -278,10 +281,11 @@ again: | |||
| 278 | pr_debug("%s: virtio not prepared to send\n", dev->name); | 281 | pr_debug("%s: virtio not prepared to send\n", dev->name); |
| 279 | netif_stop_queue(dev); | 282 | netif_stop_queue(dev); |
| 280 | 283 | ||
| 281 | /* Activate callback for using skbs: if this fails it | 284 | /* Activate callback for using skbs: if this returns false it |
| 282 | * means some were used in the meantime. */ | 285 | * means some were used in the meantime. */ |
| 283 | if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) { | 286 | if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) { |
| 284 | printk("Unlikely: restart svq failed\n"); | 287 | printk("Unlikely: restart svq race\n"); |
| 288 | vi->svq->vq_ops->disable_cb(vi->svq); | ||
| 285 | netif_start_queue(dev); | 289 | netif_start_queue(dev); |
| 286 | goto again; | 290 | goto again; |
| 287 | } | 291 | } |
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 3a28c1382131..aa714028641e 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
| @@ -232,7 +232,6 @@ static bool vring_enable_cb(struct virtqueue *_vq) | |||
| 232 | vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; | 232 | vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; |
| 233 | mb(); | 233 | mb(); |
| 234 | if (unlikely(more_used(vq))) { | 234 | if (unlikely(more_used(vq))) { |
| 235 | vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; | ||
| 236 | END_USE(vq); | 235 | END_USE(vq); |
| 237 | return false; | 236 | return false; |
| 238 | } | 237 | } |
diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 260d1fcf29a4..12c18ac1b973 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h | |||
| @@ -43,8 +43,9 @@ struct virtqueue | |||
| 43 | * vq: the struct virtqueue we're talking about. | 43 | * vq: the struct virtqueue we're talking about. |
| 44 | * @enable_cb: restart callbacks after disable_cb. | 44 | * @enable_cb: restart callbacks after disable_cb. |
| 45 | * vq: the struct virtqueue we're talking about. | 45 | * vq: the struct virtqueue we're talking about. |
| 46 | * This returns "false" (and doesn't re-enable) if there are pending | 46 | * This re-enables callbacks; it returns "false" if there are pending |
| 47 | * buffers in the queue, to avoid a race. | 47 | * buffers in the queue, to detect a possible race between the driver |
| 48 | * checking for more work, and enabling callbacks. | ||
| 48 | * | 49 | * |
| 49 | * Locking rules are straightforward: the driver is responsible for | 50 | * Locking rules are straightforward: the driver is responsible for |
| 50 | * locking. No two operations may be invoked simultaneously. | 51 | * locking. No two operations may be invoked simultaneously. |
