]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
phy: lynx-28g: improve lynx_28g_probe() sequence
authorVladimir Oltean <vladimir.oltean@nxp.com>
Tue, 25 Nov 2025 11:48:47 +0000 (13:48 +0200)
committerVinod Koul <vkoul@kernel.org>
Tue, 23 Dec 2025 17:41:06 +0000 (23:11 +0530)
dev_set_drvdata() is called twice, it is sufficient to do it only once.

devm_of_phy_provider_register() can fail, and if it does, the
&priv->cdr_check work item is queued, but not cancelled, and the device
probing failed, so it will trigger use after free. This is a minor risk
though.

Resource initialization should be done a little earlier, in case we need
to dereference dev_get_drvdata() in lynx_28g_pll_read_configuration() or
in lynx_28g_lane_read_configuration().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20251125114847.804961-16-vladimir.oltean@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/phy/freescale/phy-fsl-lynx-28g.c

index 423223371dd09b4edd45b195fdf22a39f7614df3..2b0fd95ba62fd48e2e61a8c8dc9a7b49ae4a2132 100644 (file)
@@ -1163,7 +1163,11 @@ static int lynx_28g_probe(struct platform_device *pdev)
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
+
        priv->dev = dev;
+       dev_set_drvdata(dev, priv);
+       spin_lock_init(&priv->pcc_lock);
+       INIT_DELAYED_WORK(&priv->cdr_check, lynx_28g_cdr_lock_check);
 
        priv->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(priv->base))
@@ -1208,18 +1212,14 @@ static int lynx_28g_probe(struct platform_device *pdev)
                }
        }
 
-       dev_set_drvdata(dev, priv);
-
-       spin_lock_init(&priv->pcc_lock);
-       INIT_DELAYED_WORK(&priv->cdr_check, lynx_28g_cdr_lock_check);
+       provider = devm_of_phy_provider_register(dev, lynx_28g_xlate);
+       if (IS_ERR(provider))
+               return PTR_ERR(provider);
 
        queue_delayed_work(system_power_efficient_wq, &priv->cdr_check,
                           msecs_to_jiffies(1000));
 
-       dev_set_drvdata(dev, priv);
-       provider = devm_of_phy_provider_register(dev, lynx_28g_xlate);
-
-       return PTR_ERR_OR_ZERO(provider);
+       return 0;
 }
 
 static void lynx_28g_remove(struct platform_device *pdev)