|
@@ -760,7 +760,7 @@ static int netvsc_set_channels(struct net_device *net,
|
|
|
if (count > net->num_tx_queues || count > net->num_rx_queues)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- if (net_device_ctx->start_remove || !nvdev || nvdev->destroy)
|
|
|
+ if (!nvdev || nvdev->destroy)
|
|
|
return -ENODEV;
|
|
|
|
|
|
if (nvdev->nvsp_version < NVSP_PROTOCOL_VERSION_5)
|
|
@@ -776,7 +776,6 @@ static int netvsc_set_channels(struct net_device *net,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- net_device_ctx->start_remove = true;
|
|
|
rndis_filter_device_remove(dev, nvdev);
|
|
|
|
|
|
ret = netvsc_set_queues(net, dev, count);
|
|
@@ -785,8 +784,6 @@ static int netvsc_set_channels(struct net_device *net,
|
|
|
else
|
|
|
netvsc_set_queues(net, dev, nvdev->num_chn);
|
|
|
|
|
|
- net_device_ctx->start_remove = false;
|
|
|
-
|
|
|
if (was_running)
|
|
|
ret = netvsc_open(net);
|
|
|
|
|
@@ -860,7 +857,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
|
|
|
bool was_running;
|
|
|
int ret;
|
|
|
|
|
|
- if (ndevctx->start_remove || !nvdev || nvdev->destroy)
|
|
|
+ if (!nvdev || nvdev->destroy)
|
|
|
return -ENODEV;
|
|
|
|
|
|
was_running = netif_running(ndev);
|
|
@@ -875,7 +872,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
|
|
|
device_info.num_chn = nvdev->num_chn;
|
|
|
device_info.max_num_vrss_chns = nvdev->num_chn;
|
|
|
|
|
|
- ndevctx->start_remove = true;
|
|
|
rndis_filter_device_remove(hdev, nvdev);
|
|
|
|
|
|
/* 'nvdev' has been freed in rndis_filter_device_remove() ->
|
|
@@ -888,8 +884,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
|
|
|
|
|
|
rndis_filter_device_add(hdev, &device_info);
|
|
|
|
|
|
- ndevctx->start_remove = false;
|
|
|
-
|
|
|
if (was_running)
|
|
|
ret = netvsc_open(ndev);
|
|
|
|
|
@@ -1245,10 +1239,10 @@ static void netvsc_link_change(struct work_struct *w)
|
|
|
unsigned long flags, next_reconfig, delay;
|
|
|
|
|
|
rtnl_lock();
|
|
|
- if (ndev_ctx->start_remove)
|
|
|
+ net_device = rtnl_dereference(ndev_ctx->nvdev);
|
|
|
+ if (!net_device)
|
|
|
goto out_unlock;
|
|
|
|
|
|
- net_device = rtnl_dereference(ndev_ctx->nvdev);
|
|
|
rdev = net_device->extension;
|
|
|
|
|
|
next_reconfig = ndev_ctx->last_reconfig + LINKCHANGE_INT;
|
|
@@ -1509,8 +1503,6 @@ static int netvsc_probe(struct hv_device *dev,
|
|
|
|
|
|
hv_set_drvdata(dev, net);
|
|
|
|
|
|
- net_device_ctx->start_remove = false;
|
|
|
-
|
|
|
INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
|
|
|
INIT_WORK(&net_device_ctx->work, do_set_multicast);
|
|
|
|
|
@@ -1579,26 +1571,20 @@ static int netvsc_remove(struct hv_device *dev)
|
|
|
|
|
|
ndev_ctx = netdev_priv(net);
|
|
|
|
|
|
- /* Avoid racing with netvsc_change_mtu()/netvsc_set_channels()
|
|
|
- * removing the device.
|
|
|
- */
|
|
|
- rtnl_lock();
|
|
|
- ndev_ctx->start_remove = true;
|
|
|
- rtnl_unlock();
|
|
|
+ netif_device_detach(net);
|
|
|
|
|
|
cancel_delayed_work_sync(&ndev_ctx->dwork);
|
|
|
cancel_work_sync(&ndev_ctx->work);
|
|
|
|
|
|
- /* Stop outbound asap */
|
|
|
- netif_tx_disable(net);
|
|
|
-
|
|
|
- unregister_netdev(net);
|
|
|
-
|
|
|
/*
|
|
|
* Call to the vsc driver to let it know that the device is being
|
|
|
- * removed
|
|
|
+ * removed. Also blocks mtu and channel changes.
|
|
|
*/
|
|
|
+ rtnl_lock();
|
|
|
rndis_filter_device_remove(dev, ndev_ctx->nvdev);
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
+ unregister_netdev(net);
|
|
|
|
|
|
hv_set_drvdata(dev, NULL);
|
|
|
|