* [PATCH 0/8] pwm: Fix various bugs reported by Sashiko
@ 2026-11-05 14:38 Lee Jones
2026-11-05 14:38 ` [PATCH 1/8] pwm: tegra: Prevent 32-bit period truncation and division by zero Lee Jones
` (7 more replies)
0 siblings, 8 replies; 14+ messages in thread
From: Lee Jones @ 2026-11-05 14:38 UTC (permalink / raw)
To: lee
Cc: linux-kernel, Andrew Bresticker, Binbin Zhou, David Lechner,
Drew Fustini, Ezequiel Garcia, Fabio Estevam, Frank Li,
Grant Erickson, Huacai Chen, imx, Joachim Eastwood,
Jonathan Hunter, Juxin Gao, linux-arm-kernel, linux-pwm,
linux-tegra, Lokesh Vutla, Michael Hennerich, Mikko Perttunen,
Naidu Tellapati, Neil Armstrong, NeilBrown, Nuno Sá,
Pengutronix Kernel Team, Philip, Avinash, Rasmus Villemoes,
Sai Masarapu, Sandipan Patra, Sascha Hauer, Sergiu Cuciurean,
Shawn Guo, Shenwei Wang, Thierry Reding, Trevor Gamblin,
Uwe Kleine-König, Vaibhav Bedia, Vladimir Zapolskiy,
Xiubo Li
These issues were reported by Sashiko.
Lee Jones (8):
pwm: tegra: Prevent 32-bit period truncation and division by zero
pwm: mxs: Return early when disabling and fix error-path clock leak
pwm: loongson: Fix 32-bit control register truncation in
pwm_loongson_set_polarity()
pwm: axi-pwmgen: Enable clocks before accessing hardware registers in
probe()
pwm: fsl-ftm: Enable ipg_clk around regcache_sync() during resume
pwm: omap-dmtimer: Handle negative error codes from get_pwm_status()
pwm: tiehrpwm: Enable runtime PM before registering PWM chip
pwm: img: Unregister PWM chip before disabling runtime PM and clocks
drivers/pwm/pwm-axi-pwmgen.c | 20 ++++++++++----------
drivers/pwm/pwm-fsl-ftm.c | 7 +++++++
drivers/pwm/pwm-img.c | 8 ++++----
drivers/pwm/pwm-loongson.c | 2 +-
drivers/pwm/pwm-mxs.c | 32 ++++++++++++++++++--------------
drivers/pwm/pwm-omap-dmtimer.c | 8 ++++++--
drivers/pwm/pwm-tegra.c | 14 +++++++-------
drivers/pwm/pwm-tiehrpwm.c | 15 ++++++++-------
8 files changed, 61 insertions(+), 45 deletions(-)
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: Binbin Zhou <zhoubinbin@loongson.cn>
Cc: David Lechner <dlechner@baylibre.com>
Cc: Drew Fustini <dfustini@baylibre.com>
Cc: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: Frank Li <Frank.Li@nxp.com>
Cc: Grant Erickson <marathon96@gmail.com>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: imx@lists.linux.dev
Cc: Joachim Eastwood <manabian@gmail.com>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Juxin Gao <gaojuxin@loongson.cn>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-pwm@vger.kernel.org
Cc: linux-tegra@vger.kernel.org
Cc: Lokesh Vutla <lokeshvutla@ti.com>
Cc: Michael Hennerich <michael.hennerich@analog.com>
Cc: Mikko Perttunen <mperttunen@nvidia.com>
Cc: Naidu Tellapati <naidu.tellapati@gmail.com>
Cc: Neil Armstrong <neil.armstrong@linaro.org>
Cc: NeilBrown <neil@brown.name>
Cc: "Nuno Sá" <nuno.sa@analog.com>
Cc: Pengutronix Kernel Team <kernel@pengutronix.de>
Cc: "Philip, Avinash" <avinashphilip@ti.com>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Sai Masarapu <Sai.Masarapu@imgtec.com>
Cc: Sandipan Patra <spatra@nvidia.com>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Shenwei Wang <shenwei.wang@nxp.com>
Cc: Thierry Reding <thierry.reding@kernel.org>
Cc: Trevor Gamblin <tgamblin@baylibre.com>
Cc: "Uwe Kleine-König" <ukleinek@kernel.org>
Cc: Vaibhav Bedia <vaibhav.bedia@ti.com>
Cc: Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>
Cc: Xiubo Li <Li.Xiubo@freescale.com>
--
2.56.0.398.g882cbad275-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/8] pwm: tegra: Prevent 32-bit period truncation and division by zero
2026-11-05 14:38 [PATCH 0/8] pwm: Fix various bugs reported by Sashiko Lee Jones
@ 2026-11-05 14:38 ` Lee Jones
2026-11-05 15:46 ` Uwe Kleine-König
2026-11-05 14:38 ` [PATCH 2/8] pwm: mxs: Return early when disabling and fix error-path clock leak Lee Jones
` (6 subsequent siblings)
7 siblings, 1 reply; 14+ messages in thread
From: Lee Jones @ 2026-11-05 14:38 UTC (permalink / raw)
To: lee, Thierry Reding, Uwe Kleine-König, Jonathan Hunter,
Mikko Perttunen, Sascha Hauer, Sandipan Patra, linux-pwm,
linux-tegra, linux-kernel
Cc: stable
tegra_pwm_apply() passes the 64-bit state->duty_cycle and state->period
values into tegra_pwm_config(), which accepts signed 32-bit int
parameters and performs DIV_ROUND_CLOSEST_ULL(c, period_ns) before
validating period_ns against pc->min_period_ns. If a consumer requests
a period that is a non-zero multiple of 2^32 nanoseconds, period_ns
truncates to zero and triggers a divide-by-zero panic.
Widen duty_ns and period_ns to u64 and validate that period_ns lies
within [pc->min_period_ns, U32_MAX] prior to dividing by period_ns.
Fixes: 1d7796bdb63a ("pwm: tegra: Support dynamic clock frequency configuration")
Fixes: fd3ddd4355c0 ("pwm: tegra: Implement .apply() callback")
Closes: https://sashiko.dev/#/bug/linux-5c5b97d6-4da6-4d06-9dc7-957419dcd832
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/pwm/pwm-tegra.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index 5cdbe120ba2d..f99ae2b3a276 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -138,7 +138,7 @@ static inline void tegra_pwm_writel(struct pwm_device *pwm, unsigned int offset,
}
static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
- int duty_ns, int period_ns)
+ u64 duty_ns, u64 period_ns)
{
struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
unsigned long long c = duty_ns;
@@ -146,6 +146,12 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
u32 val = 0;
int err;
+ /*
+ * min period = max clock limit / TEGRA_PWM_DEPTH
+ */
+ if (period_ns < pc->min_period_ns || period_ns > U32_MAX)
+ return -EINVAL;
+
/*
* Convert from duty_ns / period_ns to a fixed number of duty ticks
* per TEGRA_PWM_DEPTH cycles and make sure to round to the
@@ -156,12 +162,6 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
val = (u32)c << TEGRA_PWM_DUTY_SHIFT;
- /*
- * min period = max clock limit / TEGRA_PWM_DEPTH
- */
- if (period_ns < pc->min_period_ns)
- return -EINVAL;
-
/*
* Compute the prescaler value for which TEGRA_PWM_DEPTH
* cycles at the PWM clock rate will take period_ns nanoseconds.
Cc: Sandipan Patra <spatra@nvidia.com>
Cc: "Uwe Kleine-König" <ukleinek@kernel.org>
--
2.56.0.398.g882cbad275-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/8] pwm: mxs: Return early when disabling and fix error-path clock leak
2026-11-05 14:38 [PATCH 0/8] pwm: Fix various bugs reported by Sashiko Lee Jones
2026-11-05 14:38 ` [PATCH 1/8] pwm: tegra: Prevent 32-bit period truncation and division by zero Lee Jones
@ 2026-11-05 14:38 ` Lee Jones
2026-11-05 16:50 ` Frank Li
2026-11-05 14:38 ` [PATCH 3/8] pwm: loongson: Fix 32-bit control register truncation in pwm_loongson_set_polarity() Lee Jones
` (5 subsequent siblings)
7 siblings, 1 reply; 14+ messages in thread
From: Lee Jones @ 2026-11-05 14:38 UTC (permalink / raw)
To: lee, Uwe Kleine-König, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shawn Guo,
Thierry Reding, Rasmus Villemoes, linux-pwm, imx,
linux-arm-kernel, linux-kernel
Cc: stable
When disabling a PWM channel (!state->enabled), the PWM core permits
state->period to be zero. mxs_pwm_apply() currently falls through into
the period and duty-cycle calculations even when !state->enabled,
causing do_div(c, state->period) to divide by zero when state->period is
zero. In addition, if the requested period exceeds the maximum divider
(div >= PERIOD_CDIV_MAX) while the PWM channel is currently disabled,
mxs_pwm_apply() returns -EINVAL without disabling and unpreparing
mxs->clk.
Handle the !state->enabled path upfront and return early, and balance
clk_prepare_enable() on the -EINVAL error path.
Fixes: bf29c2ff82fd ("pwm: mxs: Implement ->apply()")
Closes: https://sashiko.dev/#/bug/linux-710f863f-6964-4e4f-990a-e5043dbc1a87
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/pwm/pwm-mxs.c | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
index e1a3df6549fc..16233764fd3c 100644
--- a/drivers/pwm/pwm-mxs.c
+++ b/drivers/pwm/pwm-mxs.c
@@ -56,6 +56,14 @@ static int mxs_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
unsigned long long c;
unsigned int pol_bits;
+ if (!state->enabled) {
+ if (pwm_is_enabled(pwm)) {
+ writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + CLR);
+ clk_disable_unprepare(mxs->clk);
+ }
+ return 0;
+ }
+
/*
* If the PWM channel is disabled, make sure to turn on the
* clock before calling clk_get_rate() and writing to the
@@ -67,9 +75,6 @@ static int mxs_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}
- if (!state->enabled && pwm_is_enabled(pwm))
- writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + CLR);
-
rate = clk_get_rate(mxs->clk);
while (1) {
c = rate >> cdiv_shift[div];
@@ -78,8 +83,11 @@ static int mxs_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (c < PERIOD_PERIOD_MAX)
break;
div++;
- if (div >= PERIOD_CDIV_MAX)
+ if (div >= PERIOD_CDIV_MAX) {
+ if (!pwm_is_enabled(pwm))
+ clk_disable_unprepare(mxs->clk);
return -EINVAL;
+ }
}
period_cycles = c;
@@ -101,16 +109,12 @@ static int mxs_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
writel(PERIOD_PERIOD(period_cycles) | pol_bits | PERIOD_CDIV(div),
mxs->base + PWM_PERIOD0 + pwm->hwpwm * 0x20);
- if (state->enabled) {
- if (!pwm_is_enabled(pwm)) {
- /*
- * The clock was enabled above. Just enable
- * the channel in the control register.
- */
- writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + SET);
- }
- } else {
- clk_disable_unprepare(mxs->clk);
+ if (!pwm_is_enabled(pwm)) {
+ /*
+ * The clock was enabled above. Just enable
+ * the channel in the control register.
+ */
+ writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + SET);
}
return 0;
}
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
--
2.56.0.398.g882cbad275-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 3/8] pwm: loongson: Fix 32-bit control register truncation in pwm_loongson_set_polarity()
2026-11-05 14:38 [PATCH 0/8] pwm: Fix various bugs reported by Sashiko Lee Jones
2026-11-05 14:38 ` [PATCH 1/8] pwm: tegra: Prevent 32-bit period truncation and division by zero Lee Jones
2026-11-05 14:38 ` [PATCH 2/8] pwm: mxs: Return early when disabling and fix error-path clock leak Lee Jones
@ 2026-11-05 14:38 ` Lee Jones
2026-11-05 14:38 ` [PATCH 4/8] pwm: axi-pwmgen: Enable clocks before accessing hardware registers in probe() Lee Jones
` (4 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Lee Jones @ 2026-11-05 14:38 UTC (permalink / raw)
To: lee, Binbin Zhou, Uwe Kleine-König, Juxin Gao, Huacai Chen,
linux-pwm, linux-kernel
Cc: stable
pwm_loongson_set_polarity() stores the 32-bit value read from
LOONGSON_PWM_REG_CTRL into a 16-bit local variable before writing it
back to the register, silently clearing the upper 16 bits.
Change val from u16 to u32 to match the 32-bit register width used
throughout the rest of the driver.
Fixes: 2b62c89448dd ("pwm: Add Loongson PWM controller support")
Closes: https://sashiko.dev/#/bug/linux-bea00bdd-ae27-4d81-9902-e96ed8b6d8ad
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/pwm/pwm-loongson.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pwm/pwm-loongson.c b/drivers/pwm/pwm-loongson.c
index 98c809bde2b3..4e8b54c8016c 100644
--- a/drivers/pwm/pwm-loongson.c
+++ b/drivers/pwm/pwm-loongson.c
@@ -76,7 +76,7 @@ static inline void pwm_loongson_writel(struct pwm_loongson_ddata *ddata,
static int pwm_loongson_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
enum pwm_polarity polarity)
{
- u16 val;
+ u32 val;
struct pwm_loongson_ddata *ddata = to_pwm_loongson_ddata(chip);
val = pwm_loongson_readl(ddata, LOONGSON_PWM_REG_CTRL);
Cc: Binbin Zhou <zhoubinbin@loongson.cn>
--
2.56.0.398.g882cbad275-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 4/8] pwm: axi-pwmgen: Enable clocks before accessing hardware registers in probe()
2026-11-05 14:38 [PATCH 0/8] pwm: Fix various bugs reported by Sashiko Lee Jones
` (2 preceding siblings ...)
2026-11-05 14:38 ` [PATCH 3/8] pwm: loongson: Fix 32-bit control register truncation in pwm_loongson_set_polarity() Lee Jones
@ 2026-11-05 14:38 ` Lee Jones
2026-11-05 15:48 ` Uwe Kleine-König
2026-11-05 14:38 ` [PATCH 5/8] pwm: fsl-ftm: Enable ipg_clk around regcache_sync() during resume Lee Jones
` (3 subsequent siblings)
7 siblings, 1 reply; 14+ messages in thread
From: Lee Jones @ 2026-11-05 14:38 UTC (permalink / raw)
To: lee, Michael Hennerich, Nuno Sá,
Trevor Gamblin, Uwe Kleine-König, Sergiu Cuciurean,
Drew Fustini, linux-pwm, linux-kernel
Cc: stable
axi_pwmgen_probe() calls axi_pwmgen_setup(), which reads and writes MMIO
registers to verify the IP core version and determine the channel count,
before acquiring and enabling axi_clk. If the bootloader leaves the AXI
peripheral clock gated, accessing the registers causes an unclocked bus
access fault.
Acquire and enable the clocks before calling axi_pwmgen_setup().
Fixes: 41814fe5c782 ("pwm: Add driver for AXI PWM generator")
Closes: https://sashiko.dev/#/bug/linux-bc988dbc-7b12-4785-a164-b6dcab29b86a
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/pwm/pwm-axi-pwmgen.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/pwm/pwm-axi-pwmgen.c b/drivers/pwm/pwm-axi-pwmgen.c
index b40522f01002..7c1b38124787 100644
--- a/drivers/pwm/pwm-axi-pwmgen.c
+++ b/drivers/pwm/pwm-axi-pwmgen.c
@@ -270,16 +270,6 @@ static int axi_pwmgen_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(regmap),
"failed to init register map\n");
- ret = axi_pwmgen_setup(regmap, dev);
- if (ret < 0)
- return ret;
-
- chip = devm_pwmchip_alloc(dev, ret, sizeof(*ddata));
- if (IS_ERR(chip))
- return PTR_ERR(chip);
- ddata = pwmchip_get_drvdata(chip);
- ddata->regmap = regmap;
-
/*
* Using NULL here instead of "axi" for backwards compatibility. There
* are some dtbs that don't give clock-names and have the "ext" clock
@@ -305,6 +295,16 @@ static int axi_pwmgen_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "failed to get exclusive rate\n");
+ ret = axi_pwmgen_setup(regmap, dev);
+ if (ret < 0)
+ return ret;
+
+ chip = devm_pwmchip_alloc(dev, ret, sizeof(*ddata));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ ddata = pwmchip_get_drvdata(chip);
+ ddata->regmap = regmap;
+
ddata->clk_rate_hz = clk_get_rate(clk);
if (!ddata->clk_rate_hz || ddata->clk_rate_hz > NSEC_PER_SEC)
return dev_err_probe(dev, -EINVAL,
Cc: Drew Fustini <dfustini@baylibre.com>
--
2.56.0.398.g882cbad275-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 5/8] pwm: fsl-ftm: Enable ipg_clk around regcache_sync() during resume
2026-11-05 14:38 [PATCH 0/8] pwm: Fix various bugs reported by Sashiko Lee Jones
` (3 preceding siblings ...)
2026-11-05 14:38 ` [PATCH 4/8] pwm: axi-pwmgen: Enable clocks before accessing hardware registers in probe() Lee Jones
@ 2026-11-05 14:38 ` Lee Jones
2026-11-05 14:38 ` [PATCH 6/8] pwm: omap-dmtimer: Handle negative error codes from get_pwm_status() Lee Jones
` (2 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Lee Jones @ 2026-11-05 14:38 UTC (permalink / raw)
To: lee, Uwe Kleine-König, Xiubo Li, shenwei.wang,
Thierry Reding, linux-pwm, linux-kernel
Cc: stable
On SoCs with a dedicated IP interface clock (ipg_clk), register accesses
require ipg_clk to be enabled in addition to the ftm_sys clock managed
by regmap_mmio. In fsl_pwm_resume(), ipg_clk is only enabled inside the
channel loop for channels with PWMF_REQUESTED set, so if no channels are
currently requested, regcache_sync() writes to the hardware registers
while ipg_clk is disabled.
Enable ipg_clk across fsl_pwm_resume() around regcache_sync(), matching
fsl_pwm_init().
Fixes: 82a9c55a2bb0 ("pwm: fsl-ftm: Added a dedicated IP interface clock")
Closes: https://sashiko.dev/#/bug/linux-858851cf-55a9-4776-883c-69c05f3961f2
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/pwm/pwm-fsl-ftm.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c
index 35406b2e1925..9e5470e2efe6 100644
--- a/drivers/pwm/pwm-fsl-ftm.c
+++ b/drivers/pwm/pwm-fsl-ftm.c
@@ -501,8 +501,13 @@ static int fsl_pwm_resume(struct device *dev)
{
struct pwm_chip *chip = dev_get_drvdata(dev);
struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
+ int ret;
int i;
+ ret = clk_prepare_enable(fpc->ipg_clk);
+ if (ret)
+ return ret;
+
for (i = 0; i < chip->npwm; i++) {
struct pwm_device *pwm = &chip->pwms[i];
@@ -522,6 +527,8 @@ static int fsl_pwm_resume(struct device *dev)
regcache_cache_only(fpc->regmap, false);
regcache_sync(fpc->regmap);
+ clk_disable_unprepare(fpc->ipg_clk);
+
return 0;
}
#endif
Cc: shenwei.wang@nxp.com
--
2.56.0.398.g882cbad275-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 6/8] pwm: omap-dmtimer: Handle negative error codes from get_pwm_status()
2026-11-05 14:38 [PATCH 0/8] pwm: Fix various bugs reported by Sashiko Lee Jones
` (4 preceding siblings ...)
2026-11-05 14:38 ` [PATCH 5/8] pwm: fsl-ftm: Enable ipg_clk around regcache_sync() during resume Lee Jones
@ 2026-11-05 14:38 ` Lee Jones
2026-11-05 14:38 ` [PATCH 7/8] pwm: tiehrpwm: Enable runtime PM before registering PWM chip Lee Jones
2026-11-05 14:38 ` [PATCH 8/8] pwm: img: Unregister PWM chip before disabling runtime PM and clocks Lee Jones
7 siblings, 0 replies; 14+ messages in thread
From: Lee Jones @ 2026-11-05 14:38 UTC (permalink / raw)
To: lee, Uwe Kleine-König, Neil Armstrong, Joachim Eastwood,
NeilBrown, Grant Erickson, Thierry Reding, Lokesh Vutla,
linux-pwm, linux-kernel
Cc: stable
omap->pdata->get_pwm_status() returns a signed int that can be a
negative error code on runtime PM failure or invalid timer cookie.
pwm_omap_dmtimer_is_enabled() and pwm_omap_dmtimer_polarity() store the
return value in an unsigned u32 and test OMAP_TIMER_CTRL_ST (BIT(0)) and
OMAP_TIMER_CTRL_SCPWM (BIT(7)), misinterpreting negative error codes
(such as -EINVAL or -EACCES) as an enabled or inverted timer.
Store the return value in a signed int and check for negative error
codes before testing register bits.
Fixes: 6b28fb6f3ca3 ("pwm: omap-dmtimer: Implement .apply callback")
Closes: https://sashiko.dev/#/bug/linux-f4782faa-466d-43a8-85d8-6d6181ee2243
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/pwm/pwm-omap-dmtimer.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
index 51830a87275c..1e4d8b9e224f 100644
--- a/drivers/pwm/pwm-omap-dmtimer.c
+++ b/drivers/pwm/pwm-omap-dmtimer.c
@@ -111,9 +111,11 @@ static void pwm_omap_dmtimer_start(struct pwm_omap_dmtimer_chip *omap)
*/
static bool pwm_omap_dmtimer_is_enabled(struct pwm_omap_dmtimer_chip *omap)
{
- u32 status;
+ int status;
status = omap->pdata->get_pwm_status(omap->dm_timer);
+ if (status < 0)
+ return false;
return !!(status & OMAP_TIMER_CTRL_ST);
}
@@ -126,9 +128,11 @@ static bool pwm_omap_dmtimer_is_enabled(struct pwm_omap_dmtimer_chip *omap)
*/
static int pwm_omap_dmtimer_polarity(struct pwm_omap_dmtimer_chip *omap)
{
- u32 status;
+ int status;
status = omap->pdata->get_pwm_status(omap->dm_timer);
+ if (status < 0)
+ return PWM_POLARITY_NORMAL;
return !!(status & OMAP_TIMER_CTRL_SCPWM);
}
Cc: Lokesh Vutla <lokeshvutla@ti.com>
--
2.56.0.398.g882cbad275-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 7/8] pwm: tiehrpwm: Enable runtime PM before registering PWM chip
2026-11-05 14:38 [PATCH 0/8] pwm: Fix various bugs reported by Sashiko Lee Jones
` (5 preceding siblings ...)
2026-11-05 14:38 ` [PATCH 6/8] pwm: omap-dmtimer: Handle negative error codes from get_pwm_status() Lee Jones
@ 2026-11-05 14:38 ` Lee Jones
2026-11-05 14:38 ` [PATCH 8/8] pwm: img: Unregister PWM chip before disabling runtime PM and clocks Lee Jones
7 siblings, 0 replies; 14+ messages in thread
From: Lee Jones @ 2026-11-05 14:38 UTC (permalink / raw)
To: lee, Uwe Kleine-König, Philip, Avinash, Vaibhav Bedia,
Thierry Reding, linux-pwm, linux-kernel
Cc: stable
ehrpwm_pwm_probe() calls pwmchip_add() before setting driver data and
enabling runtime PM. Because pwmchip_add() immediately exposes the PWM
channels to consumers, a consumer can invoke ehrpwm_pwm_apply() before
pm_runtime_enable() runs, causing registers to be accessed while the
device remains runtime-suspended.
Set driver data and enable runtime PM before calling pwmchip_add(), and
disable runtime PM on the error path.
Fixes: 19891b20e7c2 ("pwm: pwm-tiehrpwm: PWM driver support for EHRPWM")
Closes: https://sashiko.dev/#/bug/linux-28b36a80-e4a9-4bb6-97bc-7ca02895570a
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/pwm/pwm-tiehrpwm.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index e3407d0a1f7f..f9dd3b91c73a 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -461,18 +461,19 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
return ret;
}
- ret = pwmchip_add(chip);
- if (ret < 0) {
- dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
- goto err_clk_unprepare;
- }
-
platform_set_drvdata(pdev, chip);
pm_runtime_enable(&pdev->dev);
+ ret = pwmchip_add(chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
+ goto err_pm_disable;
+ }
+
return 0;
-err_clk_unprepare:
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
clk_unprepare(pc->tbclk);
return ret;
Cc: "Philip, Avinash" <avinashphilip@ti.com>
--
2.56.0.398.g882cbad275-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 8/8] pwm: img: Unregister PWM chip before disabling runtime PM and clocks
2026-11-05 14:38 [PATCH 0/8] pwm: Fix various bugs reported by Sashiko Lee Jones
` (6 preceding siblings ...)
2026-11-05 14:38 ` [PATCH 7/8] pwm: tiehrpwm: Enable runtime PM before registering PWM chip Lee Jones
@ 2026-11-05 14:38 ` Lee Jones
7 siblings, 0 replies; 14+ messages in thread
From: Lee Jones @ 2026-11-05 14:38 UTC (permalink / raw)
To: lee, Uwe Kleine-König, Sai Masarapu, Vladimir Zapolskiy,
Naidu Tellapati, Ezequiel Garcia, Thierry Reding,
Andrew Bresticker, linux-pwm, linux-kernel
Cc: stable
img_pwm_remove() disables runtime PM and gates the peripheral clocks via
img_pwm_runtime_suspend() before calling pwmchip_remove(). While the
PWM chip is still registered, a consumer can call img_pwm_apply(), where
pm_runtime_resume_and_get() returns -EACCES or succeeds without
re-enabling clocks, leading to unclocked register access.
Call pwmchip_remove() before disabling runtime PM and suspending the
device.
Fixes: 277bb6a29e00 ("pwm: Imagination Technologies PWM DAC driver")
Closes: https://sashiko.dev/#/bug/linux-b06bab8d-dbf2-4ba2-9f5d-c5e141076abd
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/pwm/pwm-img.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/pwm/pwm-img.c b/drivers/pwm/pwm-img.c
index 91e0b19f0c08..b6e090674c07 100644
--- a/drivers/pwm/pwm-img.c
+++ b/drivers/pwm/pwm-img.c
@@ -338,11 +338,11 @@ static void img_pwm_remove(struct platform_device *pdev)
{
struct pwm_chip *chip = platform_get_drvdata(pdev);
- pm_runtime_disable(&pdev->dev);
- if (!pm_runtime_status_suspended(&pdev->dev))
- img_pwm_runtime_suspend(&pdev->dev);
-
pwmchip_remove(chip);
+
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ img_pwm_runtime_suspend(&pdev->dev);
}
#ifdef CONFIG_PM_SLEEP
Cc: Naidu Tellapati <naidu.tellapati@gmail.com>
--
2.56.0.398.g882cbad275-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/8] pwm: tegra: Prevent 32-bit period truncation and division by zero
2026-11-05 14:38 ` [PATCH 1/8] pwm: tegra: Prevent 32-bit period truncation and division by zero Lee Jones
@ 2026-11-05 15:46 ` Uwe Kleine-König
0 siblings, 0 replies; 14+ messages in thread
From: Uwe Kleine-König @ 2026-11-05 15:46 UTC (permalink / raw)
To: Lee Jones
Cc: Thierry Reding, Jonathan Hunter, Mikko Perttunen, Sascha Hauer,
Sandipan Patra, linux-pwm, linux-tegra, linux-kernel, stable
[-- Attachment #1: Type: text/plain, Size: 1106 bytes --]
Hello Lee,
On Thu, Nov 05, 2026 at 02:38:03PM +0000, Lee Jones wrote:
> tegra_pwm_apply() passes the 64-bit state->duty_cycle and state->period
> values into tegra_pwm_config(), which accepts signed 32-bit int
> parameters and performs DIV_ROUND_CLOSEST_ULL(c, period_ns) before
> validating period_ns against pc->min_period_ns. If a consumer requests
> a period that is a non-zero multiple of 2^32 nanoseconds, period_ns
> truncates to zero and triggers a divide-by-zero panic.
>
> Widen duty_ns and period_ns to u64 and validate that period_ns lies
> within [pc->min_period_ns, U32_MAX] prior to dividing by period_ns.
>
> Fixes: 1d7796bdb63a ("pwm: tegra: Support dynamic clock frequency configuration")
> Fixes: fd3ddd4355c0 ("pwm: tegra: Implement .apply() callback")
> Closes: https://sashiko.dev/#/bug/linux-5c5b97d6-4da6-4d06-9dc7-957419dcd832
> Cc: stable@vger.kernel.org
> Signed-off-by: Lee Jones <lee@kernel.org>
This is already addressed in
9ad5602d4943 ("pwm: tegra: Fix value discarding for duty and period")
which is next-20261102 and later.
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 4/8] pwm: axi-pwmgen: Enable clocks before accessing hardware registers in probe()
2026-11-05 14:38 ` [PATCH 4/8] pwm: axi-pwmgen: Enable clocks before accessing hardware registers in probe() Lee Jones
@ 2026-11-05 15:48 ` Uwe Kleine-König
2026-11-05 18:26 ` Lee Jones
0 siblings, 1 reply; 14+ messages in thread
From: Uwe Kleine-König @ 2026-11-05 15:48 UTC (permalink / raw)
To: Lee Jones
Cc: Michael Hennerich, Nuno Sá,
Trevor Gamblin, Sergiu Cuciurean, Drew Fustini, linux-pwm,
linux-kernel, stable
[-- Attachment #1: Type: text/plain, Size: 471 bytes --]
On Thu, Nov 05, 2026 at 02:38:06PM +0000, Lee Jones wrote:
> axi_pwmgen_probe() calls axi_pwmgen_setup(), which reads and writes MMIO
> registers to verify the IP core version and determine the channel count,
> before acquiring and enabling axi_clk. If the bootloader leaves the AXI
> peripheral clock gated, accessing the registers causes an unclocked bus
> access fault.
Do you have the hardware? Or what convinced you that an access fault
happens?
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/8] pwm: mxs: Return early when disabling and fix error-path clock leak
2026-11-05 14:38 ` [PATCH 2/8] pwm: mxs: Return early when disabling and fix error-path clock leak Lee Jones
@ 2026-11-05 16:50 ` Frank Li
0 siblings, 0 replies; 14+ messages in thread
From: Frank Li @ 2026-11-05 16:50 UTC (permalink / raw)
To: Lee Jones
Cc: Uwe Kleine-König, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shawn Guo,
Thierry Reding, Rasmus Villemoes, linux-pwm, imx,
linux-arm-kernel, linux-kernel, stable
On Thu, Nov 05, 2026 at 02:38:04PM +0000, Lee Jones wrote:
> When disabling a PWM channel (!state->enabled), the PWM core permits
> state->period to be zero. mxs_pwm_apply() currently falls through into
> the period and duty-cycle calculations even when !state->enabled,
> causing do_div(c, state->period) to divide by zero when state->period is
> zero. In addition, if the requested period exceeds the maximum divider
> (div >= PERIOD_CDIV_MAX) while the PWM channel is currently disabled,
> mxs_pwm_apply() returns -EINVAL without disabling and unpreparing
> mxs->clk.
>
> Handle the !state->enabled path upfront and return early, and balance
> clk_prepare_enable() on the -EINVAL error path.
>
> Fixes: bf29c2ff82fd ("pwm: mxs: Implement ->apply()")
> Closes: https://sashiko.dev/#/bug/linux-710f863f-6964-4e4f-990a-e5043dbc1a87
> Cc: stable@vger.kernel.org
> Signed-off-by: Lee Jones <lee@kernel.org>
> --
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/pwm/pwm-mxs.c | 32 ++++++++++++++++++--------------
> 1 file changed, 18 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
> index e1a3df6549fc..16233764fd3c 100644
> --- a/drivers/pwm/pwm-mxs.c
> +++ b/drivers/pwm/pwm-mxs.c
> @@ -56,6 +56,14 @@ static int mxs_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> unsigned long long c;
> unsigned int pol_bits;
>
> + if (!state->enabled) {
> + if (pwm_is_enabled(pwm)) {
> + writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + CLR);
> + clk_disable_unprepare(mxs->clk);
> + }
> + return 0;
> + }
> +
> /*
> * If the PWM channel is disabled, make sure to turn on the
> * clock before calling clk_get_rate() and writing to the
> @@ -67,9 +75,6 @@ static int mxs_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> return ret;
> }
>
> - if (!state->enabled && pwm_is_enabled(pwm))
> - writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + CLR);
> -
> rate = clk_get_rate(mxs->clk);
> while (1) {
> c = rate >> cdiv_shift[div];
> @@ -78,8 +83,11 @@ static int mxs_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> if (c < PERIOD_PERIOD_MAX)
> break;
> div++;
> - if (div >= PERIOD_CDIV_MAX)
> + if (div >= PERIOD_CDIV_MAX) {
> + if (!pwm_is_enabled(pwm))
> + clk_disable_unprepare(mxs->clk);
> return -EINVAL;
> + }
> }
>
> period_cycles = c;
> @@ -101,16 +109,12 @@ static int mxs_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> writel(PERIOD_PERIOD(period_cycles) | pol_bits | PERIOD_CDIV(div),
> mxs->base + PWM_PERIOD0 + pwm->hwpwm * 0x20);
>
> - if (state->enabled) {
> - if (!pwm_is_enabled(pwm)) {
> - /*
> - * The clock was enabled above. Just enable
> - * the channel in the control register.
> - */
> - writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + SET);
> - }
> - } else {
> - clk_disable_unprepare(mxs->clk);
> + if (!pwm_is_enabled(pwm)) {
> + /*
> + * The clock was enabled above. Just enable
> + * the channel in the control register.
> + */
> + writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + SET);
> }
> return 0;
> }
> Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> --
> 2.56.0.398.g882cbad275-goog
>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 4/8] pwm: axi-pwmgen: Enable clocks before accessing hardware registers in probe()
2026-11-05 15:48 ` Uwe Kleine-König
@ 2026-11-05 18:26 ` Lee Jones
2026-11-05 18:26 ` Lee Jones
0 siblings, 1 reply; 14+ messages in thread
From: Lee Jones @ 2026-11-05 18:26 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Michael Hennerich, Nuno Sá,
Trevor Gamblin, Sergiu Cuciurean, Drew Fustini, linux-pwm,
linux-kernel, stable
On Thu, 05 Nov 2026, Uwe Kleine-König wrote:
> On Thu, Nov 05, 2026 at 02:38:06PM +0000, Lee Jones wrote:
> > axi_pwmgen_probe() calls axi_pwmgen_setup(), which reads and writes MMIO
> > registers to verify the IP core version and determine the channel count,
> > before acquiring and enabling axi_clk. If the bootloader leaves the AXI
> > peripheral clock gated, accessing the registers causes an unclocked bus
> > access fault.
>
> Do you have the hardware? Or what convinced you that an access fault
> happens?
These are Sashiko bugs, as we discussed out-of-band.
None of these have been tested on real h/w.
--
Lee Jones
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 4/8] pwm: axi-pwmgen: Enable clocks before accessing hardware registers in probe()
2026-11-05 18:26 ` Lee Jones
@ 2026-11-05 18:26 ` Lee Jones
0 siblings, 0 replies; 14+ messages in thread
From: Lee Jones @ 2026-11-05 18:26 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Michael Hennerich, Nuno Sá,
Trevor Gamblin, Sergiu Cuciurean, Drew Fustini, linux-pwm,
linux-kernel, stable
On Thu, 05 Nov 2026, Lee Jones wrote:
> On Thu, 05 Nov 2026, Uwe Kleine-König wrote:
>
> > On Thu, Nov 05, 2026 at 02:38:06PM +0000, Lee Jones wrote:
> > > axi_pwmgen_probe() calls axi_pwmgen_setup(), which reads and writes MMIO
> > > registers to verify the IP core version and determine the channel count,
> > > before acquiring and enabling axi_clk. If the bootloader leaves the AXI
> > > peripheral clock gated, accessing the registers causes an unclocked bus
> > > access fault.
> >
> > Do you have the hardware? Or what convinced you that an access fault
> > happens?
>
> These are Sashiko bugs, as we discussed out-of-band.
>
> None of these have been tested on real h/w.
I'll make that clear in the cover-letters going forward.
--
Lee Jones
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-11-05 18:26 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-05 14:38 [PATCH 0/8] pwm: Fix various bugs reported by Sashiko Lee Jones
2026-11-05 14:38 ` [PATCH 1/8] pwm: tegra: Prevent 32-bit period truncation and division by zero Lee Jones
2026-11-05 15:46 ` Uwe Kleine-König
2026-11-05 14:38 ` [PATCH 2/8] pwm: mxs: Return early when disabling and fix error-path clock leak Lee Jones
2026-11-05 16:50 ` Frank Li
2026-11-05 14:38 ` [PATCH 3/8] pwm: loongson: Fix 32-bit control register truncation in pwm_loongson_set_polarity() Lee Jones
2026-11-05 14:38 ` [PATCH 4/8] pwm: axi-pwmgen: Enable clocks before accessing hardware registers in probe() Lee Jones
2026-11-05 15:48 ` Uwe Kleine-König
2026-11-05 18:26 ` Lee Jones
2026-11-05 18:26 ` Lee Jones
2026-11-05 14:38 ` [PATCH 5/8] pwm: fsl-ftm: Enable ipg_clk around regcache_sync() during resume Lee Jones
2026-11-05 14:38 ` [PATCH 6/8] pwm: omap-dmtimer: Handle negative error codes from get_pwm_status() Lee Jones
2026-11-05 14:38 ` [PATCH 7/8] pwm: tiehrpwm: Enable runtime PM before registering PWM chip Lee Jones
2026-11-05 14:38 ` [PATCH 8/8] pwm: img: Unregister PWM chip before disabling runtime PM and clocks Lee Jones
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®