diff options
author | Dan Carpenter <error27@gmail.com> | 2010-12-20 16:34:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-21 13:53:19 -0500 |
commit | 34a52f363ab6bcf6d50a65c153dec03f3fb32653 (patch) | |
tree | 62a84a17730b64c692ac788354cb1ae6913087b3 /drivers/net/stmmac/stmmac_main.c | |
parent | 4b97f8e10893e2c8f64a2795901bdb447a3308f4 (diff) |
stmmac: unwind properly in stmmac_dvr_probe()
The original code had a several problems:
*) It had potential null dereferences of "priv" and "res".
*) It released the memory region before it was aquired.
*) It didn't free "ndev" after it was allocated.
*) It didn't call unregister_netdev() after calling stmmac_probe().
Signed-off-by: Dan Carpenter <error27@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/stmmac/stmmac_main.c')
-rw-r--r-- | drivers/net/stmmac/stmmac_main.c | 50 |
1 files changed, 25 insertions, 25 deletions
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 20f803df868..34a0af3837f 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c | |||
@@ -1647,10 +1647,8 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
1647 | 1647 | ||
1648 | pr_info("STMMAC driver:\n\tplatform registration... "); | 1648 | pr_info("STMMAC driver:\n\tplatform registration... "); |
1649 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1649 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1650 | if (!res) { | 1650 | if (!res) |
1651 | ret = -ENODEV; | 1651 | return -ENODEV; |
1652 | goto out; | ||
1653 | } | ||
1654 | pr_info("\tdone!\n"); | 1652 | pr_info("\tdone!\n"); |
1655 | 1653 | ||
1656 | if (!request_mem_region(res->start, resource_size(res), | 1654 | if (!request_mem_region(res->start, resource_size(res), |
@@ -1658,22 +1656,21 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
1658 | pr_err("%s: ERROR: memory allocation failed" | 1656 | pr_err("%s: ERROR: memory allocation failed" |
1659 | "cannot get the I/O addr 0x%x\n", | 1657 | "cannot get the I/O addr 0x%x\n", |
1660 | __func__, (unsigned int)res->start); | 1658 | __func__, (unsigned int)res->start); |
1661 | ret = -EBUSY; | 1659 | return -EBUSY; |
1662 | goto out; | ||
1663 | } | 1660 | } |
1664 | 1661 | ||
1665 | addr = ioremap(res->start, resource_size(res)); | 1662 | addr = ioremap(res->start, resource_size(res)); |
1666 | if (!addr) { | 1663 | if (!addr) { |
1667 | pr_err("%s: ERROR: memory mapping failed\n", __func__); | 1664 | pr_err("%s: ERROR: memory mapping failed\n", __func__); |
1668 | ret = -ENOMEM; | 1665 | ret = -ENOMEM; |
1669 | goto out; | 1666 | goto out_release_region; |
1670 | } | 1667 | } |
1671 | 1668 | ||
1672 | ndev = alloc_etherdev(sizeof(struct stmmac_priv)); | 1669 | ndev = alloc_etherdev(sizeof(struct stmmac_priv)); |
1673 | if (!ndev) { | 1670 | if (!ndev) { |
1674 | pr_err("%s: ERROR: allocating the device\n", __func__); | 1671 | pr_err("%s: ERROR: allocating the device\n", __func__); |
1675 | ret = -ENOMEM; | 1672 | ret = -ENOMEM; |
1676 | goto out; | 1673 | goto out_unmap; |
1677 | } | 1674 | } |
1678 | 1675 | ||
1679 | SET_NETDEV_DEV(ndev, &pdev->dev); | 1676 | SET_NETDEV_DEV(ndev, &pdev->dev); |
@@ -1683,8 +1680,8 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
1683 | if (ndev->irq == -ENXIO) { | 1680 | if (ndev->irq == -ENXIO) { |
1684 | pr_err("%s: ERROR: MAC IRQ configuration " | 1681 | pr_err("%s: ERROR: MAC IRQ configuration " |
1685 | "information not found\n", __func__); | 1682 | "information not found\n", __func__); |
1686 | ret = -ENODEV; | 1683 | ret = -ENXIO; |
1687 | goto out; | 1684 | goto out_free_ndev; |
1688 | } | 1685 | } |
1689 | 1686 | ||
1690 | priv = netdev_priv(ndev); | 1687 | priv = netdev_priv(ndev); |
@@ -1711,18 +1708,18 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
1711 | if (priv->plat->init) { | 1708 | if (priv->plat->init) { |
1712 | ret = priv->plat->init(pdev); | 1709 | ret = priv->plat->init(pdev); |
1713 | if (unlikely(ret)) | 1710 | if (unlikely(ret)) |
1714 | goto out; | 1711 | goto out_free_ndev; |
1715 | } | 1712 | } |
1716 | 1713 | ||
1717 | /* MAC HW revice detection */ | 1714 | /* MAC HW revice detection */ |
1718 | ret = stmmac_mac_device_setup(ndev); | 1715 | ret = stmmac_mac_device_setup(ndev); |
1719 | if (ret < 0) | 1716 | if (ret < 0) |
1720 | goto out; | 1717 | goto out_plat_exit; |
1721 | 1718 | ||
1722 | /* Network Device Registration */ | 1719 | /* Network Device Registration */ |
1723 | ret = stmmac_probe(ndev); | 1720 | ret = stmmac_probe(ndev); |
1724 | if (ret < 0) | 1721 | if (ret < 0) |
1725 | goto out; | 1722 | goto out_plat_exit; |
1726 | 1723 | ||
1727 | /* associate a PHY - it is provided by another platform bus */ | 1724 | /* associate a PHY - it is provided by another platform bus */ |
1728 | if (!driver_for_each_device | 1725 | if (!driver_for_each_device |
@@ -1730,7 +1727,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
1730 | stmmac_associate_phy)) { | 1727 | stmmac_associate_phy)) { |
1731 | pr_err("No PHY device is associated with this MAC!\n"); | 1728 | pr_err("No PHY device is associated with this MAC!\n"); |
1732 | ret = -ENODEV; | 1729 | ret = -ENODEV; |
1733 | goto out; | 1730 | goto out_unregister; |
1734 | } | 1731 | } |
1735 | 1732 | ||
1736 | pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n" | 1733 | pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n" |
@@ -1741,19 +1738,22 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
1741 | pr_debug("\tMDIO bus (id: %d)...", priv->plat->bus_id); | 1738 | pr_debug("\tMDIO bus (id: %d)...", priv->plat->bus_id); |
1742 | ret = stmmac_mdio_register(ndev); | 1739 | ret = stmmac_mdio_register(ndev); |
1743 | if (ret < 0) | 1740 | if (ret < 0) |
1744 | goto out; | 1741 | goto out_unregister; |
1745 | pr_debug("registered!\n"); | 1742 | pr_debug("registered!\n"); |
1743 | return 0; | ||
1746 | 1744 | ||
1747 | out: | 1745 | out_unregister: |
1748 | if (ret < 0) { | 1746 | unregister_netdev(ndev); |
1749 | if (priv->plat->exit) | 1747 | out_plat_exit: |
1750 | priv->plat->exit(pdev); | 1748 | if (priv->plat->exit) |
1751 | 1749 | priv->plat->exit(pdev); | |
1752 | platform_set_drvdata(pdev, NULL); | 1750 | out_free_ndev: |
1753 | release_mem_region(res->start, resource_size(res)); | 1751 | free_netdev(ndev); |
1754 | if (addr != NULL) | 1752 | platform_set_drvdata(pdev, NULL); |
1755 | iounmap(addr); | 1753 | out_unmap: |
1756 | } | 1754 | iounmap(addr); |
1755 | out_release_region: | ||
1756 | release_mem_region(res->start, resource_size(res)); | ||
1757 | 1757 | ||
1758 | return ret; | 1758 | return ret; |
1759 | } | 1759 | } |