* [PATCH net] net: pse-pd: don't enable a PI again while disabling it
@ 2026-10-18 18:20 Ross Cawston
2026-10-19 9:11 ` Kory Maincent
2026-10-19 18:42 ` netdev-bot+sashiko
0 siblings, 2 replies; 3+ messages in thread
From: Ross Cawston @ 2026-10-18 18:20 UTC (permalink / raw)
To: netdev
Cc: o.rempel, kory.maincent, 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. The PI being disabled is one
of them, as its admin state and PD detection are 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
- a PI disabled to free budget for a PI of higher priority is enabled
again with the budget it just freed, so priorities never take effect
Clear the admin state and the PD detection before disabling the PI,
and don't retry the power domain in pse_disable_pi_pol(), whose freed
budget is meant for the PI being allocated. That PI stays waiting for
power and is retried when budget is freed later.
The problem was found, and this fix written, with an AI coding
assistant, 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>
---
drivers/net/pse-pd/pse_core.c | 50 ++++++++++++++++++++++++++++-------
1 file changed, 41 insertions(+), 9 deletions(-)
diff --git a/drivers/net/pse-pd/pse_core.c b/drivers/net/pse-pd/pse_core.c
index a5e6d7b26b9..b46e3a13a31 100644
--- a/drivers/net/pse-pd/pse_core.c
+++ b/drivers/net/pse-pd/pse_core.c
@@ -448,14 +448,14 @@ static void pse_pi_deallocate_pw_budget(struct pse_pi *pi)
}
/**
- * _pse_pi_disable - Call disable operation. Assumes the PSE lock has been
- * acquired.
+ * __pse_pi_disable - Call disable operation and free the power budget of the
+ * PI. Assumes the PSE lock has been acquired.
* @pcdev: a pointer to the PSE
* @id: index of the PSE control
*
* Return: 0 on success and failure value on error
*/
-static int _pse_pi_disable(struct pse_controller_dev *pcdev, int id)
+static int __pse_pi_disable(struct pse_controller_dev *pcdev, int id)
{
const struct pse_controller_ops *ops = pcdev->ops;
int ret;
@@ -469,6 +469,29 @@ static int _pse_pi_disable(struct pse_controller_dev *pcdev, int id)
pse_pi_deallocate_pw_budget(&pcdev->pi[id]);
+ return 0;
+}
+
+/**
+ * _pse_pi_disable - Disable a PI, then retry the power delivery of the PIs
+ * waiting for power in its power domain. Assumes the PSE
+ * lock has been acquired.
+ * @pcdev: a pointer to the PSE
+ * @id: index of the PSE control
+ *
+ * The caller must have cleared the admin state or the PD detection of the
+ * PI first, or the retry enables the PI again.
+ *
+ * Return: 0 on success and failure value on error
+ */
+static int _pse_pi_disable(struct pse_controller_dev *pcdev, int id)
+{
+ int ret;
+
+ ret = __pse_pi_disable(pcdev, id);
+ if (ret)
+ return ret;
+
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);
@@ -490,7 +513,10 @@ static int pse_disable_pi_pol(struct pse_controller_dev *pcdev, int id)
dev_dbg(pcdev->dev, "Disabling PI %d to free power budget\n", id);
- ret = _pse_pi_disable(pcdev, id);
+ /* The power freed is for the PI being allocated, and this PI waits
+ * for power again: no retry of the power domain here.
+ */
+ ret = __pse_pi_disable(pcdev, id);
if (ret)
notifs |= ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR;
@@ -703,14 +729,18 @@ static int pse_pi_disable(struct regulator_dev *rdev)
{
struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
struct pse_pi *pi;
+ bool enabled;
int id, ret;
id = rdev_get_id(rdev);
pi = &pcdev->pi[id];
mutex_lock(&pcdev->lock);
+ /* Disabled before _pse_pi_disable() retries the power domain */
+ enabled = pi->admin_state_enabled;
+ pi->admin_state_enabled = 0;
ret = _pse_pi_disable(pcdev, id);
- if (!ret)
- pi->admin_state_enabled = 0;
+ if (ret)
+ pi->admin_state_enabled = enabled;
mutex_unlock(&pcdev->lock);
return 0;
@@ -1229,10 +1259,12 @@ 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)
- ret = _pse_pi_disable(pcdev, id);
+ bool pd_detected = pcdev->pi[id].isr_pd_detected;
+
+ /* Gone before _pse_pi_disable() retries the power domain */
pcdev->pi[id].isr_pd_detected = false;
+ if (pcdev->pi[id].admin_state_enabled && pd_detected)
+ ret = _pse_pi_disable(pcdev, id);
}
return ret;
--
2.55.0.windows.5
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net] net: pse-pd: don't enable a PI again while disabling it
2026-10-18 18:20 [PATCH net] net: pse-pd: don't enable a PI again while disabling it Ross Cawston
@ 2026-10-19 9:11 ` Kory Maincent
2026-10-19 18:42 ` netdev-bot+sashiko
1 sibling, 0 replies; 3+ messages in thread
From: Kory Maincent @ 2026-10-19 9:11 UTC (permalink / raw)
To: Ross Cawston, netdev
Cc: o.rempel, andrew+netdev, davem, edumazet, kuba, pabeni, linux-kernel
On 10/18/26 20:20, Ross Cawston wrote:
> 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. The PI being disabled is one
> of them, as its admin state and PD detection are 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
> - a PI disabled to free budget for a PI of higher priority is enabled
> again with the budget it just freed, so priorities never take effect
>
> Clear the admin state and the PD detection before disabling the PI,
> and don't retry the power domain in pse_disable_pi_pol(), whose freed
> budget is meant for the PI being allocated. That PI stays waiting for
> power and is retried when budget is freed later.
>
> The problem was found, and this fix written, with an AI coding
> assistant, 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>
> ---
> drivers/net/pse-pd/pse_core.c | 50 ++++++++++++++++++++++++++++-------
> 1 file changed, 41 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/pse-pd/pse_core.c b/drivers/net/pse-pd/pse_core.c
> index a5e6d7b26b9..b46e3a13a31 100644
> --- a/drivers/net/pse-pd/pse_core.c
> +++ b/drivers/net/pse-pd/pse_core.c
> @@ -448,14 +448,14 @@ static void pse_pi_deallocate_pw_budget(struct pse_pi *pi)
> }
>
> /**
> - * _pse_pi_disable - Call disable operation. Assumes the PSE lock has been
> - * acquired.
> + * __pse_pi_disable - Call disable operation and free the power budget of the
> + * PI. Assumes the PSE lock has been acquired.
> * @pcdev: a pointer to the PSE
> * @id: index of the PSE control
> *
> * Return: 0 on success and failure value on error
> */
> -static int _pse_pi_disable(struct pse_controller_dev *pcdev, int id)
> +static int __pse_pi_disable(struct pse_controller_dev *pcdev, int id)
> {
> const struct pse_controller_ops *ops = pcdev->ops;
> int ret;
> @@ -469,6 +469,29 @@ static int _pse_pi_disable(struct pse_controller_dev *pcdev, int id)
>
> pse_pi_deallocate_pw_budget(&pcdev->pi[id]);
>
> + return 0;
> +}
> +
> +/**
> + * _pse_pi_disable - Disable a PI, then retry the power delivery of the PIs
> + * waiting for power in its power domain. Assumes the PSE
> + * lock has been acquired.
> + * @pcdev: a pointer to the PSE
> + * @id: index of the PSE control
> + *
> + * The caller must have cleared the admin state or the PD detection of the
> + * PI first, or the retry enables the PI again.
> + *
> + * Return: 0 on success and failure value on error
> + */
> +static int _pse_pi_disable(struct pse_controller_dev *pcdev, int id)
> +{
> + int ret;
> +
> + ret = __pse_pi_disable(pcdev, id);
> + if (ret)
> + return ret;
> +
> 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);
Thanks for your fix.
I think, I would prefer to have these two lines moved out of
_pse_pi_disable() calls than to have another disable function.
Indeed this is not strictly related to the disable call.
This will also simplify your change below.
> @@ -490,7 +513,10 @@ static int pse_disable_pi_pol(struct pse_controller_dev *pcdev, int id)
>
> dev_dbg(pcdev->dev, "Disabling PI %d to free power budget\n", id);
>
> - ret = _pse_pi_disable(pcdev, id);
> + /* The power freed is for the PI being allocated, and this PI waits
> + * for power again: no retry of the power domain here.
> + */
> + ret = __pse_pi_disable(pcdev, id);
> if (ret)
> notifs |= ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR;
>
> @@ -703,14 +729,18 @@ static int pse_pi_disable(struct regulator_dev *rdev)
> {
> struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
> struct pse_pi *pi;
> + bool enabled;
> int id, ret;
>
> id = rdev_get_id(rdev);
> pi = &pcdev->pi[id];
> mutex_lock(&pcdev->lock);
> + /* Disabled before _pse_pi_disable() retries the power domain */
> + enabled = pi->admin_state_enabled;
> + pi->admin_state_enabled = 0;
> ret = _pse_pi_disable(pcdev, id);
> - if (!ret)
> - pi->admin_state_enabled = 0;
> + if (ret)
> + pi->admin_state_enabled = enabled;
>
> mutex_unlock(&pcdev->lock);
> return 0;
> @@ -1229,10 +1259,12 @@ 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)
> - ret = _pse_pi_disable(pcdev, id);
> + bool pd_detected = pcdev->pi[id].isr_pd_detected;
> +
> + /* Gone before _pse_pi_disable() retries the power domain */
> pcdev->pi[id].isr_pd_detected = false;
> + if (pcdev->pi[id].admin_state_enabled && pd_detected)
> + ret = _pse_pi_disable(pcdev, id);
> }
>
> return ret;
--
Köry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net] net: pse-pd: don't enable a PI again while disabling it
2026-10-18 18:20 [PATCH net] net: pse-pd: don't enable a PI again while disabling it Ross Cawston
2026-10-19 9:11 ` Kory Maincent
@ 2026-10-19 18:42 ` netdev-bot+sashiko
1 sibling, 0 replies; 3+ messages in thread
From: netdev-bot+sashiko @ 2026-10-19 18:42 UTC (permalink / raw)
To: ross
Cc: netdev, o.rempel, kory.maincent, andrew+netdev, davem, edumazet,
kuba, pabeni, linux-kernel
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider.
Critical: 0 · High: 1 · Medium: 0 (5) · Low: 0 (1)
If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).
- [High] The patch removes the power-domain retry from
pse_disable_pi_pol().
Pre-existing issues:
- [Medium] This problem wasn't introduced by this patch, but
pse_pi_disable() drops the error from _pse_pi_disable() and always…
- [Medium] This problem wasn't introduced by this patch, but in the
DISCONNECTION branch of pse_set_config_isr() isr_pd_detected is…
- [Medium] This problem wasn't introduced by this patch, but
pse_pi_is_admin_enable_pending() returns false only when…
- [Medium] This problem wasn't introduced by this patch, but
pse_set_config_isr() starts with 'if (notifs &…
- [Medium] This problem wasn't introduced by this patch, but
pse_ethtool_set_pw_limit() reads admin_state_enabled and…
- [Low] This problem wasn't introduced by this patch, but in
pse_pw_d_retry_power_delivery() the variable 'int prio_max =…
--
net: pse-pd: don't enable a PI again while disabling it
This patch splits _pse_pi_disable() in two. __pse_pi_disable() disables
the PI and frees its budget, and _pse_pi_disable() also retries power
delivery in the power domain. Admin state and PD detection are now cleared
before _pse_pi_disable() runs, and pse_disable_pi_pol() no longer retries
the power domain.
> diff --git a/drivers/net/pse-pd/pse_core.c b/drivers/net/pse-pd/pse_core.c
> index a5e6d7b26b9fd..b46e3a13a3108 100644
> --- a/drivers/net/pse-pd/pse_core.c
> +++ b/drivers/net/pse-pd/pse_core.c
[ ... ]
> +static int _pse_pi_disable(struct pse_controller_dev *pcdev, int id)
> +{
> + int ret;
> +
> + ret = __pse_pi_disable(pcdev, id);
> + if (ret)
> + return ret;
> +
> 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);
[Severity: Medium]
This is a pre-existing issue, but pse_pi_is_admin_enable_pending() only
treats a PI as not pending when pse_pi_is_hw_enabled() returns exactly 1:
ret = pse_pi_is_hw_enabled(pcdev, id);
/* PSE PI is already enabled at hardware level */
if (ret == 1)
return false;
return true;
If ops->pi_get_admin_state() fails, a negative error is treated as
pending. One example is a failed i2c_smbus_read_word_data() of
TPS23881_REG_PW_STATUS in tps23881_pi_get_admin_state().
Can the retry loop then call _pse_pi_delivery_power_sw_pw_ctrl() on a PI
that is already powered? That would request its budget a second time.
pse_pi_allocate_pw_budget_static_prio() then overwrites
pi->pw_allocated_mW, which leaks the earlier allocation.
[Severity: Low]
This isn't a bug introduced by this patch, but in
pse_pw_d_retry_power_delivery() prio_max is declared inside the loop body:
for (i = 0; i < pcdev->nr_lines; i++) {
int prio_max = pcdev->nr_lines;
...
if (pcdev->pi[i].prio > prio_max)
continue;
ret = _pse_pi_delivery_power_sw_pw_ctrl(pcdev, i, &extack);
if (ret == -ERANGE)
prio_max = pcdev->pi[i].prio;
}
The value saved after -ERANGE is lost on the next iteration. For the
static strategy, pse_ethtool_set_prio() rejects prio >= nr_lines, so can
the prio > prio_max check ever be true?
The comment "Do not try to enable PI with a lower prio (higher value)
than one which already can't be enabled" describes a cut-off that never
seems to happen. Should prio_max be declared outside the loop?
[ ... ]
> @@ -490,7 +513,10 @@ static int pse_disable_pi_pol(struct pse_controller_dev *pcdev, int id)
>
> dev_dbg(pcdev->dev, "Disabling PI %d to free power budget\n", id);
>
> - ret = _pse_pi_disable(pcdev, id);
> + /* The power freed is for the PI being allocated, and this PI waits
> + * for power again: no retry of the power domain here.
> + */
> + ret = __pse_pi_disable(pcdev, id);
[Severity: High]
With the retry removed here, what powers the evicted PI back on when the
allocation that evicted it doesn't use all of the freed budget?
The evicted PI is left with admin_state_enabled = 1 and
isr_pd_detected = true, but it is off in hardware with
pw_allocated_mW = 0. pse_pw_d_retry_power_delivery() is only called from
_pse_pi_disable() and pse_ethtool_set_prio(). Nothing retries the domain
after the outer allocation finishes.
There seem to be two ways to get there. First,
pse_pi_allocate_pw_budget_static_prio() can return -ERANGE after it has
already turned off lower-priority PIs:
while (regulator_request_power_budget(pi->pw_d->supply, pw_req) == -ERANGE) {
if (_prio <= pi->prio) {
...
return -ERANGE;
}
ret = pse_disable_pi_prio(pcdev, pi->pw_d, _prio);
...
_prio--;
}
For example, take a 60 W budget with H0 (prio 0) holding 30 W and L1
(prio 1) holding 30 W. A new prio 0 PD H2 asks for 40 W. L1 is turned off
and 30 W is freed, but the request still fails. L1 then stays off while
30 W is unused.
Second, pse_disable_pi_prio() turns off every hardware-enabled PI at a
priority level, not just as many as the request needs. With two prio 1
PIs at 30 W each and a 30 W prio 0 request, both prio 1 PIs go off. One
30 W share stays free, and neither PI is powered again.
The callers don't retry afterwards either. The CLASSIFICATION path of
pse_set_config_isr() and pse_pi_enable() both turn -ERANGE into success.
_pse_pi_delivery_power_sw_pw_ctrl() returns without a retry on both
success and failure.
Given this, is the new comment accurate? The commit message also says:
That PI stays waiting for power and is retried when budget is freed
later.
In these cases the budget may already be free. The evicted PIs only come
back after an unrelated event, such as an admin disable or unplug of
another PI in the domain, or pse_ethtool_set_prio().
TPS23881 may recover by chance, because tps23881_pi_disable() re-arms
detection and classification. The core doesn't require pi_disable to do
that, so other controllers might not recover. The RTL8239 driver named
in the commit message is one example.
Could the domain retry be deferred until the outer allocation finishes,
or could the evictions be undone when the allocation fails?
[ ... ]
> @@ -703,14 +729,18 @@ static int pse_pi_disable(struct regulator_dev *rdev)
> {
> struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
> struct pse_pi *pi;
> + bool enabled;
> int id, ret;
>
> id = rdev_get_id(rdev);
> pi = &pcdev->pi[id];
> mutex_lock(&pcdev->lock);
> + /* Disabled before _pse_pi_disable() retries the power domain */
> + enabled = pi->admin_state_enabled;
> + pi->admin_state_enabled = 0;
> ret = _pse_pi_disable(pcdev, id);
> - if (!ret)
> - pi->admin_state_enabled = 0;
> + if (ret)
> + pi->admin_state_enabled = enabled;
>
> mutex_unlock(&pcdev->lock);
> return 0;
[Severity: Medium]
This is a pre-existing issue, but pse_pi_disable() still returns 0 when
_pse_pi_disable() fails. admin_state_enabled is restored on error, yet
the regulator core sees success. _regulator_disable() then drops
rdev->use_count and the consumer's enable_count.
If ops->pi_disable() fails, can the PSE state and the regulator state
get out of sync? An I2C write error in tps23881_pi_disable() would do it.
A later admin enable in pse_ethtool_c33_set_config() does nothing,
because admin_state_enabled is still 1. A later admin disable goes
through:
case ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED:
if (psec->pcdev->pi[psec->id].admin_state_enabled)
err = regulator_disable(psec->ps);
and hits this in _regulator_disable():
if (WARN(regulator->enable_count == 0,
"unbalanced disables for %s\n", rdev_get_name(rdev)))
return -EIO;
Should pse_pi_disable() return ret here?
> @@ -1229,10 +1259,12 @@ static int pse_set_config_isr(struct pse_controller_dev *pcdev, int id,
> ret = 0;
> }
[Severity: Medium]
This isn't a bug introduced by this patch, but pse_set_config_isr()
starts with:
if (notifs & PSE_BUDGET_EVAL_STRAT_DYNAMIC)
return 0;
PSE_BUDGET_EVAL_STRAT_DYNAMIC is a budget strategy value (1 << 2), not
an event mask. It has the same value as ETHTOOL_C33_PSE_EVENT_DETECTION
(4). tps23881_set_notifs_helper() ORs events together, so detection and
classification can arrive in the same notification.
Does a DETECTION | CLASSIFICATION notification return early here? That
would skip setting isr_pd_detected and skip power delivery for that PD
in the classification branch.
> } else if (notifs & ETHTOOL_C33_PSE_EVENT_DISCONNECTION) {
> - if (pcdev->pi[id].admin_state_enabled &&
> - pcdev->pi[id].isr_pd_detected)
> - ret = _pse_pi_disable(pcdev, id);
> + bool pd_detected = pcdev->pi[id].isr_pd_detected;
> +
> + /* Gone before _pse_pi_disable() retries the power domain */
> pcdev->pi[id].isr_pd_detected = false;
> + if (pcdev->pi[id].admin_state_enabled && pd_detected)
> + ret = _pse_pi_disable(pcdev, id);
[Severity: Medium]
This is a pre-existing issue, but isr_pd_detected is cleared here
whatever _pse_pi_disable() returns. If ops->pi_disable() fails,
__pse_pi_disable() returns before it calls pse_pi_deallocate_pw_budget().
pi->pw_allocated_mW then stays non-zero while isr_pd_detected is false.
A later DISCONNECTION skips the disable. The next CLASSIFICATION goes
through
_pse_pi_delivery_power_sw_pw_ctrl()->pse_pi_allocate_pw_budget_static_prio(),
which does:
pi->pw_allocated_mW = pw_req;
without freeing the old allocation. Is that budget lost from the supply
for good?
Simply restoring isr_pd_detected on error would let the retry re-enable
the empty port. The fix may belong in how pw_allocated_mW is tracked
instead.
[Severity: Medium]
This is a pre-existing issue, but pse_ethtool_set_pw_limit() checks
admin_state_enabled and isr_pd_detected without holding pcdev->lock:
psec->pcdev->pi[psec->id].admin_state_enabled &&
psec->pcdev->pi[psec->id].isr_pd_detected) {
ret = pse_pi_update_pw_budget(psec->pcdev, psec->id,
pw_limit, extack);
pse_pi_update_pw_budget() takes the lock but doesn't check them again.
Can an ethtool power limit change race with this disconnection path?
CPU1
pse_ethtool_set_pw_limit()
sees admin_state_enabled && isr_pd_detected
CPU2
pse_isr()->pse_set_config_isr()
isr_pd_detected = false
_pse_pi_disable()
pw_allocated_mW = 0
CPU1
pse_pi_update_pw_budget()
pw_diff = pw_req - 0
regulator_request_power_budget() for the empty port
Later disconnections do nothing, because isr_pd_detected is already
false. The next classification overwrites pw_allocated_mW in
pse_pi_allocate_pw_budget_static_prio(). Would that requested budget
leak?
> }
>
> return ret;
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261018182005.1193-1-ross%40r-sc.ca
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-19 18:42 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-18 18:20 [PATCH net] net: pse-pd: don't enable a PI again while disabling it Ross Cawston
2026-10-19 9:11 ` Kory Maincent
2026-10-19 18:42 ` netdev-bot+sashiko
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®