diff options
author | Jon Mason <jon.mason@exar.com> | 2011-01-18 10:02:19 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-20 02:18:13 -0500 |
commit | 6cca200362b46a6845b3f07367f5068a427161e1 (patch) | |
tree | 7f61585e158691935618afa591219ae343d27b8c /drivers/net/vxge/vxge-main.c | |
parent | 80f8f1027b99660897bdeaeae73002185d829906 (diff) |
vxge: cleanup probe error paths
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>
Diffstat (limited to 'drivers/net/vxge/vxge-main.c')
-rw-r--r-- | drivers/net/vxge/vxge-main.c | 55 |
1 files changed, 25 insertions, 30 deletions
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index c81a6512c683..ecf9a8ee6838 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c | |||
@@ -3348,7 +3348,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, | |||
3348 | vxge_debug_init(VXGE_ERR, | 3348 | vxge_debug_init(VXGE_ERR, |
3349 | "%s: vpath memory allocation failed", | 3349 | "%s: vpath memory allocation failed", |
3350 | vdev->ndev->name); | 3350 | vdev->ndev->name); |
3351 | ret = -ENODEV; | 3351 | ret = -ENOMEM; |
3352 | goto _out1; | 3352 | goto _out1; |
3353 | } | 3353 | } |
3354 | 3354 | ||
@@ -3369,11 +3369,11 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, | |||
3369 | if (vdev->config.gro_enable) | 3369 | if (vdev->config.gro_enable) |
3370 | ndev->features |= NETIF_F_GRO; | 3370 | ndev->features |= NETIF_F_GRO; |
3371 | 3371 | ||
3372 | if (register_netdev(ndev)) { | 3372 | ret = register_netdev(ndev); |
3373 | if (ret) { | ||
3373 | vxge_debug_init(vxge_hw_device_trace_level_get(hldev), | 3374 | vxge_debug_init(vxge_hw_device_trace_level_get(hldev), |
3374 | "%s: %s : device registration failed!", | 3375 | "%s: %s : device registration failed!", |
3375 | ndev->name, __func__); | 3376 | ndev->name, __func__); |
3376 | ret = -ENODEV; | ||
3377 | goto _out2; | 3377 | goto _out2; |
3378 | } | 3378 | } |
3379 | 3379 | ||
@@ -3444,6 +3444,11 @@ static void vxge_device_unregister(struct __vxge_hw_device *hldev) | |||
3444 | /* in 2.6 will call stop() if device is up */ | 3444 | /* in 2.6 will call stop() if device is up */ |
3445 | unregister_netdev(dev); | 3445 | unregister_netdev(dev); |
3446 | 3446 | ||
3447 | kfree(vdev->vpaths); | ||
3448 | |||
3449 | /* we are safe to free it now */ | ||
3450 | free_netdev(dev); | ||
3451 | |||
3447 | vxge_debug_init(vdev->level_trace, "%s: ethernet device unregistered", | 3452 | vxge_debug_init(vdev->level_trace, "%s: ethernet device unregistered", |
3448 | buf); | 3453 | buf); |
3449 | vxge_debug_entryexit(vdev->level_trace, "%s: %s:%d Exiting...", buf, | 3454 | 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) | |||
4335 | goto _exit1; | 4340 | goto _exit1; |
4336 | } | 4341 | } |
4337 | 4342 | ||
4338 | if (pci_request_region(pdev, 0, VXGE_DRIVER_NAME)) { | 4343 | ret = pci_request_region(pdev, 0, VXGE_DRIVER_NAME); |
4344 | if (ret) { | ||
4339 | vxge_debug_init(VXGE_ERR, | 4345 | vxge_debug_init(VXGE_ERR, |
4340 | "%s : request regions failed", __func__); | 4346 | "%s : request regions failed", __func__); |
4341 | ret = -ENODEV; | ||
4342 | goto _exit1; | 4347 | goto _exit1; |
4343 | } | 4348 | } |
4344 | 4349 | ||
@@ -4643,8 +4648,9 @@ _exit6: | |||
4643 | _exit5: | 4648 | _exit5: |
4644 | vxge_device_unregister(hldev); | 4649 | vxge_device_unregister(hldev); |
4645 | _exit4: | 4650 | _exit4: |
4646 | pci_disable_sriov(pdev); | 4651 | pci_set_drvdata(pdev, NULL); |
4647 | vxge_hw_device_terminate(hldev); | 4652 | vxge_hw_device_terminate(hldev); |
4653 | pci_disable_sriov(pdev); | ||
4648 | _exit3: | 4654 | _exit3: |
4649 | iounmap(attr.bar0); | 4655 | iounmap(attr.bar0); |
4650 | _exit2: | 4656 | _exit2: |
@@ -4655,7 +4661,7 @@ _exit0: | |||
4655 | kfree(ll_config); | 4661 | kfree(ll_config); |
4656 | kfree(device_config); | 4662 | kfree(device_config); |
4657 | driver_config->config_dev_cnt--; | 4663 | driver_config->config_dev_cnt--; |
4658 | pci_set_drvdata(pdev, NULL); | 4664 | driver_config->total_dev_cnt--; |
4659 | return ret; | 4665 | return ret; |
4660 | } | 4666 | } |
4661 | 4667 | ||
@@ -4668,45 +4674,34 @@ _exit0: | |||
4668 | static void __devexit vxge_remove(struct pci_dev *pdev) | 4674 | static void __devexit vxge_remove(struct pci_dev *pdev) |
4669 | { | 4675 | { |
4670 | struct __vxge_hw_device *hldev; | 4676 | struct __vxge_hw_device *hldev; |
4671 | struct vxgedev *vdev = NULL; | 4677 | struct vxgedev *vdev; |
4672 | struct net_device *dev; | 4678 | int i; |
4673 | int i = 0; | ||
4674 | 4679 | ||
4675 | hldev = pci_get_drvdata(pdev); | 4680 | hldev = pci_get_drvdata(pdev); |
4676 | |||
4677 | if (hldev == NULL) | 4681 | if (hldev == NULL) |
4678 | return; | 4682 | return; |
4679 | 4683 | ||
4680 | dev = hldev->ndev; | 4684 | vdev = netdev_priv(hldev->ndev); |
4681 | vdev = netdev_priv(dev); | ||
4682 | 4685 | ||
4683 | vxge_debug_entryexit(vdev->level_trace, "%s:%d", __func__, __LINE__); | 4686 | vxge_debug_entryexit(vdev->level_trace, "%s:%d", __func__, __LINE__); |
4684 | |||
4685 | vxge_debug_init(vdev->level_trace, "%s : removing PCI device...", | 4687 | vxge_debug_init(vdev->level_trace, "%s : removing PCI device...", |
4686 | __func__); | 4688 | __func__); |
4687 | vxge_device_unregister(hldev); | ||
4688 | 4689 | ||
4689 | for (i = 0; i < vdev->no_of_vpath; i++) { | 4690 | for (i = 0; i < vdev->no_of_vpath; i++) |
4690 | vxge_free_mac_add_list(&vdev->vpaths[i]); | 4691 | vxge_free_mac_add_list(&vdev->vpaths[i]); |
4691 | vdev->vpaths[i].mcast_addr_cnt = 0; | ||
4692 | vdev->vpaths[i].mac_addr_cnt = 0; | ||
4693 | } | ||
4694 | |||
4695 | kfree(vdev->vpaths); | ||
4696 | 4692 | ||
4693 | vxge_device_unregister(hldev); | ||
4694 | pci_set_drvdata(pdev, NULL); | ||
4695 | /* Do not call pci_disable_sriov here, as it will break child devices */ | ||
4696 | vxge_hw_device_terminate(hldev); | ||
4697 | iounmap(vdev->bar0); | 4697 | iounmap(vdev->bar0); |
4698 | 4698 | pci_release_region(pdev, 0); | |
4699 | /* we are safe to free it now */ | 4699 | pci_disable_device(pdev); |
4700 | free_netdev(dev); | 4700 | driver_config->config_dev_cnt--; |
4701 | driver_config->total_dev_cnt--; | ||
4701 | 4702 | ||
4702 | vxge_debug_init(vdev->level_trace, "%s:%d Device unregistered", | 4703 | vxge_debug_init(vdev->level_trace, "%s:%d Device unregistered", |
4703 | __func__, __LINE__); | 4704 | __func__, __LINE__); |
4704 | |||
4705 | vxge_hw_device_terminate(hldev); | ||
4706 | |||
4707 | pci_disable_device(pdev); | ||
4708 | pci_release_region(pdev, 0); | ||
4709 | pci_set_drvdata(pdev, NULL); | ||
4710 | vxge_debug_entryexit(vdev->level_trace, "%s:%d Exiting...", __func__, | 4705 | vxge_debug_entryexit(vdev->level_trace, "%s:%d Exiting...", __func__, |
4711 | __LINE__); | 4706 | __LINE__); |
4712 | } | 4707 | } |