Commit 59cd4f19 authored by Robert Hancock's avatar Robert Hancock Committed by David S. Miller

net: axienet: Fix probe error cleanup

The driver did not always clean up all allocated resources when probe
failed. Fix the probe cleanup path to clean up everything that was
allocated.

Fixes: 57baf8cc ("net: axienet: Handle deferred probe on clock properly")
Signed-off-by: default avatarRobert Hancock <robert.hancock@calian.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f211ac15
...@@ -1880,7 +1880,7 @@ static int axienet_probe(struct platform_device *pdev) ...@@ -1880,7 +1880,7 @@ static int axienet_probe(struct platform_device *pdev)
if (IS_ERR(lp->regs)) { if (IS_ERR(lp->regs)) {
dev_err(&pdev->dev, "could not map Axi Ethernet regs.\n"); dev_err(&pdev->dev, "could not map Axi Ethernet regs.\n");
ret = PTR_ERR(lp->regs); ret = PTR_ERR(lp->regs);
goto free_netdev; goto cleanup_clk;
} }
lp->regs_start = ethres->start; lp->regs_start = ethres->start;
...@@ -1958,18 +1958,18 @@ static int axienet_probe(struct platform_device *pdev) ...@@ -1958,18 +1958,18 @@ static int axienet_probe(struct platform_device *pdev)
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
goto free_netdev; goto cleanup_clk;
} }
} else { } else {
ret = of_get_phy_mode(pdev->dev.of_node, &lp->phy_mode); ret = of_get_phy_mode(pdev->dev.of_node, &lp->phy_mode);
if (ret) if (ret)
goto free_netdev; goto cleanup_clk;
} }
if (lp->switch_x_sgmii && lp->phy_mode != PHY_INTERFACE_MODE_SGMII && if (lp->switch_x_sgmii && lp->phy_mode != PHY_INTERFACE_MODE_SGMII &&
lp->phy_mode != PHY_INTERFACE_MODE_1000BASEX) { lp->phy_mode != PHY_INTERFACE_MODE_1000BASEX) {
dev_err(&pdev->dev, "xlnx,switch-x-sgmii only supported with SGMII or 1000BaseX\n"); dev_err(&pdev->dev, "xlnx,switch-x-sgmii only supported with SGMII or 1000BaseX\n");
ret = -EINVAL; ret = -EINVAL;
goto free_netdev; goto cleanup_clk;
} }
/* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
...@@ -1982,7 +1982,7 @@ static int axienet_probe(struct platform_device *pdev) ...@@ -1982,7 +1982,7 @@ static int axienet_probe(struct platform_device *pdev)
dev_err(&pdev->dev, dev_err(&pdev->dev,
"unable to get DMA resource\n"); "unable to get DMA resource\n");
of_node_put(np); of_node_put(np);
goto free_netdev; goto cleanup_clk;
} }
lp->dma_regs = devm_ioremap_resource(&pdev->dev, lp->dma_regs = devm_ioremap_resource(&pdev->dev,
&dmares); &dmares);
...@@ -2002,12 +2002,12 @@ static int axienet_probe(struct platform_device *pdev) ...@@ -2002,12 +2002,12 @@ static int axienet_probe(struct platform_device *pdev)
if (IS_ERR(lp->dma_regs)) { if (IS_ERR(lp->dma_regs)) {
dev_err(&pdev->dev, "could not map DMA regs\n"); dev_err(&pdev->dev, "could not map DMA regs\n");
ret = PTR_ERR(lp->dma_regs); ret = PTR_ERR(lp->dma_regs);
goto free_netdev; goto cleanup_clk;
} }
if ((lp->rx_irq <= 0) || (lp->tx_irq <= 0)) { if ((lp->rx_irq <= 0) || (lp->tx_irq <= 0)) {
dev_err(&pdev->dev, "could not determine irqs\n"); dev_err(&pdev->dev, "could not determine irqs\n");
ret = -ENOMEM; ret = -ENOMEM;
goto free_netdev; goto cleanup_clk;
} }
/* Autodetect the need for 64-bit DMA pointers. /* Autodetect the need for 64-bit DMA pointers.
...@@ -2037,7 +2037,7 @@ static int axienet_probe(struct platform_device *pdev) ...@@ -2037,7 +2037,7 @@ static int axienet_probe(struct platform_device *pdev)
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_width)); ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_width));
if (ret) { if (ret) {
dev_err(&pdev->dev, "No suitable DMA available\n"); dev_err(&pdev->dev, "No suitable DMA available\n");
goto free_netdev; goto cleanup_clk;
} }
/* Check for Ethernet core IRQ (optional) */ /* Check for Ethernet core IRQ (optional) */
...@@ -2068,12 +2068,12 @@ static int axienet_probe(struct platform_device *pdev) ...@@ -2068,12 +2068,12 @@ static int axienet_probe(struct platform_device *pdev)
if (!lp->phy_node) { if (!lp->phy_node) {
dev_err(&pdev->dev, "phy-handle required for 1000BaseX/SGMII\n"); dev_err(&pdev->dev, "phy-handle required for 1000BaseX/SGMII\n");
ret = -EINVAL; ret = -EINVAL;
goto free_netdev; goto cleanup_mdio;
} }
lp->pcs_phy = of_mdio_find_device(lp->phy_node); lp->pcs_phy = of_mdio_find_device(lp->phy_node);
if (!lp->pcs_phy) { if (!lp->pcs_phy) {
ret = -EPROBE_DEFER; ret = -EPROBE_DEFER;
goto free_netdev; goto cleanup_mdio;
} }
lp->phylink_config.pcs_poll = true; lp->phylink_config.pcs_poll = true;
} }
...@@ -2087,17 +2087,30 @@ static int axienet_probe(struct platform_device *pdev) ...@@ -2087,17 +2087,30 @@ static int axienet_probe(struct platform_device *pdev)
if (IS_ERR(lp->phylink)) { if (IS_ERR(lp->phylink)) {
ret = PTR_ERR(lp->phylink); ret = PTR_ERR(lp->phylink);
dev_err(&pdev->dev, "phylink_create error (%i)\n", ret); dev_err(&pdev->dev, "phylink_create error (%i)\n", ret);
goto free_netdev; goto cleanup_mdio;
} }
ret = register_netdev(lp->ndev); ret = register_netdev(lp->ndev);
if (ret) { if (ret) {
dev_err(lp->dev, "register_netdev() error (%i)\n", ret); dev_err(lp->dev, "register_netdev() error (%i)\n", ret);
goto free_netdev; goto cleanup_phylink;
} }
return 0; return 0;
cleanup_phylink:
phylink_destroy(lp->phylink);
cleanup_mdio:
if (lp->pcs_phy)
put_device(&lp->pcs_phy->dev);
if (lp->mii_bus)
axienet_mdio_teardown(lp);
of_node_put(lp->phy_node);
cleanup_clk:
clk_disable_unprepare(lp->clk);
free_netdev: free_netdev:
free_netdev(ndev); free_netdev(ndev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment