net: phylink: put link_gpio if phylink_create fails

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 ce0aa27ff3 ("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: ce0aa27ff3 ("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>
This commit is contained in:
Christian Marangi 2026-07-26 17:08:05 +02:00 committed by Jakub Kicinski
parent 0408e7f6f6
commit 0fe1e3e8f3

View 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);