net: axienet: Fix probe error cleanup
authorRobert Hancock <robert.hancock@calian.com>
Thu, 11 Mar 2021 20:05:18 +0000 (14:05 -0600)
committerDavid S. Miller <davem@davemloft.net>
Sat, 13 Mar 2021 00:51:32 +0000 (16:51 -0800)
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: 57baf8cc70ea ("net: axienet: Handle deferred probe on clock properly")
Signed-off-by: Robert Hancock <robert.hancock@calian.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/xilinx/xilinx_axienet_main.c

index 3a8775e..5d677db 100644 (file)
@@ -1880,7 +1880,7 @@ static int axienet_probe(struct platform_device *pdev)
        if (IS_ERR(lp->regs)) {
                dev_err(&pdev->dev, "could not map Axi Ethernet regs.\n");
                ret = PTR_ERR(lp->regs);
-               goto free_netdev;
+               goto cleanup_clk;
        }
        lp->regs_start = ethres->start;
 
@@ -1958,18 +1958,18 @@ static int axienet_probe(struct platform_device *pdev)
                        break;
                default:
                        ret = -EINVAL;
-                       goto free_netdev;
+                       goto cleanup_clk;
                }
        } else {
                ret = of_get_phy_mode(pdev->dev.of_node, &lp->phy_mode);
                if (ret)
-                       goto free_netdev;
+                       goto cleanup_clk;
        }
        if (lp->switch_x_sgmii && lp->phy_mode != PHY_INTERFACE_MODE_SGMII &&
            lp->phy_mode != PHY_INTERFACE_MODE_1000BASEX) {
                dev_err(&pdev->dev, "xlnx,switch-x-sgmii only supported with SGMII or 1000BaseX\n");
                ret = -EINVAL;
-               goto free_netdev;
+               goto cleanup_clk;
        }
 
        /* 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)
                        dev_err(&pdev->dev,
                                "unable to get DMA resource\n");
                        of_node_put(np);
-                       goto free_netdev;
+                       goto cleanup_clk;
                }
                lp->dma_regs = devm_ioremap_resource(&pdev->dev,
                                                     &dmares);
@@ -2002,12 +2002,12 @@ static int axienet_probe(struct platform_device *pdev)
        if (IS_ERR(lp->dma_regs)) {
                dev_err(&pdev->dev, "could not map DMA regs\n");
                ret = PTR_ERR(lp->dma_regs);
-               goto free_netdev;
+               goto cleanup_clk;
        }
        if ((lp->rx_irq <= 0) || (lp->tx_irq <= 0)) {
                dev_err(&pdev->dev, "could not determine irqs\n");
                ret = -ENOMEM;
-               goto free_netdev;
+               goto cleanup_clk;
        }
 
        /* Autodetect the need for 64-bit DMA pointers.
@@ -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));
        if (ret) {
                dev_err(&pdev->dev, "No suitable DMA available\n");
-               goto free_netdev;
+               goto cleanup_clk;
        }
 
        /* Check for Ethernet core IRQ (optional) */
@@ -2068,12 +2068,12 @@ static int axienet_probe(struct platform_device *pdev)
                if (!lp->phy_node) {
                        dev_err(&pdev->dev, "phy-handle required for 1000BaseX/SGMII\n");
                        ret = -EINVAL;
-                       goto free_netdev;
+                       goto cleanup_mdio;
                }
                lp->pcs_phy = of_mdio_find_device(lp->phy_node);
                if (!lp->pcs_phy) {
                        ret = -EPROBE_DEFER;
-                       goto free_netdev;
+                       goto cleanup_mdio;
                }
                lp->phylink_config.pcs_poll = true;
        }
@@ -2087,17 +2087,30 @@ static int axienet_probe(struct platform_device *pdev)
        if (IS_ERR(lp->phylink)) {
                ret = PTR_ERR(lp->phylink);
                dev_err(&pdev->dev, "phylink_create error (%i)\n", ret);
-               goto free_netdev;
+               goto cleanup_mdio;
        }
 
        ret = register_netdev(lp->ndev);
        if (ret) {
                dev_err(lp->dev, "register_netdev() error (%i)\n", ret);
-               goto free_netdev;
+               goto cleanup_phylink;
        }
 
        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(ndev);