|
@@ -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;
|
|
@@ -2021,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;
|
|
|
}
|
|
@@ -2130,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);
|