diff options
Diffstat (limited to 'drivers/net/xen-netfront.c')
| -rw-r--r-- | drivers/net/xen-netfront.c | 19 | 
1 files changed, 19 insertions, 0 deletions
| diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 18c85e55e76a..9bd7ddeeb6a5 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -87,6 +87,8 @@ struct netfront_cb {  /* IRQ name is queue name with "-tx" or "-rx" appended */  #define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3) +static DECLARE_WAIT_QUEUE_HEAD(module_unload_q); +  struct netfront_stats {  	u64			packets;  	u64			bytes; @@ -1324,6 +1326,7 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)  	netif_carrier_off(netdev); +	xenbus_switch_state(dev, XenbusStateInitialising);  	return netdev;   exit: @@ -2020,10 +2023,12 @@ static void netback_changed(struct xenbus_device *dev,  		break;  	case XenbusStateClosed: +		wake_up_all(&module_unload_q);  		if (dev->state == XenbusStateClosed)  			break;  		/* Missed the backend's CLOSING state -- fallthrough */  	case XenbusStateClosing: +		wake_up_all(&module_unload_q);  		xenbus_frontend_closed(dev);  		break;  	} @@ -2129,6 +2134,20 @@ static int xennet_remove(struct xenbus_device *dev)  	dev_dbg(&dev->dev, "%s\n", dev->nodename); +	if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) { +		xenbus_switch_state(dev, XenbusStateClosing); +		wait_event(module_unload_q, +			   xenbus_read_driver_state(dev->otherend) == +			   XenbusStateClosing); + +		xenbus_switch_state(dev, XenbusStateClosed); +		wait_event(module_unload_q, +			   xenbus_read_driver_state(dev->otherend) == +			   XenbusStateClosed || +			   xenbus_read_driver_state(dev->otherend) == +			   XenbusStateUnknown); +	} +  	xennet_disconnect_backend(info);  	unregister_netdev(info->netdev); |