virtio: net: Move vq initialization into separate function
Subsystems (4)
PATCH 1/2 virtio: net: Move vq initialization into separate function
From: Amit Shah <[email protected]>
The probe and PM restore functions will share this code.
--- drivers/net/virtio_net.c | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-)
drivers/net/virtio_net.c +28 -19
@@ -966,15 +966,38 @@ static void virtnet_config_changed(struct virtio_device *vdev)virtnet_update_status (vi); } +static int init_vqs (struct virtnet_info *vi) +{ +struct virtqueue *vqs[3 ]; +vq_callback_t *callbacks[] = { skb_recv_done, skb_xmit_done,NULL }; +const char *names[] = {"input" ,"output" ,"control" }; +int nvqs, err; + +/* We expect two virtqueues, receive then send, +* and optionally control. */ + nvqs =virtio_has_feature (vi->vdev,VIRTIO_NET_F_CTRL_VQ ) ?3 :2 ; + + err = vi->vdev->config->find_vqs (vi->vdev, nvqs, vqs, callbacks, names); +if (err) +return err; + + vi->rvq = vqs[0 ]; + vi->svq = vqs[1 ]; + +if (virtio_has_feature (vi->vdev,VIRTIO_NET_F_CTRL_VQ )) { + vi->cvq = vqs[2 ]; + +if (virtio_has_feature (vi->vdev,VIRTIO_NET_F_CTRL_VLAN )) + vi->dev->features |=NETIF_F_HW_VLAN_FILTER ; + } +return 0 ; +} +static int virtnet_probe (struct virtio_device *vdev) {int err;struct net_device *dev;struct virtnet_info *vi; -struct virtqueue *vqs[3 ]; -vq_callback_t *callbacks[] = { skb_recv_done, skb_xmit_done,NULL }; -const char *names[] = {"input" ,"output" ,"control" }; -int nvqs;/* Allocate ourselves a network device with room for our info */ dev =alloc_etherdev (sizeof (struct virtnet_info ));
@@ -1046,24 +1069,10 @@ static int virtnet_probe(struct virtio_device *vdev)if (virtio_has_feature (vdev,VIRTIO_NET_F_MRG_RXBUF )) vi->mergeable_rx_bufs = true; -/* We expect two virtqueues, receive then send, -* and optionally control. */ - nvqs =virtio_has_feature (vi->vdev,VIRTIO_NET_F_CTRL_VQ ) ?3 :2 ; - - err = vdev->config->find_vqs (vdev, nvqs, vqs, callbacks, names); + err =init_vqs (vi);if (err) goto free_stats; - vi->rvq = vqs[0 ]; - vi->svq = vqs[1 ]; - -if (virtio_has_feature (vi->vdev,VIRTIO_NET_F_CTRL_VQ )) { - vi->cvq = vqs[2 ]; - -if (virtio_has_feature (vi->vdev,VIRTIO_NET_F_CTRL_VLAN )) - dev->features |=NETIF_F_HW_VLAN_FILTER ; - } - err =register_netdev (dev);if (err) {pr_debug ("virtio_net: registering device failed\n" );
PATCH 2/2 virtio: net: Move vq and vq buf removal into separate function
From: Amit Shah <[email protected]>
The remove and PM freeze functions will share this code.
--- drivers/net/virtio_net.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
drivers/net/virtio_net.c +12 -8
@@ -1134,22 +1134,26 @@ static void free_unused_bufs(struct virtnet_info *vi)BUG_ON (vi->num !=0 ); } -static void __devexit virtnet_remove(struct virtio_device *vdev) +static void remove_vq_common (struct virtnet_info *vi) { -struct virtnet_info *vi = vdev->priv; - -/* Stop all the virtqueues. */ - vdev->config->reset (vdev); - -unregister_netdev (vi->dev); + vi->vdev->config->reset (vi->vdev);/* Free unused buffers in both send and recv, if any. */ free_unused_bufs (vi); - vdev->config->del_vqs (vi->vdev); + vi->vdev->config->del_vqs (vi->vdev);while (vi->pages)__free_pages (get_a_page (vi,GFP_KERNEL ),0 ); +} + +static void __devexit virtnet_remove(struct virtio_device *vdev) +{ +struct virtnet_info *vi = vdev->priv; + +unregister_netdev (vi->dev); + +remove_vq_common (vi);free_percpu (vi->stats);free_netdev (vi->dev);
PATCH 1/1 (please ack, don't apply!) virtio: net: Add freeze, restore handlers to support S4
In reply to Rusty Russell(This needs PM changes to virtio_pci which are in my tree, so best done
via that rather than net-next. Thanks!)
From: Amit Shah <[email protected]>
Remove all the vqs, disable napi and detach from the netdev on hibernation.
Re-create vqs after restoring from a hibernated image, re-enable napi and re-attach the netdev. This keeps networking working across hibernation.
--- drivers/net/virtio_net.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
drivers/net/virtio_net.c +46 -0
@@ -1159,6 +1159,48 @@ static void __devexit virtnet_remove(strfree_netdev (vi->dev); } +#ifdef CONFIG_PM +static int virtnet_freeze (struct virtio_device *vdev) +{ +struct virtnet_info *vi = vdev->priv; + +virtqueue_disable_cb (vi->rvq); +virtqueue_disable_cb (vi->svq); +if (virtio_has_feature (vi->vdev,VIRTIO_NET_F_CTRL_VQ )) +virtqueue_disable_cb (vi->cvq); + +netif_device_detach (vi->dev); +cancel_delayed_work_sync (&vi->refill); + +if (netif_running (vi->dev)) +napi_disable (&vi->napi); + +remove_vq_common (vi); + +return 0 ; +} + +static int virtnet_restore (struct virtio_device *vdev) +{ +struct virtnet_info *vi = vdev->priv; +int err; + + err =init_vqs (vi); +if (err) +return err; + +if (netif_running (vi->dev)) +virtnet_napi_enable (vi); + +netif_device_attach (vi->dev); + +if (!try_fill_recv (vi,GFP_KERNEL )) +queue_delayed_work (system_nrt_wq, &vi->refill,0 ); + +return 0 ; +} +#endif +static struct virtio_device_id id_table[] = { {VIRTIO_ID_NET ,VIRTIO_DEV_ANY_ID }, {0 },
@@ -1183,6 +1225,10 @@ static struct virtio_driver virtio_net_d .probe = virtnet_probe, .remove = __devexit_p(virtnet_remove), .config_changed = virtnet_config_changed, +#ifdef CONFIG_PM + .freeze = virtnet_freeze, + .restore = virtnet_restore, +#endif };static int __init init (void )