Skip to content

Commit

Permalink
vxge: cleanup probe error paths
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jon Mason authored and David S. Miller committed Jan 20, 2011
1 parent 80f8f10 commit 6cca200
Showing 1 changed file with 25 additions and 30 deletions.
55 changes: 25 additions & 30 deletions drivers/net/vxge/vxge-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -4643,8 +4648,9 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
_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:
Expand All @@ -4655,7 +4661,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
kfree(ll_config);
kfree(device_config);
driver_config->config_dev_cnt--;
pci_set_drvdata(pdev, NULL);
driver_config->total_dev_cnt--;
return ret;
}

Expand All @@ -4668,45 +4674,34 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
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__);
}
Expand Down

0 comments on commit 6cca200

Please sign in to comment.