Re: [PATCH net 10/10] net: pse-pd: reject a power limit whose current does not fit an int
From: Kory Maincent
Date: Mon Oct 19 2026 - 08:53:23 EST
On 10/18/26 10:23, Carlo Szelinsky wrote:
pse_ethtool_set_pw_limit() turns the power limit into a current as
mW * 10^9 / uV and stores it in an int. For the largest allowed limit,
99900 mW, that overflows below about 46.5 mV. Only 0 V is rejected, and
si3474 reports the measured voltage of each port. A negative result then
hits the BUG_ON() in regulator_check_current_limit().
pse_pi_get_current_limit() does the same conversion and can return a
wrapped value that looks like an error code.
Do the conversion in one helper that returns -ERANGE when the result
does not fit an int.
Same as patch 9. This is not a fix.
Can you send both to net-next instead.
You can add my R-by tag to it.
Fixes: 4a83abcef5f4 ("net: pse-pd: Add new power limit get and set c33 features")
Signed-off-by: Carlo Szelinsky <github@xxxxxxxxxxxx>
---
drivers/net/pse-pd/pse_core.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/net/pse-pd/pse_core.c b/drivers/net/pse-pd/pse_core.c
index 0d1e5d5039f8..3e333bef4e48 100644
--- a/drivers/net/pse-pd/pse_core.c
+++ b/drivers/net/pse-pd/pse_core.c
@@ -741,12 +741,19 @@ static int pse_pi_get_voltage(struct regulator_dev *rdev)
return ret;
}
+/* uA = mW * 1000000000 / uV, which does not fit an int for a low uV */
+static int pse_mw_to_ua(unsigned int mW, int uV)
+{
+ u64 uA = DIV_ROUND_CLOSEST_ULL((u64)mW * 1000000000ull, uV);
+
+ return uA > INT_MAX ? -ERANGE : uA;
+}
+
static int pse_pi_get_current_limit(struct regulator_dev *rdev)
{
struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
const struct pse_controller_ops *ops;
int id, uV, mW, ret;
- s64 tmp_64;
ops = pcdev->ops;
id = rdev_get_id(rdev);
@@ -769,10 +776,7 @@ static int pse_pi_get_current_limit(struct regulator_dev *rdev)
goto out;
uV = ret;
- tmp_64 = mW;
- tmp_64 *= 1000000000ull;
- /* uA = mW * 1000000000 / uV */
- ret = DIV_ROUND_CLOSEST_ULL(tmp_64, uV);
+ ret = pse_mw_to_ua(mW, uV);
out:
mutex_unlock(&pcdev->lock);
@@ -1910,7 +1914,6 @@ int pse_ethtool_set_pw_limit(struct pse_control *psec,
{
int uV, uA, ret, previous_pw_allocated = 0;
bool updated;
- s64 tmp_64;
if (pw_limit > MAX_PI_PW)
return -ERANGE;
@@ -1928,10 +1931,12 @@ int pse_ethtool_set_pw_limit(struct pse_control *psec,
}
uV = ret;
- tmp_64 = pw_limit;
- tmp_64 *= 1000000000ull;
- /* uA = mW * 1000000000 / uV */
- uA = DIV_ROUND_CLOSEST_ULL(tmp_64, uV);
+ uA = pse_mw_to_ua(pw_limit, uV);
+ if (uA < 0) {
+ NL_SET_ERR_MSG(extack,
+ "PSE voltage read is too low to set the limit");
+ return uA;
+ }
/* Update power budget only in software power control case and
* if a Power Device is powered.
--
Köry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com