diff options
Diffstat (limited to 'drivers/net/xen-netfront.c')
| -rw-r--r-- | drivers/net/xen-netfront.c | 18 | 
1 files changed, 18 insertions, 0 deletions
| diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 18c85e55e76a..c5a34671abda 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; @@ -2020,10 +2022,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 +2133,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); | 
