drivers/net/ethernet/sunplus/spl2sw_driver.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
spl2sw_probe() acquires three of_node references that are never properly
released in all paths:
- eth_ports_np from of_get_child_by_name() leaks on every probe.
- port_np returned from spl2sw_get_eth_child_node() (which exits a
for_each_child_of_node() loop mid-iteration) leaks per loop pass.
- phy_np from of_parse_phandle() leaks on the -EPROBE_DEFER and
spl2sw_init_netdev() failure goto paths, and the registered netdev's
mac->phy_node is not released on the out_unregister_dev cleanup path.
Convert eth_ports_np and port_np to scoped __free(device_node), add
explicit of_node_put(phy_np) on the two early-error gotos where
ownership has not yet been transferred to mac->phy_node, and release
each registered ndev's mac->phy_node in the out_unregister_dev loop
before unregister_netdev().
The mac->phy_node release in the normal driver-remove path is handled
by the preceding fix to spl2sw_phy_remove().
Fixes: fd3040b9394c ("net: ethernet: Add driver for Sunplus SP7021")
Cc: stable@vger.kernel.org
Signed-off-by: Shitalkumar Gandhi <shitalkumar.gandhi@cambiumnetworks.com>
---
drivers/net/ethernet/sunplus/spl2sw_driver.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/sunplus/spl2sw_driver.c b/drivers/net/ethernet/sunplus/spl2sw_driver.c
index 5e0e4c9ecbb0..d78bda050ee4 100644
--- a/drivers/net/ethernet/sunplus/spl2sw_driver.c
+++ b/drivers/net/ethernet/sunplus/spl2sw_driver.c
@@ -319,10 +319,8 @@ static struct device_node *spl2sw_get_eth_child_node(struct device_node *ether_n
static int spl2sw_probe(struct platform_device *pdev)
{
- struct device_node *eth_ports_np;
- struct device_node *port_np;
+ struct device_node *eth_ports_np __free(device_node) = NULL;
struct spl2sw_common *comm;
- struct device_node *phy_np;
phy_interface_t phy_mode;
struct net_device *ndev;
struct spl2sw_mac *mac;
@@ -418,8 +416,10 @@ static int spl2sw_probe(struct platform_device *pdev)
}
for (i = 0; i < MAX_NETDEV_NUM; i++) {
- /* Get port@i of node ethernet-ports. */
- port_np = spl2sw_get_eth_child_node(eth_ports_np, i);
+ struct device_node *port_np __free(device_node) =
+ spl2sw_get_eth_child_node(eth_ports_np, i);
+ struct device_node *phy_np;
+
if (!port_np)
continue;
@@ -441,6 +441,7 @@ static int spl2sw_probe(struct platform_device *pdev)
/* Get mac-address from nvmem. */
ret = spl2sw_nvmem_get_mac_address(&pdev->dev, port_np, mac_addr);
if (ret == -EPROBE_DEFER) {
+ of_node_put(phy_np);
goto out_unregister_dev;
} else if (ret) {
dev_info(&pdev->dev, "Generate a random mac address!\n");
@@ -449,8 +450,10 @@ static int spl2sw_probe(struct platform_device *pdev)
/* Initialize the net device. */
ret = spl2sw_init_netdev(pdev, mac_addr, &ndev);
- if (ret)
+ if (ret) {
+ of_node_put(phy_np);
goto out_unregister_dev;
+ }
ndev->irq = irq;
comm->ndev[i] = ndev;
@@ -500,8 +503,11 @@ static int spl2sw_probe(struct platform_device *pdev)
out_unregister_dev:
for (i = 0; i < MAX_NETDEV_NUM; i++)
- if (comm->ndev[i])
+ if (comm->ndev[i]) {
+ mac = netdev_priv(comm->ndev[i]);
+ of_node_put(mac->phy_node);
unregister_netdev(comm->ndev[i]);
+ }
out_free_mdio:
spl2sw_mdio_remove(comm);
--
2.25.1
© 2016 - 2026 Red Hat, Inc.