|  | @@ -175,6 +175,22 @@ static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
 | 
		
	
		
			
			| 175 | 175 |  	}
 | 
		
	
		
			
			| 176 | 176 |  }
 | 
		
	
		
			
			| 177 | 177 |  
 | 
		
	
		
			
			|  | 178 | +/** Helper to free all virtqueue memory
 | 
		
	
		
			
			|  | 179 | + *
 | 
		
	
		
			
			|  | 180 | + * @v netdev		Network device
 | 
		
	
		
			
			|  | 181 | + */
 | 
		
	
		
			
			|  | 182 | +static void virtnet_free_virtqueues ( struct net_device *netdev ) {
 | 
		
	
		
			
			|  | 183 | +	struct virtnet_nic *virtnet = netdev->priv;
 | 
		
	
		
			
			|  | 184 | +	int i;
 | 
		
	
		
			
			|  | 185 | +
 | 
		
	
		
			
			|  | 186 | +	for ( i = 0; i < QUEUE_NB; i++ ) {
 | 
		
	
		
			
			|  | 187 | +		virtio_pci_unmap_capability ( &virtnet->virtqueue[i].notification );
 | 
		
	
		
			
			|  | 188 | +	}
 | 
		
	
		
			
			|  | 189 | +
 | 
		
	
		
			
			|  | 190 | +	free ( virtnet->virtqueue );
 | 
		
	
		
			
			|  | 191 | +	virtnet->virtqueue = NULL;
 | 
		
	
		
			
			|  | 192 | +}
 | 
		
	
		
			
			|  | 193 | +
 | 
		
	
		
			
			| 178 | 194 |  /** Open network device, legacy virtio 0.9.5
 | 
		
	
		
			
			| 179 | 195 |   *
 | 
		
	
		
			
			| 180 | 196 |   * @v netdev	Network device
 | 
		
	
	
		
			
			|  | @@ -200,8 +216,7 @@ static int virtnet_open_legacy ( struct net_device *netdev ) {
 | 
		
	
		
			
			| 200 | 216 |  		if ( vp_find_vq ( ioaddr, i, &virtnet->virtqueue[i] ) == -1 ) {
 | 
		
	
		
			
			| 201 | 217 |  			DBGC ( virtnet, "VIRTIO-NET %p cannot register queue %d\n",
 | 
		
	
		
			
			| 202 | 218 |  			       virtnet, i );
 | 
		
	
		
			
			| 203 |  | -			free ( virtnet->virtqueue );
 | 
		
	
		
			
			| 204 |  | -			virtnet->virtqueue = NULL;
 | 
		
	
		
			
			|  | 219 | +			virtnet_free_virtqueues ( netdev );
 | 
		
	
		
			
			| 205 | 220 |  			return -ENOENT;
 | 
		
	
		
			
			| 206 | 221 |  		}
 | 
		
	
		
			
			| 207 | 222 |  	}
 | 
		
	
	
		
			
			|  | @@ -263,8 +278,7 @@ static int virtnet_open_modern ( struct net_device *netdev ) {
 | 
		
	
		
			
			| 263 | 278 |  	if ( vpm_find_vqs ( &virtnet->vdev, QUEUE_NB, virtnet->virtqueue ) ) {
 | 
		
	
		
			
			| 264 | 279 |  		DBGC ( virtnet, "VIRTIO-NET %p cannot register queues\n",
 | 
		
	
		
			
			| 265 | 280 |  		       virtnet );
 | 
		
	
		
			
			| 266 |  | -		free ( virtnet->virtqueue );
 | 
		
	
		
			
			| 267 |  | -		virtnet->virtqueue = NULL;
 | 
		
	
		
			
			|  | 281 | +		virtnet_free_virtqueues ( netdev );
 | 
		
	
		
			
			| 268 | 282 |  		vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED );
 | 
		
	
		
			
			| 269 | 283 |  		return -ENOENT;
 | 
		
	
		
			
			| 270 | 284 |  	}
 | 
		
	
	
		
			
			|  | @@ -304,7 +318,6 @@ static void virtnet_close ( struct net_device *netdev ) {
 | 
		
	
		
			
			| 304 | 318 |  	struct virtnet_nic *virtnet = netdev->priv;
 | 
		
	
		
			
			| 305 | 319 |  	struct io_buffer *iobuf;
 | 
		
	
		
			
			| 306 | 320 |  	struct io_buffer *next_iobuf;
 | 
		
	
		
			
			| 307 |  | -	int i;
 | 
		
	
		
			
			| 308 | 321 |  
 | 
		
	
		
			
			| 309 | 322 |  	if ( virtnet->virtio_version ) {
 | 
		
	
		
			
			| 310 | 323 |  		vpm_reset ( &virtnet->vdev );
 | 
		
	
	
		
			
			|  | @@ -313,12 +326,7 @@ static void virtnet_close ( struct net_device *netdev ) {
 | 
		
	
		
			
			| 313 | 326 |  	}
 | 
		
	
		
			
			| 314 | 327 |  
 | 
		
	
		
			
			| 315 | 328 |  	/* Virtqueues can be freed now that NIC is reset */
 | 
		
	
		
			
			| 316 |  | -	for ( i = 0 ; i < QUEUE_NB ; i++ ) {
 | 
		
	
		
			
			| 317 |  | -		virtio_pci_unmap_capability ( &virtnet->virtqueue[i].notification );
 | 
		
	
		
			
			| 318 |  | -	}
 | 
		
	
		
			
			| 319 |  | -
 | 
		
	
		
			
			| 320 |  | -	free ( virtnet->virtqueue );
 | 
		
	
		
			
			| 321 |  | -	virtnet->virtqueue = NULL;
 | 
		
	
		
			
			|  | 329 | +	virtnet_free_virtqueues ( netdev );
 | 
		
	
		
			
			| 322 | 330 |  
 | 
		
	
		
			
			| 323 | 331 |  	/* Free rx iobufs */
 | 
		
	
		
			
			| 324 | 332 |  	list_for_each_entry_safe ( iobuf, next_iobuf, &virtnet->rx_iobufs, list ) {
 |