]> www.infradead.org Git - users/hch/dma-mapping.git/commitdiff
net: pse-pd: Fix enabled status mismatch
authorKory Maincent <kory.maincent@bootlin.com>
Wed, 2 Oct 2024 12:17:05 +0000 (14:17 +0200)
committerJakub Kicinski <kuba@kernel.org>
Fri, 4 Oct 2024 20:14:18 +0000 (13:14 -0700)
PSE controllers like the TPS23881 can forcefully turn off their
configuration state. In such cases, the is_enabled() and get_status()
callbacks will report the PSE as disabled, while admin_state_enabled
will show it as enabled. This mismatch can lead the user to attempt
to enable it, but no action is taken as admin_state_enabled remains set.

The solution is to disable the PSE before enabling it, ensuring the
actual status matches admin_state_enabled.

Fixes: d83e13761d5b ("net: pse-pd: Use regulator framework within PSE framework")
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20241002121706.246143-1-kory.maincent@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/pse-pd/pse_core.c

index 4f032b16a8a0a6ce33911179e60764136c1b0cef..f8e6854781e6eee2a3058ec13bfb54785d11c04a 100644 (file)
@@ -785,6 +785,17 @@ static int pse_ethtool_c33_set_config(struct pse_control *psec,
         */
        switch (config->c33_admin_control) {
        case ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED:
+               /* We could have mismatch between admin_state_enabled and
+                * state reported by regulator_is_enabled. This can occur when
+                * the PI is forcibly turn off by the controller. Call
+                * regulator_disable on that case to fix the counters state.
+                */
+               if (psec->pcdev->pi[psec->id].admin_state_enabled &&
+                   !regulator_is_enabled(psec->ps)) {
+                       err = regulator_disable(psec->ps);
+                       if (err)
+                               break;
+               }
                if (!psec->pcdev->pi[psec->id].admin_state_enabled)
                        err = regulator_enable(psec->ps);
                break;