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 { | |||
87 | /* IRQ name is queue name with "-tx" or "-rx" appended */ | 87 | /* IRQ name is queue name with "-tx" or "-rx" appended */ |
88 | #define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3) | 88 | #define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3) |
89 | 89 | ||
90 | static DECLARE_WAIT_QUEUE_HEAD(module_unload_q); | ||
91 | |||
90 | struct netfront_stats { | 92 | struct netfront_stats { |
91 | u64 packets; | 93 | u64 packets; |
92 | u64 bytes; | 94 | u64 bytes; |
@@ -1324,6 +1326,7 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev) | |||
1324 | 1326 | ||
1325 | netif_carrier_off(netdev); | 1327 | netif_carrier_off(netdev); |
1326 | 1328 | ||
1329 | xenbus_switch_state(dev, XenbusStateInitialising); | ||
1327 | return netdev; | 1330 | return netdev; |
1328 | 1331 | ||
1329 | exit: | 1332 | exit: |
@@ -2020,10 +2023,12 @@ static void netback_changed(struct xenbus_device *dev, | |||
2020 | break; | 2023 | break; |
2021 | 2024 | ||
2022 | case XenbusStateClosed: | 2025 | case XenbusStateClosed: |
2026 | wake_up_all(&module_unload_q); | ||
2023 | if (dev->state == XenbusStateClosed) | 2027 | if (dev->state == XenbusStateClosed) |
2024 | break; | 2028 | break; |
2025 | /* Missed the backend's CLOSING state -- fallthrough */ | 2029 | /* Missed the backend's CLOSING state -- fallthrough */ |
2026 | case XenbusStateClosing: | 2030 | case XenbusStateClosing: |
2031 | wake_up_all(&module_unload_q); | ||
2027 | xenbus_frontend_closed(dev); | 2032 | xenbus_frontend_closed(dev); |
2028 | break; | 2033 | break; |
2029 | } | 2034 | } |
@@ -2129,6 +2134,20 @@ static int xennet_remove(struct xenbus_device *dev) | |||
2129 | 2134 | ||
2130 | dev_dbg(&dev->dev, "%s\n", dev->nodename); | 2135 | dev_dbg(&dev->dev, "%s\n", dev->nodename); |
2131 | 2136 | ||
2137 | if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) { | ||
2138 | xenbus_switch_state(dev, XenbusStateClosing); | ||
2139 | wait_event(module_unload_q, | ||
2140 | xenbus_read_driver_state(dev->otherend) == | ||
2141 | XenbusStateClosing); | ||
2142 | |||
2143 | xenbus_switch_state(dev, XenbusStateClosed); | ||
2144 | wait_event(module_unload_q, | ||
2145 | xenbus_read_driver_state(dev->otherend) == | ||
2146 | XenbusStateClosed || | ||
2147 | xenbus_read_driver_state(dev->otherend) == | ||
2148 | XenbusStateUnknown); | ||
2149 | } | ||
2150 | |||
2132 | xennet_disconnect_backend(info); | 2151 | xennet_disconnect_backend(info); |
2133 | 2152 | ||
2134 | unregister_netdev(info->netdev); | 2153 | unregister_netdev(info->netdev); |