aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAlexey Khoroshilov <khoroshilov@ispras.ru>2015-04-24 21:07:03 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-26 16:05:49 -0400
commit0e03fd3e335d272bee88fe733d5fd13f5c5b7140 (patch)
tree5868379cbbf23f5d453a25d102455f1329ace3f7 /drivers/net
parent2ea2f62c8bda242433809c7f4e9eae1c52c40bbe (diff)
pxa168: fix double deallocation of managed resources
Commit 43d3ddf87a57 ("net: pxa168_eth: add device tree support") starts to use managed resources by adding devm_clk_get() and devm_ioremap_resource(), but it leaves explicit iounmap() and clock_put() in pxa168_eth_remove() and in failure handling code of pxa168_eth_probe(). As a result double free can happen. The patch removes explicit resource deallocation. Also it converts clk_disable() to clk_disable_unprepare() to make it symmetrical with clk_prepare_enable(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c16
1 files changed, 5 insertions, 11 deletions
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index af829c578400..7ace07dad6a3 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1508,7 +1508,8 @@ static int pxa168_eth_probe(struct platform_device *pdev)
1508 np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); 1508 np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
1509 if (!np) { 1509 if (!np) {
1510 dev_err(&pdev->dev, "missing phy-handle\n"); 1510 dev_err(&pdev->dev, "missing phy-handle\n");
1511 return -EINVAL; 1511 err = -EINVAL;
1512 goto err_netdev;
1512 } 1513 }
1513 of_property_read_u32(np, "reg", &pep->phy_addr); 1514 of_property_read_u32(np, "reg", &pep->phy_addr);
1514 pep->phy_intf = of_get_phy_mode(pdev->dev.of_node); 1515 pep->phy_intf = of_get_phy_mode(pdev->dev.of_node);
@@ -1526,7 +1527,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
1526 pep->smi_bus = mdiobus_alloc(); 1527 pep->smi_bus = mdiobus_alloc();
1527 if (pep->smi_bus == NULL) { 1528 if (pep->smi_bus == NULL) {
1528 err = -ENOMEM; 1529 err = -ENOMEM;
1529 goto err_base; 1530 goto err_netdev;
1530 } 1531 }
1531 pep->smi_bus->priv = pep; 1532 pep->smi_bus->priv = pep;
1532 pep->smi_bus->name = "pxa168_eth smi"; 1533 pep->smi_bus->name = "pxa168_eth smi";
@@ -1551,13 +1552,10 @@ err_mdiobus:
1551 mdiobus_unregister(pep->smi_bus); 1552 mdiobus_unregister(pep->smi_bus);
1552err_free_mdio: 1553err_free_mdio:
1553 mdiobus_free(pep->smi_bus); 1554 mdiobus_free(pep->smi_bus);
1554err_base:
1555 iounmap(pep->base);
1556err_netdev: 1555err_netdev:
1557 free_netdev(dev); 1556 free_netdev(dev);
1558err_clk: 1557err_clk:
1559 clk_disable(clk); 1558 clk_disable_unprepare(clk);
1560 clk_put(clk);
1561 return err; 1559 return err;
1562} 1560}
1563 1561
@@ -1574,13 +1572,9 @@ static int pxa168_eth_remove(struct platform_device *pdev)
1574 if (pep->phy) 1572 if (pep->phy)
1575 phy_disconnect(pep->phy); 1573 phy_disconnect(pep->phy);
1576 if (pep->clk) { 1574 if (pep->clk) {
1577 clk_disable(pep->clk); 1575 clk_disable_unprepare(pep->clk);
1578 clk_put(pep->clk);
1579 pep->clk = NULL;
1580 } 1576 }
1581 1577
1582 iounmap(pep->base);
1583 pep->base = NULL;
1584 mdiobus_unregister(pep->smi_bus); 1578 mdiobus_unregister(pep->smi_bus);
1585 mdiobus_free(pep->smi_bus); 1579 mdiobus_free(pep->smi_bus);
1586 unregister_netdev(dev); 1580 unregister_netdev(dev);