2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

net: pse-pd: pd692x0: Fix power budget leak in manager setup error path

Fix a resource leak where manager power budgets were freed on both
success and error paths during manager setup. Power budgets should
only be freed on error paths after regulator registration or during
driver removal.

Refactor cleanup logic by extracting OF node cleanup and power budget
freeing into separate helper functions for better maintainability.

Fixes: 359754013e ("net: pse-pd: pd692x0: Add support for PSE PI priority feature")
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
Link: https://patch.msgid.link/20250820132708.837255-1-kory.maincent@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Kory Maincent 2025-08-20 15:27:07 +02:00 committed by Jakub Kicinski
parent 8c5d95988c
commit 1c67f9c54c

View File

@ -1162,12 +1162,44 @@ pd692x0_write_ports_matrix(struct pd692x0_priv *priv,
return 0; return 0;
} }
static void pd692x0_of_put_managers(struct pd692x0_priv *priv,
struct pd692x0_manager *manager,
int nmanagers)
{
int i, j;
for (i = 0; i < nmanagers; i++) {
for (j = 0; j < manager[i].nports; j++)
of_node_put(manager[i].port_node[j]);
of_node_put(manager[i].node);
}
}
static void pd692x0_managers_free_pw_budget(struct pd692x0_priv *priv)
{
int i;
for (i = 0; i < PD692X0_MAX_MANAGERS; i++) {
struct regulator *supply;
if (!priv->manager_reg[i] || !priv->manager_pw_budget[i])
continue;
supply = priv->manager_reg[i]->supply;
if (!supply)
continue;
regulator_free_power_budget(supply,
priv->manager_pw_budget[i]);
}
}
static int pd692x0_setup_pi_matrix(struct pse_controller_dev *pcdev) static int pd692x0_setup_pi_matrix(struct pse_controller_dev *pcdev)
{ {
struct pd692x0_manager *manager __free(kfree) = NULL; struct pd692x0_manager *manager __free(kfree) = NULL;
struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
struct pd692x0_matrix port_matrix[PD692X0_MAX_PIS]; struct pd692x0_matrix port_matrix[PD692X0_MAX_PIS];
int ret, i, j, nmanagers; int ret, nmanagers;
/* Should we flash the port matrix */ /* Should we flash the port matrix */
if (priv->fw_state != PD692X0_FW_OK && if (priv->fw_state != PD692X0_FW_OK &&
@ -1185,31 +1217,27 @@ static int pd692x0_setup_pi_matrix(struct pse_controller_dev *pcdev)
nmanagers = ret; nmanagers = ret;
ret = pd692x0_register_managers_regulator(priv, manager, nmanagers); ret = pd692x0_register_managers_regulator(priv, manager, nmanagers);
if (ret) if (ret)
goto out; goto err_of_managers;
ret = pd692x0_configure_managers(priv, nmanagers); ret = pd692x0_configure_managers(priv, nmanagers);
if (ret) if (ret)
goto out; goto err_of_managers;
ret = pd692x0_set_ports_matrix(priv, manager, nmanagers, port_matrix); ret = pd692x0_set_ports_matrix(priv, manager, nmanagers, port_matrix);
if (ret) if (ret)
goto out; goto err_managers_req_pw;
ret = pd692x0_write_ports_matrix(priv, port_matrix); ret = pd692x0_write_ports_matrix(priv, port_matrix);
if (ret) if (ret)
goto out; goto err_managers_req_pw;
out: pd692x0_of_put_managers(priv, manager, nmanagers);
for (i = 0; i < nmanagers; i++) { return 0;
struct regulator *supply = priv->manager_reg[i]->supply;
regulator_free_power_budget(supply, err_managers_req_pw:
priv->manager_pw_budget[i]); pd692x0_managers_free_pw_budget(priv);
err_of_managers:
for (j = 0; j < manager[i].nports; j++) pd692x0_of_put_managers(priv, manager, nmanagers);
of_node_put(manager[i].port_node[j]);
of_node_put(manager[i].node);
}
return ret; return ret;
} }
@ -1748,6 +1776,7 @@ static void pd692x0_i2c_remove(struct i2c_client *client)
{ {
struct pd692x0_priv *priv = i2c_get_clientdata(client); struct pd692x0_priv *priv = i2c_get_clientdata(client);
pd692x0_managers_free_pw_budget(priv);
firmware_upload_unregister(priv->fwl); firmware_upload_unregister(priv->fwl);
} }