net: ethernet: ti: cpsw: Add of_node_put() before return and break
authorNishka Dasgupta <nishkadg.linux@gmail.com>
Tue, 16 Jul 2019 05:48:43 +0000 (11:18 +0530)
committerDavid S. Miller <davem@davemloft.net>
Tue, 16 Jul 2019 19:37:30 +0000 (12:37 -0700)
Each iteration of for_each_available_child_of_node puts the previous
node, but in the case of a return or break from the middle of the loop,
there is no put, thus causing a memory leak.
Hence, for function cpsw_probe_dt, create an extra label err_node_put
that puts the last used node and returns ret; modify the return
statements in the loop to save the return value in ret and goto this new
label.
For function cpsw_remove_dt, add an of_node_put before the break.
Issue found with Coccinelle.

Signed-off-by: Nishka Dasgupta <nishkadg.linux@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ti/cpsw.c

index f320f9a..32a8974 100644 (file)
@@ -2570,7 +2570,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                        ret = PTR_ERR(slave_data->ifphy);
                        dev_err(&pdev->dev,
                                "%d: Error retrieving port phy: %d\n", i, ret);
-                       return ret;
+                       goto err_node_put;
                }
 
                slave_data->slave_node = slave_node;
@@ -2589,7 +2589,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                        if (ret) {
                                if (ret != -EPROBE_DEFER)
                                        dev_err(&pdev->dev, "failed to register fixed-link phy: %d\n", ret);
-                               return ret;
+                               goto err_node_put;
                        }
                        slave_data->phy_node = of_node_get(slave_node);
                } else if (parp) {
@@ -2607,7 +2607,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                        of_node_put(mdio_node);
                        if (!mdio) {
                                dev_err(&pdev->dev, "Missing mdio platform device\n");
-                               return -EINVAL;
+                               ret = -EINVAL;
+                               goto err_node_put;
                        }
                        snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
                                 PHY_ID_FMT, mdio->name, phyid);
@@ -2622,7 +2623,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                if (slave_data->phy_if < 0) {
                        dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n",
                                i);
-                       return slave_data->phy_if;
+                       ret = slave_data->phy_if;
+                       goto err_node_put;
                }
 
 no_phy_slave:
@@ -2633,7 +2635,7 @@ no_phy_slave:
                        ret = ti_cm_get_macid(&pdev->dev, i,
                                              slave_data->mac_addr);
                        if (ret)
-                               return ret;
+                               goto err_node_put;
                }
                if (data->dual_emac) {
                        if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
@@ -2648,11 +2650,17 @@ no_phy_slave:
                }
 
                i++;
-               if (i == data->slaves)
-                       break;
+               if (i == data->slaves) {
+                       ret = 0;
+                       goto err_node_put;
+               }
        }
 
        return 0;
+
+err_node_put:
+       of_node_put(slave_node);
+       return ret;
 }
 
 static void cpsw_remove_dt(struct platform_device *pdev)
@@ -2675,8 +2683,10 @@ static void cpsw_remove_dt(struct platform_device *pdev)
                of_node_put(slave_data->phy_node);
 
                i++;
-               if (i == data->slaves)
+               if (i == data->slaves) {
+                       of_node_put(slave_node);
                        break;
+               }
        }
 
        of_platform_depopulate(&pdev->dev);