staging: hv: re-order the code in netvsc_probe()
authorHaiyang Zhang <haiyangz@microsoft.com>
Thu, 1 Sep 2011 19:19:43 +0000 (12:19 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 6 Sep 2011 18:56:18 +0000 (11:56 -0700)
Re-order the code in netvsc_probe() to prevent a guest crash caused by
packets possibly received from NetVSP before call to register_netdev().

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/hv/netvsc_drv.c

index e6513be00c4d010d8d5623531f27c03d32cdda1d..b49a08f4ed5acb9882df436bdcd5be5b31fff2c8 100644 (file)
@@ -348,19 +348,6 @@ static int netvsc_probe(struct hv_device *dev)
        dev_set_drvdata(&dev->device, net);
        INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
 
-       /* Notify the netvsc driver of the new device */
-       device_info.ring_size = ring_size;
-       ret = rndis_filter_device_add(dev, &device_info);
-       if (ret != 0) {
-               free_netdev(net);
-               dev_set_drvdata(&dev->device, NULL);
-               return ret;
-       }
-
-       netif_carrier_on(net);
-
-       memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
-
        net->netdev_ops = &device_ops;
 
        /* TODO: Add GSO and Checksum offload */
@@ -372,11 +359,26 @@ static int netvsc_probe(struct hv_device *dev)
 
        ret = register_netdev(net);
        if (ret != 0) {
-               /* Remove the device and release the resource */
-               rndis_filter_device_remove(dev);
+               pr_err("Unable to register netdev.\n");
                free_netdev(net);
+               goto out;
        }
 
+       /* Notify the netvsc driver of the new device */
+       device_info.ring_size = ring_size;
+       ret = rndis_filter_device_add(dev, &device_info);
+       if (ret != 0) {
+               netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
+               unregister_netdev(net);
+               free_netdev(net);
+               dev_set_drvdata(&dev->device, NULL);
+               return ret;
+       }
+       memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
+
+       netif_carrier_on(net);
+
+out:
        return ret;
 }