git.samba.org
/
sfrench
/
cifs-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
virtio: fix race in enable_cb
[sfrench/cifs-2.6.git]
/
drivers
/
net
/
virtio_net.c
diff --git
a/drivers/net/virtio_net.c
b/drivers/net/virtio_net.c
index 19fd4cb0ddf8583cbd9235b6085a7ad1100dfa19..b58472cf76f862c16fa861b02bcb494008c00f90 100644
(file)
--- a/
drivers/net/virtio_net.c
+++ b/
drivers/net/virtio_net.c
@@
-203,8
+203,11
@@
again:
if (received < budget) {
netif_rx_complete(vi->dev, napi);
if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq))
if (received < budget) {
netif_rx_complete(vi->dev, napi);
if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq))
- && netif_rx_reschedule(vi->dev, napi))
+ && napi_schedule_prep(napi)) {
+ vi->rvq->vq_ops->disable_cb(vi->rvq);
+ __netif_rx_schedule(vi->dev, napi);
goto again;
goto again;
+ }
}
return received;
}
return received;
@@
-278,10
+281,11
@@
again:
pr_debug("%s: virtio not prepared to send\n", dev->name);
netif_stop_queue(dev);
pr_debug("%s: virtio not prepared to send\n", dev->name);
netif_stop_queue(dev);
- /* Activate callback for using skbs: if this
fails
it
+ /* Activate callback for using skbs: if this
returns false
it
* means some were used in the meantime. */
if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
* means some were used in the meantime. */
if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
- printk("Unlikely: restart svq failed\n");
+ printk("Unlikely: restart svq race\n");
+ vi->svq->vq_ops->disable_cb(vi->svq);
netif_start_queue(dev);
goto again;
}
netif_start_queue(dev);
goto again;
}
@@
-294,6
+298,15
@@
again:
return 0;
}
return 0;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void virtnet_netpoll(struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+
+ napi_schedule(&vi->napi);
+}
+#endif
+
static int virtnet_open(struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
static int virtnet_open(struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
@@
-336,6
+349,9
@@
static int virtnet_probe(struct virtio_device *vdev)
dev->stop = virtnet_close;
dev->hard_start_xmit = start_xmit;
dev->features = NETIF_F_HIGHDMA;
dev->stop = virtnet_close;
dev->hard_start_xmit = start_xmit;
dev->features = NETIF_F_HIGHDMA;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = virtnet_netpoll;
+#endif
SET_NETDEV_DEV(dev, &vdev->dev);
/* Do we support "hardware" checksums? */
SET_NETDEV_DEV(dev, &vdev->dev);
/* Do we support "hardware" checksums? */