]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: phylink: put link_gpio if phylink_create fails
authorChristian Marangi <ansuelsmth@gmail.com>
Sun, 26 Jul 2026 15:08:05 +0000 (17:08 +0200)
committerJakub Kicinski <kuba@kernel.org>
Wed, 29 Jul 2026 01:31:11 +0000 (18:31 -0700)
In phylink_create() if phylink_register_sfp() returns an error, link_gpio
obtained by phylink_parse_fixedlink() is never released. While this is a
very unlikely scenario, it's worth to fix/handle this.

This was present from the very first implementation of phylink but got
relevant only with the introduction of ce0aa27ff3f6 ("sfp: add sfp-bus to
bridge between network devices and sfp cages") where additional function
were added after phylink_parse_fixedlink() making the release of link_gpio
needed if such additional function errored out.

While at it, restructure the exit condition of phylink_create() with the
goto pattern to reduce code duplication on handling error conditions.

Fixes: ce0aa27ff3f6 ("sfp: add sfp-bus to bridge between network devices and sfp cages")
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20260726150806.2437-1-ansuelsmth@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/phy/phylink.c

index 087ac63f9193d790d20bf5739965669a7adf654c..18d2ead97aa547587406db9358a34bc1f8f8802f 100644 (file)
@@ -1875,8 +1875,8 @@ struct phylink *phylink_create(struct phylink_config *config,
        } else if (config->type == PHYLINK_DEV) {
                pl->dev = config->dev;
        } else {
-               kfree(pl);
-               return ERR_PTR(-EINVAL);
+               ret = -EINVAL;
+               goto free_pl;
        }
 
        pl->mac_supports_eee_ops = phylink_mac_implements_lpi(mac_ops);
@@ -1909,28 +1909,29 @@ struct phylink *phylink_create(struct phylink_config *config,
        phylink_validate(pl, pl->supported, &pl->link_config);
 
        ret = phylink_parse_mode(pl, fwnode);
-       if (ret < 0) {
-               kfree(pl);
-               return ERR_PTR(ret);
-       }
+       if (ret < 0)
+               goto free_pl;
 
        if (pl->cfg_link_an_mode == MLO_AN_FIXED) {
                ret = phylink_parse_fixedlink(pl, fwnode);
-               if (ret < 0) {
-                       kfree(pl);
-                       return ERR_PTR(ret);
-               }
+               if (ret < 0)
+                       goto release_link_gpio;
        }
 
        pl->req_link_an_mode = pl->cfg_link_an_mode;
 
        ret = phylink_register_sfp(pl, fwnode);
-       if (ret < 0) {
-               kfree(pl);
-               return ERR_PTR(ret);
-       }
+       if (ret < 0)
+               goto release_link_gpio;
 
        return pl;
+
+release_link_gpio:
+       if (pl->link_gpio)
+               gpiod_put(pl->link_gpio);
+free_pl:
+       kfree(pl);
+       return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(phylink_create);