vxge: cleanup probe error paths
authorJon Mason <jon.mason@exar.com>
Tue, 18 Jan 2011 15:02:19 +0000 (15:02 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 20 Jan 2011 07:18:13 +0000 (23:18 -0800)
Reorder the commands to be in the inverse order of their allocations
(instead of the random order they appear to be in), propagate return
code on errors from pci_request_region and register_netdev, reduce the
config_dev_cnt and total_dev_cnt counters on remove, and return the
correct error code for vdev->vpaths kzalloc failures.  Also, prevent
leaking of vdev->vpaths memory and netdev in vxge_probe error path due
to freeing for these not occurring in vxge_device_unregister.

Signed-off-by: Jon Mason <jon.mason@exar.com>
Signed-off-by: Sivakumar Subramani <sivakumar.subramani@exar.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/vxge/vxge-main.c

index c81a651..ecf9a8e 100644 (file)
@@ -3348,7 +3348,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
                vxge_debug_init(VXGE_ERR,
                        "%s: vpath memory allocation failed",
                        vdev->ndev->name);
-               ret = -ENODEV;
+               ret = -ENOMEM;
                goto _out1;
        }
 
@@ -3369,11 +3369,11 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
        if (vdev->config.gro_enable)
                ndev->features |= NETIF_F_GRO;
 
-       if (register_netdev(ndev)) {
+       ret = register_netdev(ndev);
+       if (ret) {
                vxge_debug_init(vxge_hw_device_trace_level_get(hldev),
                        "%s: %s : device registration failed!",
                        ndev->name, __func__);
-               ret = -ENODEV;
                goto _out2;
        }
 
@@ -3444,6 +3444,11 @@ static void vxge_device_unregister(struct __vxge_hw_device *hldev)
        /* in 2.6 will call stop() if device is up */
        unregister_netdev(dev);
 
+       kfree(vdev->vpaths);
+
+       /* we are safe to free it now */
+       free_netdev(dev);
+
        vxge_debug_init(vdev->level_trace, "%s: ethernet device unregistered",
                        buf);
        vxge_debug_entryexit(vdev->level_trace, "%s: %s:%d  Exiting...", buf,
@@ -4335,10 +4340,10 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
                goto _exit1;
        }
 
-       if (pci_request_region(pdev, 0, VXGE_DRIVER_NAME)) {
+       ret = pci_request_region(pdev, 0, VXGE_DRIVER_NAME);
+       if (ret) {
                vxge_debug_init(VXGE_ERR,
                        "%s : request regions failed", __func__);
-               ret = -ENODEV;
                goto _exit1;
        }
 
@@ -4643,8 +4648,9 @@ _exit6:
 _exit5:
        vxge_device_unregister(hldev);
 _exit4:
-       pci_disable_sriov(pdev);
+       pci_set_drvdata(pdev, NULL);
        vxge_hw_device_terminate(hldev);
+       pci_disable_sriov(pdev);
 _exit3:
        iounmap(attr.bar0);
 _exit2:
@@ -4655,7 +4661,7 @@ _exit0:
        kfree(ll_config);
        kfree(device_config);
        driver_config->config_dev_cnt--;
-       pci_set_drvdata(pdev, NULL);
+       driver_config->total_dev_cnt--;
        return ret;
 }
 
@@ -4668,45 +4674,34 @@ _exit0:
 static void __devexit vxge_remove(struct pci_dev *pdev)
 {
        struct __vxge_hw_device *hldev;
-       struct vxgedev *vdev = NULL;
-       struct net_device *dev;
-       int i = 0;
+       struct vxgedev *vdev;
+       int i;
 
        hldev = pci_get_drvdata(pdev);
-
        if (hldev == NULL)
                return;
 
-       dev = hldev->ndev;
-       vdev = netdev_priv(dev);
+       vdev = netdev_priv(hldev->ndev);
 
        vxge_debug_entryexit(vdev->level_trace, "%s:%d", __func__, __LINE__);
-
        vxge_debug_init(vdev->level_trace, "%s : removing PCI device...",
                        __func__);
-       vxge_device_unregister(hldev);
 
-       for (i = 0; i < vdev->no_of_vpath; i++) {
+       for (i = 0; i < vdev->no_of_vpath; i++)
                vxge_free_mac_add_list(&vdev->vpaths[i]);
-               vdev->vpaths[i].mcast_addr_cnt = 0;
-               vdev->vpaths[i].mac_addr_cnt = 0;
-       }
-
-       kfree(vdev->vpaths);
 
+       vxge_device_unregister(hldev);
+       pci_set_drvdata(pdev, NULL);
+       /* Do not call pci_disable_sriov here, as it will break child devices */
+       vxge_hw_device_terminate(hldev);
        iounmap(vdev->bar0);
-
-       /* we are safe to free it now */
-       free_netdev(dev);
+       pci_release_region(pdev, 0);
+       pci_disable_device(pdev);
+       driver_config->config_dev_cnt--;
+       driver_config->total_dev_cnt--;
 
        vxge_debug_init(vdev->level_trace, "%s:%d Device unregistered",
                        __func__, __LINE__);
-
-       vxge_hw_device_terminate(hldev);
-
-       pci_disable_device(pdev);
-       pci_release_region(pdev, 0);
-       pci_set_drvdata(pdev, NULL);
        vxge_debug_entryexit(vdev->level_trace, "%s:%d  Exiting...", __func__,
                             __LINE__);
 }