* [PATCH net v2] net: pse-pd: don't enable a PI again while disabling it
@ 2026-10-19 22:08 Ross Cawston
0 siblings, 0 replies; only message in thread
From: Ross Cawston @ 2026-10-19 22:08 UTC (permalink / raw)
To: netdev
Cc: kory.maincent, github, o.rempel, andrew+netdev, davem, edumazet,
kuba, pabeni, linux-kernel, Ross Cawston
With software power control, _pse_pi_disable() frees the power budget
of the PI and then retries the power delivery of the PIs waiting for
power in its power domain: those that are admin enabled, have a PD
detected, and are not enabled in hardware. On an admin disable or a
disconnection, the PI being disabled is one of them, as its admin state
or PD detection is only cleared after _pse_pi_disable() returns, so it
is enabled again right away:
- an admin disable of a port with a PD keeps the port powered, and the
next admin enable allocates its budget a second time
- a disconnection enables the now empty port again, with a new budget
allocation that is never freed: when the port reports the
disconnection again, its PD detection is already cleared
Move the retry out of _pse_pi_disable() into its callers:
pse_pi_disable() and the disconnection handling of pse_set_config_isr()
retry after they clear the admin state or the PD detection, and
pse_disable_pi_pol() retries as before.
The problem was found while testing the budget on a switch with two
Realtek RTL8239 PSE controllers, whose driver (not in mainline yet) uses
the static budget strategy like the TPS23881. Before this change,
"ethtool --set-pse <port> c33-pse-admin-control disable" left a port
with a PD powered, and the budget allocated in the power domain grew
with every disable and every unplug. With it, the port stays off, and
the allocated budget is back to 0 after a disable and after an unplug.
Tested on that switch with OpenWrt's 6.18 kernel; the change for
mainline is the same apart from context and is build-tested.
Fixes: ffef61d6d273 ("net: pse-pd: Add support for budget evaluation strategies")
Signed-off-by: Ross Cawston <ross@r-sc.ca>
---
Changes in v2:
- Move the retry of the power domain out of _pse_pi_disable() into its
callers, instead of splitting out a __pse_pi_disable() without it
(Kory)
- Keep the retry after pse_disable_pi_pol(): without it, PIs turned off
for a PI of higher priority stay off even when their budget wasn't
needed (Sashiko). That the retry powers such a PI again right away is
left for a separate patch.
v1: https://lore.kernel.org/netdev/20261018182005.1193-1-ross@r-sc.ca/
drivers/net/pse-pd/pse_core.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/drivers/net/pse-pd/pse_core.c b/drivers/net/pse-pd/pse_core.c
index a5e6d7b26b9..c71acfd5337 100644
--- a/drivers/net/pse-pd/pse_core.c
+++ b/drivers/net/pse-pd/pse_core.c
@@ -469,9 +469,6 @@ static int _pse_pi_disable(struct pse_controller_dev *pcdev, int id)
pse_pi_deallocate_pw_budget(&pcdev->pi[id]);
- if (pse_pw_d_is_sw_pw_control(pcdev, pcdev->pi[id].pw_d))
- pse_pw_d_retry_power_delivery(pcdev, pcdev->pi[id].pw_d);
-
return 0;
}
@@ -493,6 +490,8 @@ static int pse_disable_pi_pol(struct pse_controller_dev *pcdev, int id)
ret = _pse_pi_disable(pcdev, id);
if (ret)
notifs |= ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR;
+ else if (pse_pw_d_is_sw_pw_control(pcdev, pcdev->pi[id].pw_d))
+ pse_pw_d_retry_power_delivery(pcdev, pcdev->pi[id].pw_d);
ntf.notifs = notifs;
ntf.id = id;
@@ -709,8 +708,11 @@ static int pse_pi_disable(struct regulator_dev *rdev)
pi = &pcdev->pi[id];
mutex_lock(&pcdev->lock);
ret = _pse_pi_disable(pcdev, id);
- if (!ret)
+ if (!ret) {
pi->admin_state_enabled = 0;
+ if (pse_pw_d_is_sw_pw_control(pcdev, pi->pw_d))
+ pse_pw_d_retry_power_delivery(pcdev, pi->pw_d);
+ }
mutex_unlock(&pcdev->lock);
return 0;
@@ -1229,10 +1231,16 @@ static int pse_set_config_isr(struct pse_controller_dev *pcdev, int id,
ret = 0;
}
} else if (notifs & ETHTOOL_C33_PSE_EVENT_DISCONNECTION) {
- if (pcdev->pi[id].admin_state_enabled &&
- pcdev->pi[id].isr_pd_detected)
+ struct pse_pi *pi = &pcdev->pi[id];
+ bool disable = pi->admin_state_enabled && pi->isr_pd_detected;
+
+ /* Cleared first, so that the retry doesn't enable it again */
+ pi->isr_pd_detected = false;
+ if (disable) {
ret = _pse_pi_disable(pcdev, id);
- pcdev->pi[id].isr_pd_detected = false;
+ if (!ret)
+ pse_pw_d_retry_power_delivery(pcdev, pi->pw_d);
+ }
}
return ret;
--
2.55.0.windows.5
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-19 22:10 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-19 22:08 [PATCH net v2] net: pse-pd: don't enable a PI again while disabling it Ross Cawston
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®