提交 6cca2003 编写于 作者: J Jon Mason 提交者: David S. Miller

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: NJon Mason <jon.mason@exar.com>
Signed-off-by: NSivakumar Subramani <sivakumar.subramani@exar.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 80f8f102
...@@ -3348,7 +3348,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, ...@@ -3348,7 +3348,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
vxge_debug_init(VXGE_ERR, vxge_debug_init(VXGE_ERR,
"%s: vpath memory allocation failed", "%s: vpath memory allocation failed",
vdev->ndev->name); vdev->ndev->name);
ret = -ENODEV; ret = -ENOMEM;
goto _out1; goto _out1;
} }
...@@ -3369,11 +3369,11 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, ...@@ -3369,11 +3369,11 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
if (vdev->config.gro_enable) if (vdev->config.gro_enable)
ndev->features |= NETIF_F_GRO; 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), vxge_debug_init(vxge_hw_device_trace_level_get(hldev),
"%s: %s : device registration failed!", "%s: %s : device registration failed!",
ndev->name, __func__); ndev->name, __func__);
ret = -ENODEV;
goto _out2; goto _out2;
} }
...@@ -3444,6 +3444,11 @@ static void vxge_device_unregister(struct __vxge_hw_device *hldev) ...@@ -3444,6 +3444,11 @@ static void vxge_device_unregister(struct __vxge_hw_device *hldev)
/* in 2.6 will call stop() if device is up */ /* in 2.6 will call stop() if device is up */
unregister_netdev(dev); 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", vxge_debug_init(vdev->level_trace, "%s: ethernet device unregistered",
buf); buf);
vxge_debug_entryexit(vdev->level_trace, "%s: %s:%d Exiting...", 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) ...@@ -4335,10 +4340,10 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
goto _exit1; 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, vxge_debug_init(VXGE_ERR,
"%s : request regions failed", __func__); "%s : request regions failed", __func__);
ret = -ENODEV;
goto _exit1; goto _exit1;
} }
...@@ -4643,8 +4648,9 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) ...@@ -4643,8 +4648,9 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
_exit5: _exit5:
vxge_device_unregister(hldev); vxge_device_unregister(hldev);
_exit4: _exit4:
pci_disable_sriov(pdev); pci_set_drvdata(pdev, NULL);
vxge_hw_device_terminate(hldev); vxge_hw_device_terminate(hldev);
pci_disable_sriov(pdev);
_exit3: _exit3:
iounmap(attr.bar0); iounmap(attr.bar0);
_exit2: _exit2:
...@@ -4655,7 +4661,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) ...@@ -4655,7 +4661,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
kfree(ll_config); kfree(ll_config);
kfree(device_config); kfree(device_config);
driver_config->config_dev_cnt--; driver_config->config_dev_cnt--;
pci_set_drvdata(pdev, NULL); driver_config->total_dev_cnt--;
return ret; return ret;
} }
...@@ -4668,45 +4674,34 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) ...@@ -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) static void __devexit vxge_remove(struct pci_dev *pdev)
{ {
struct __vxge_hw_device *hldev; struct __vxge_hw_device *hldev;
struct vxgedev *vdev = NULL; struct vxgedev *vdev;
struct net_device *dev; int i;
int i = 0;
hldev = pci_get_drvdata(pdev); hldev = pci_get_drvdata(pdev);
if (hldev == NULL) if (hldev == NULL)
return; return;
dev = hldev->ndev; vdev = netdev_priv(hldev->ndev);
vdev = netdev_priv(dev);
vxge_debug_entryexit(vdev->level_trace, "%s:%d", __func__, __LINE__); vxge_debug_entryexit(vdev->level_trace, "%s:%d", __func__, __LINE__);
vxge_debug_init(vdev->level_trace, "%s : removing PCI device...", vxge_debug_init(vdev->level_trace, "%s : removing PCI device...",
__func__); __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]); 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); iounmap(vdev->bar0);
pci_release_region(pdev, 0);
/* we are safe to free it now */ pci_disable_device(pdev);
free_netdev(dev); driver_config->config_dev_cnt--;
driver_config->total_dev_cnt--;
vxge_debug_init(vdev->level_trace, "%s:%d Device unregistered", vxge_debug_init(vdev->level_trace, "%s:%d Device unregistered",
__func__, __LINE__); __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__, vxge_debug_entryexit(vdev->level_trace, "%s:%d Exiting...", __func__,
__LINE__); __LINE__);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册