From: Cosmin Tanislav Date: Fri, 30 Jan 2026 12:23:52 +0000 (+0200) Subject: counter: rz-mtu3-cnt: prevent counter from being toggled multiple times X-Git-Tag: v7.0-rc7~8^2~18^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=67c3f99bed6f422ba343d2b70a2eeeccdfd91bef;p=thirdparty%2Flinux.git counter: rz-mtu3-cnt: prevent counter from being toggled multiple times Runtime PM counter is incremented / decremented each time the sysfs enable file is written to. If user writes 0 to the sysfs enable file multiple times, runtime PM usage count underflows, generating the following message. rz-mtu3-counter rz-mtu3-counter.0: Runtime PM usage count underflow! At the same time, hardware registers end up being accessed with clocks off in rz_mtu3_terminate_counter() to disable an already disabled channel. If user writes 1 to the sysfs enable file multiple times, runtime PM usage count will be incremented each time, requiring the same number of 0 writes to get it back to 0. If user writes 0 to the sysfs enable file while PWM is in progress, PWM is stopped without counter being the owner of the underlying MTU3 channel. Check against the cached count_is_enabled value and exit if the user is trying to set the same enable value. Cc: stable@vger.kernel.org Fixes: 0be8907359df ("counter: Add Renesas RZ/G2L MTU3a counter driver") Signed-off-by: Cosmin Tanislav Link: https://lore.kernel.org/r/20260130122353.2263273-5-cosmin-gabriel.tanislav.xa@renesas.com Signed-off-by: William Breathitt Gray --- diff --git a/drivers/counter/rz-mtu3-cnt.c b/drivers/counter/rz-mtu3-cnt.c index e755d54dfece..a4a8ef2d88f0 100644 --- a/drivers/counter/rz-mtu3-cnt.c +++ b/drivers/counter/rz-mtu3-cnt.c @@ -499,21 +499,25 @@ static int rz_mtu3_count_enable_write(struct counter_device *counter, struct rz_mtu3_cnt *const priv = counter_priv(counter); int ret = 0; + mutex_lock(&priv->lock); + + if (priv->count_is_enabled[count->id] == enable) + goto exit; + if (enable) { - mutex_lock(&priv->lock); pm_runtime_get_sync(ch->dev); ret = rz_mtu3_initialize_counter(counter, count->id); if (ret == 0) priv->count_is_enabled[count->id] = true; - mutex_unlock(&priv->lock); } else { - mutex_lock(&priv->lock); rz_mtu3_terminate_counter(counter, count->id); priv->count_is_enabled[count->id] = false; pm_runtime_put(ch->dev); - mutex_unlock(&priv->lock); } +exit: + mutex_unlock(&priv->lock); + return ret; }