diff options
author | Haiyang Zhang <haiyangz@microsoft.com> | 2013-12-20 19:52:31 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-12-21 22:23:06 -0500 |
commit | a68f9614614749727286f675d15f1e09d13cb54a (patch) | |
tree | 1236f0c9e306e2c527846addfb34f7690cc3163d | |
parent | 965cdea825693c821d200e38fac9402cde6dce6a (diff) |
hyperv: Fix race between probe and open calls
Moving the register_netdev to the end of probe to prevent
possible open call happens before NetVSP is connected.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 20 |
1 files changed, 8 insertions, 12 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index f8135725bcf6..71baeb3ed905 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c | |||
@@ -261,9 +261,7 @@ int netvsc_recv_callback(struct hv_device *device_obj, | |||
261 | struct sk_buff *skb; | 261 | struct sk_buff *skb; |
262 | 262 | ||
263 | net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev; | 263 | net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev; |
264 | if (!net) { | 264 | if (!net || net->reg_state != NETREG_REGISTERED) { |
265 | netdev_err(net, "got receive callback but net device" | ||
266 | " not initialized yet\n"); | ||
267 | packet->status = NVSP_STAT_FAIL; | 265 | packet->status = NVSP_STAT_FAIL; |
268 | return 0; | 266 | return 0; |
269 | } | 267 | } |
@@ -435,19 +433,11 @@ static int netvsc_probe(struct hv_device *dev, | |||
435 | SET_ETHTOOL_OPS(net, ðtool_ops); | 433 | SET_ETHTOOL_OPS(net, ðtool_ops); |
436 | SET_NETDEV_DEV(net, &dev->device); | 434 | SET_NETDEV_DEV(net, &dev->device); |
437 | 435 | ||
438 | ret = register_netdev(net); | ||
439 | if (ret != 0) { | ||
440 | pr_err("Unable to register netdev.\n"); | ||
441 | free_netdev(net); | ||
442 | goto out; | ||
443 | } | ||
444 | |||
445 | /* Notify the netvsc driver of the new device */ | 436 | /* Notify the netvsc driver of the new device */ |
446 | device_info.ring_size = ring_size; | 437 | device_info.ring_size = ring_size; |
447 | ret = rndis_filter_device_add(dev, &device_info); | 438 | ret = rndis_filter_device_add(dev, &device_info); |
448 | if (ret != 0) { | 439 | if (ret != 0) { |
449 | netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); | 440 | netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); |
450 | unregister_netdev(net); | ||
451 | free_netdev(net); | 441 | free_netdev(net); |
452 | hv_set_drvdata(dev, NULL); | 442 | hv_set_drvdata(dev, NULL); |
453 | return ret; | 443 | return ret; |
@@ -456,7 +446,13 @@ static int netvsc_probe(struct hv_device *dev, | |||
456 | 446 | ||
457 | netif_carrier_on(net); | 447 | netif_carrier_on(net); |
458 | 448 | ||
459 | out: | 449 | ret = register_netdev(net); |
450 | if (ret != 0) { | ||
451 | pr_err("Unable to register netdev.\n"); | ||
452 | rndis_filter_device_remove(dev); | ||
453 | free_netdev(net); | ||
454 | } | ||
455 | |||
460 | return ret; | 456 | return ret; |
461 | } | 457 | } |
462 | 458 | ||