net: ethernet: ti: am65-cpsw: fix port_np reference counting
authorMichael Walle <mwalle@kernel.org>
Mon, 14 Apr 2025 08:39:42 +0000 (10:39 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 25 Apr 2025 08:47:44 +0000 (10:47 +0200)
[ Upstream commit 903d2b9f9efc5b3339d74015fcfc0d9fff276c4c ]

A reference to the device tree node is stored in a private struct, thus
the reference count has to be incremented. Also, decrement the count on
device removal and in the error path.

Fixes: 93a76530316a ("net: ethernet: ti: introduce am65x/j721e gigabit eth subsystem driver")
Signed-off-by: Michael Walle <mwalle@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250414083942.4015060-1-mwalle@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/ti/am65-cpsw-nuss.c

index 308a2b72a65de333a558ee051944aa0f89716819..a21e7c0afbfdc85e270dda9a6eecb0da01b64b70 100644 (file)
@@ -2680,7 +2680,7 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common)
                                of_property_read_bool(port_np, "ti,mac-only");
 
                /* get phy/link info */
-               port->slave.port_np = port_np;
+               port->slave.port_np = of_node_get(port_np);
                ret = of_get_phy_mode(port_np, &port->slave.phy_if);
                if (ret) {
                        dev_err(dev, "%pOF read phy-mode err %d\n",
@@ -2741,6 +2741,17 @@ static void am65_cpsw_nuss_phylink_cleanup(struct am65_cpsw_common *common)
        }
 }
 
+static void am65_cpsw_remove_dt(struct am65_cpsw_common *common)
+{
+       struct am65_cpsw_port *port;
+       int i;
+
+       for (i = 0; i < common->port_num; i++) {
+               port = &common->ports[i];
+               of_node_put(port->slave.port_np);
+       }
+}
+
 static int
 am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
 {
@@ -3647,6 +3658,7 @@ err_ndevs_clear:
        am65_cpsw_nuss_cleanup_ndev(common);
        am65_cpsw_nuss_phylink_cleanup(common);
        am65_cpts_release(common->cpts);
+       am65_cpsw_remove_dt(common);
 err_of_clear:
        if (common->mdio_dev)
                of_platform_device_destroy(common->mdio_dev, NULL);
@@ -3686,6 +3698,7 @@ static void am65_cpsw_nuss_remove(struct platform_device *pdev)
        am65_cpsw_nuss_phylink_cleanup(common);
        am65_cpts_release(common->cpts);
        am65_cpsw_disable_serdes_phy(common);
+       am65_cpsw_remove_dt(common);
 
        if (common->mdio_dev)
                of_platform_device_destroy(common->mdio_dev, NULL);