aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/hyperv/netvsc_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/hyperv/netvsc_drv.c')
-rw-r--r--drivers/net/hyperv/netvsc_drv.c78
1 files changed, 46 insertions, 32 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 1121a1ec407c..3af6d8d15233 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1894,20 +1894,6 @@ out_unlock:
1894 rtnl_unlock(); 1894 rtnl_unlock();
1895} 1895}
1896 1896
1897static struct net_device *get_netvsc_bymac(const u8 *mac)
1898{
1899 struct net_device_context *ndev_ctx;
1900
1901 list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
1902 struct net_device *dev = hv_get_drvdata(ndev_ctx->device_ctx);
1903
1904 if (ether_addr_equal(mac, dev->perm_addr))
1905 return dev;
1906 }
1907
1908 return NULL;
1909}
1910
1911static struct net_device *get_netvsc_byref(struct net_device *vf_netdev) 1897static struct net_device *get_netvsc_byref(struct net_device *vf_netdev)
1912{ 1898{
1913 struct net_device_context *net_device_ctx; 1899 struct net_device_context *net_device_ctx;
@@ -2036,26 +2022,48 @@ static void netvsc_vf_setup(struct work_struct *w)
2036 rtnl_unlock(); 2022 rtnl_unlock();
2037} 2023}
2038 2024
2025/* Find netvsc by VMBus serial number.
2026 * The PCI hyperv controller records the serial number as the slot.
2027 */
2028static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev)
2029{
2030 struct device *parent = vf_netdev->dev.parent;
2031 struct net_device_context *ndev_ctx;
2032 struct pci_dev *pdev;
2033
2034 if (!parent || !dev_is_pci(parent))
2035 return NULL; /* not a PCI device */
2036
2037 pdev = to_pci_dev(parent);
2038 if (!pdev->slot) {
2039 netdev_notice(vf_netdev, "no PCI slot information\n");
2040 return NULL;
2041 }
2042
2043 list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
2044 if (!ndev_ctx->vf_alloc)
2045 continue;
2046
2047 if (ndev_ctx->vf_serial == pdev->slot->number)
2048 return hv_get_drvdata(ndev_ctx->device_ctx);
2049 }
2050
2051 netdev_notice(vf_netdev,
2052 "no netdev found for slot %u\n", pdev->slot->number);
2053 return NULL;
2054}
2055
2039static int netvsc_register_vf(struct net_device *vf_netdev) 2056static int netvsc_register_vf(struct net_device *vf_netdev)
2040{ 2057{
2041 struct net_device *ndev;
2042 struct net_device_context *net_device_ctx; 2058 struct net_device_context *net_device_ctx;
2043 struct device *pdev = vf_netdev->dev.parent;
2044 struct netvsc_device *netvsc_dev; 2059 struct netvsc_device *netvsc_dev;
2060 struct net_device *ndev;
2045 int ret; 2061 int ret;
2046 2062
2047 if (vf_netdev->addr_len != ETH_ALEN) 2063 if (vf_netdev->addr_len != ETH_ALEN)
2048 return NOTIFY_DONE; 2064 return NOTIFY_DONE;
2049 2065
2050 if (!pdev || !dev_is_pci(pdev) || dev_is_pf(pdev)) 2066 ndev = get_netvsc_byslot(vf_netdev);
2051 return NOTIFY_DONE;
2052
2053 /*
2054 * We will use the MAC address to locate the synthetic interface to
2055 * associate with the VF interface. If we don't find a matching
2056 * synthetic interface, move on.
2057 */
2058 ndev = get_netvsc_bymac(vf_netdev->perm_addr);
2059 if (!ndev) 2067 if (!ndev)
2060 return NOTIFY_DONE; 2068 return NOTIFY_DONE;
2061 2069
@@ -2206,6 +2214,16 @@ static int netvsc_probe(struct hv_device *dev,
2206 2214
2207 memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); 2215 memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
2208 2216
2217 /* We must get rtnl lock before scheduling nvdev->subchan_work,
2218 * otherwise netvsc_subchan_work() can get rtnl lock first and wait
2219 * all subchannels to show up, but that may not happen because
2220 * netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer()
2221 * -> ... -> device_add() -> ... -> __device_attach() can't get
2222 * the device lock, so all the subchannels can't be processed --
2223 * finally netvsc_subchan_work() hangs for ever.
2224 */
2225 rtnl_lock();
2226
2209 if (nvdev->num_chn > 1) 2227 if (nvdev->num_chn > 1)
2210 schedule_work(&nvdev->subchan_work); 2228 schedule_work(&nvdev->subchan_work);
2211 2229
@@ -2224,7 +2242,6 @@ static int netvsc_probe(struct hv_device *dev,
2224 else 2242 else
2225 net->max_mtu = ETH_DATA_LEN; 2243 net->max_mtu = ETH_DATA_LEN;
2226 2244
2227 rtnl_lock();
2228 ret = register_netdevice(net); 2245 ret = register_netdevice(net);
2229 if (ret != 0) { 2246 if (ret != 0) {
2230 pr_err("Unable to register netdev.\n"); 2247 pr_err("Unable to register netdev.\n");
@@ -2263,17 +2280,15 @@ static int netvsc_remove(struct hv_device *dev)
2263 2280
2264 cancel_delayed_work_sync(&ndev_ctx->dwork); 2281 cancel_delayed_work_sync(&ndev_ctx->dwork);
2265 2282
2266 rcu_read_lock(); 2283 rtnl_lock();
2267 nvdev = rcu_dereference(ndev_ctx->nvdev); 2284 nvdev = rtnl_dereference(ndev_ctx->nvdev);
2268 2285 if (nvdev)
2269 if (nvdev)
2270 cancel_work_sync(&nvdev->subchan_work); 2286 cancel_work_sync(&nvdev->subchan_work);
2271 2287
2272 /* 2288 /*
2273 * Call to the vsc driver to let it know that the device is being 2289 * Call to the vsc driver to let it know that the device is being
2274 * removed. Also blocks mtu and channel changes. 2290 * removed. Also blocks mtu and channel changes.
2275 */ 2291 */
2276 rtnl_lock();
2277 vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev); 2292 vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
2278 if (vf_netdev) 2293 if (vf_netdev)
2279 netvsc_unregister_vf(vf_netdev); 2294 netvsc_unregister_vf(vf_netdev);
@@ -2285,7 +2300,6 @@ static int netvsc_remove(struct hv_device *dev)
2285 list_del(&ndev_ctx->list); 2300 list_del(&ndev_ctx->list);
2286 2301
2287 rtnl_unlock(); 2302 rtnl_unlock();
2288 rcu_read_unlock();
2289 2303
2290 hv_set_drvdata(dev, NULL); 2304 hv_set_drvdata(dev, NULL);
2291 2305