summaryrefslogtreecommitdiff |
diff options
author | Olaf Hering <ohering@suse.de> | 2018-11-06 11:07:40 +0100 |
---|---|---|
committer | Olaf Hering <ohering@suse.de> | 2018-11-06 11:07:40 +0100 |
commit | 3f347aac2148a910ca9a2ce808c298fff4992a79 (patch) | |
tree | b4e910e98458d25994a6969ce84bf19da7b77118 | |
parent | af779b7579d611b414cc73485d63c07fc8b9864f (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.c | 16 |
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); |