[ipxe-devel] [PATCH 3/4] [virtio] Simplify virtqueue shutdown

Ladi Prosek lprosek at redhat.com
Fri Dec 16 14:30:04 UTC 2016


This commit introduces virtnet_free_virtqueues called on all virtqueue
error and shutdown paths. vpm_find_vqs no longer cleans up after itself
and instead expects virtnet_free_virtqueues to be always called to undo
its effect.

Signed-off-by: Ladi Prosek <lprosek at redhat.com>
---
 src/drivers/bus/virtio-pci.c |  9 +--------
 src/drivers/net/virtio-net.c | 30 +++++++++++++++++++-----------
 2 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/src/drivers/bus/virtio-pci.c b/src/drivers/bus/virtio-pci.c
index 89c4512..30c13b9 100644
--- a/src/drivers/bus/virtio-pci.c
+++ b/src/drivers/bus/virtio-pci.c
@@ -388,7 +388,7 @@ int vpm_find_vqs(struct virtio_pci_modern_device *vdev,
             off * notify_offset_multiplier, 2,
             &vq->notification);
         if (err) {
-            goto err_map_notify;
+            return err;
         }
     }
 
@@ -402,11 +402,4 @@ int vpm_find_vqs(struct virtio_pci_modern_device *vdev,
         vpm_iowrite16(vdev, &vdev->common, 1, COMMON_OFFSET(queue_enable));
     }
     return 0;
-
-err_map_notify:
-    /* Undo the virtio_pci_map_capability calls. */
-    while (i-- > 0) {
-        virtio_pci_unmap_capability(&vqs[i].notification);
-    }
-    return err;
 }
diff --git a/src/drivers/net/virtio-net.c b/src/drivers/net/virtio-net.c
index fe0fd4b..de3333d 100644
--- a/src/drivers/net/virtio-net.c
+++ b/src/drivers/net/virtio-net.c
@@ -175,6 +175,22 @@ static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
 	}
 }
 
+/** Helper to free all virtqueue memory
+ *
+ * @v netdev		Network device
+ */
+static void virtnet_free_virtqueues ( struct net_device *netdev ) {
+	struct virtnet_nic *virtnet = netdev->priv;
+	int i;
+
+	for ( i = 0; i < QUEUE_NB; i++ ) {
+		virtio_pci_unmap_capability ( &virtnet->virtqueue[i].notification );
+	}
+
+	free ( virtnet->virtqueue );
+	virtnet->virtqueue = NULL;
+}
+
 /** Open network device, legacy virtio 0.9.5
  *
  * @v netdev	Network device
@@ -200,8 +216,7 @@ static int virtnet_open_legacy ( struct net_device *netdev ) {
 		if ( vp_find_vq ( ioaddr, i, &virtnet->virtqueue[i] ) == -1 ) {
 			DBGC ( virtnet, "VIRTIO-NET %p cannot register queue %d\n",
 			       virtnet, i );
-			free ( virtnet->virtqueue );
-			virtnet->virtqueue = NULL;
+			virtnet_free_virtqueues ( netdev );
 			return -ENOENT;
 		}
 	}
@@ -263,8 +278,7 @@ static int virtnet_open_modern ( struct net_device *netdev ) {
 	if ( vpm_find_vqs ( &virtnet->vdev, QUEUE_NB, virtnet->virtqueue ) ) {
 		DBGC ( virtnet, "VIRTIO-NET %p cannot register queues\n",
 		       virtnet );
-		free ( virtnet->virtqueue );
-		virtnet->virtqueue = NULL;
+		virtnet_free_virtqueues ( netdev );
 		vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED );
 		return -ENOENT;
 	}
@@ -304,7 +318,6 @@ static void virtnet_close ( struct net_device *netdev ) {
 	struct virtnet_nic *virtnet = netdev->priv;
 	struct io_buffer *iobuf;
 	struct io_buffer *next_iobuf;
-	int i;
 
 	if ( virtnet->virtio_version ) {
 		vpm_reset ( &virtnet->vdev );
@@ -313,12 +326,7 @@ static void virtnet_close ( struct net_device *netdev ) {
 	}
 
 	/* Virtqueues can be freed now that NIC is reset */
-	for ( i = 0 ; i < QUEUE_NB ; i++ ) {
-		virtio_pci_unmap_capability ( &virtnet->virtqueue[i].notification );
-	}
-
-	free ( virtnet->virtqueue );
-	virtnet->virtqueue = NULL;
+	virtnet_free_virtqueues ( netdev );
 
 	/* Free rx iobufs */
 	list_for_each_entry_safe ( iobuf, next_iobuf, &virtnet->rx_iobufs, list ) {
-- 
2.7.4




More information about the ipxe-devel mailing list