Home Home > GIT Browse > SLE15-SP1
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlaf Hering <ohering@suse.de>2018-11-06 11:07:40 +0100
committerOlaf Hering <ohering@suse.de>2018-11-06 11:07:40 +0100
commit3f347aac2148a910ca9a2ce808c298fff4992a79 (patch)
treeb4e910e98458d25994a6969ce84bf19da7b77118
parentaf779b7579d611b414cc73485d63c07fc8b9864f (diff)
hv_netvsc: Fix a deadlock by getting rtnl lock earlier inrpm-4.12.14-6.3--sle12-sp4-updatesrpm-4.12.14-6.3
netvsc_probe() (bsc#1109772). suse-commit: 39fd780f6c1d94c79ec64ba899880fcbdeb065ae
-rw-r--r--drivers/net/hyperv/netvsc_drv.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 694869259ff0..17121903b4ef 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -2076,6 +2076,16 @@ static int netvsc_probe(struct hv_device *dev,
memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
+ /* We must get rtnl lock before scheduling nvdev->subchan_work,
+ * otherwise netvsc_subchan_work() can get rtnl lock first and wait
+ * all subchannels to show up, but that may not happen because
+ * netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer()
+ * -> ... -> device_add() -> ... -> __device_attach() can't get
+ * the device lock, so all the subchannels can't be processed --
+ * finally netvsc_subchan_work() hangs for ever.
+ */
+ rtnl_lock();
+
if (nvdev->num_chn > 1)
schedule_work(&nvdev->subchan_work);
@@ -2094,15 +2104,17 @@ static int netvsc_probe(struct hv_device *dev,
else
net->max_mtu = ETH_DATA_LEN;
- ret = register_netdev(net);
+ ret = register_netdevice(net);
if (ret != 0) {
pr_err("Unable to register netdev.\n");
goto register_failed;
}
- return ret;
+ rtnl_unlock();
+ return 0;
register_failed:
+ rtnl_unlock();
rndis_filter_device_remove(dev, nvdev);
rndis_failed:
free_percpu(net_device_ctx->vf_stats);