Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] clocksource/drivers/samsung_pwm: switch to raw_spinlock_t type
       [not found] <CGME20260713085705eucas1p26616e64d55f903a6f87dd67e8f8da1a9@eucas1p2.samsung.com>
@ 2026-07-13  8:56 ` Marek Szyprowski
  2026-07-13 10:31   ` Sebastian Andrzej Siewior
                     ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Marek Szyprowski @ 2026-07-13  8:56 UTC (permalink / raw)
  Cc: Marek Szyprowski, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
	Daniel Lezcano, Thomas Gleixner, Uwe Kleine-K.nig,
	Sebastian Andrzej Siewior, linux-arm-kernel, linux-samsung-soc,
	linux-pwm, linux-rt-devel

Samsung PWM timer might be used as a clock source on some legacy systems.
When PREEMPT_RT is enabled on ARM, regular spinlock is converted to a
sleeping lock (mutex-based), which must not be used in atomic context
such as hard interrupt handlers. Switch the samsung_pwm_lock to the
raw_spinlock, which remains a true non-sleeping spinlock even
under PREEMPT_RT.

Fixes: 7aac482e6290 ("clocksource: samsung_pwm_timer: Make PWM spinlock global")
Fixes: f11899894c0a ("clocksource: add samsung pwm timer driver")
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
This fixes the following warning observed during boot, when
CONFIG_PROVE_RAW_LOCK_NESTING is set:

 clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
 Exynos4210 clocks: sclk_apll = 800000000, sclk_mpll = 800000000
  sclk_epll = 96000000, sclk_vpll = 108000000, arm_clk = 800000000
 
 =============================
 [ BUG: Invalid wait context ]
 7.2.0-rc1 #13178 Not tainted
 -----------------------------
 swapper/0/0 is trying to lock:
 c1640e90 (samsung_pwm_lock){....}-{3:3}, at: samsung_time_stop+0x28/0x58
 other info that might help us debug this:
 context-{5:5}
 1 lock held by swapper/0/0:
  #0: c15856f0 (clockevents_lock){....}-{2:2}, at: clockevents_register_device+0x44/0x15c
 stack backtrace:
 CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.2.0-rc1 #13178 PREEMPT 
 Hardware name: Samsung Exynos (Flattened Device Tree)
 Call trace: 
  unwind_backtrace from show_stack+0x10/0x14
  show_stack from dump_stack_lvl+0x68/0x88
  dump_stack_lvl from __lock_acquire+0xb44/0x2a58
  __lock_acquire from lock_acquire+0x134/0x3dc
  lock_acquire from _raw_spin_lock_irqsave+0x50/0x6c
  _raw_spin_lock_irqsave from samsung_time_stop+0x28/0x58
  samsung_time_stop from samsung_shutdown+0x14/0x1c
  samsung_shutdown from clockevents_exchange_device+0x90/0xf4
  clockevents_exchange_device from tick_check_new_device+0x6c/0xc8
  tick_check_new_device from clockevents_register_device+0x6c/0x15c
  clockevents_register_device from _samsung_pwm_clocksource_init+0x148/0x2a4
  _samsung_pwm_clocksource_init from samsung_pwm_alloc+0x13c/0x18c
  samsung_pwm_alloc from timer_probe+0x70/0xec
  timer_probe from time_init+0x28/0x30
  time_init from start_kernel+0x620/0x7a4
  start_kernel from 0x0
 sched_clock: 32 bits at 50MHz, resolution 20ns, wraps every 42949672950ns
 clocksource: samsung_clocksource_timer: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 38225208935 ns

Best regards
Marek Szyprowski, PhD
Samsung R&D Institute Poland
---
 drivers/clocksource/samsung_pwm_timer.c | 22 +++++++++++-----------
 drivers/pwm/pwm-samsung.c               | 22 +++++++++++-----------
 include/clocksource/samsung_pwm.h       |  2 +-
 3 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c
index b9561e3f196c..0544124cf5ce 100644
--- a/drivers/clocksource/samsung_pwm_timer.c
+++ b/drivers/clocksource/samsung_pwm_timer.c
@@ -56,7 +56,7 @@
 #define TCON_AUTORELOAD(chan)		\
 	((chan < 5) ? _TCON_AUTORELOAD(chan) : _TCON_AUTORELOAD4(chan))
 
-DEFINE_SPINLOCK(samsung_pwm_lock);
+DEFINE_RAW_SPINLOCK(samsung_pwm_lock);
 EXPORT_SYMBOL(samsung_pwm_lock);
 
 struct samsung_pwm_clocksource {
@@ -87,14 +87,14 @@ static void samsung_timer_set_prescale(unsigned int channel, u16 prescale)
 	if (channel >= 2)
 		shift = TCFG0_PRESCALER1_SHIFT;
 
-	spin_lock_irqsave(&samsung_pwm_lock, flags);
+	raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
 
 	reg = readl(pwm.base + REG_TCFG0);
 	reg &= ~(TCFG0_PRESCALER_MASK << shift);
 	reg |= (prescale - 1) << shift;
 	writel(reg, pwm.base + REG_TCFG0);
 
-	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
+	raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
 
 static void samsung_timer_set_divisor(unsigned int channel, u8 divisor)
@@ -106,14 +106,14 @@ static void samsung_timer_set_divisor(unsigned int channel, u8 divisor)
 
 	bits = (fls(divisor) - 1) - pwm.variant.div_base;
 
-	spin_lock_irqsave(&samsung_pwm_lock, flags);
+	raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
 
 	reg = readl(pwm.base + REG_TCFG1);
 	reg &= ~(TCFG1_MUX_MASK << shift);
 	reg |= bits << shift;
 	writel(reg, pwm.base + REG_TCFG1);
 
-	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
+	raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
 
 static void samsung_time_stop(unsigned int channel)
@@ -124,13 +124,13 @@ static void samsung_time_stop(unsigned int channel)
 	if (channel > 0)
 		++channel;
 
-	spin_lock_irqsave(&samsung_pwm_lock, flags);
+	raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
 
 	tcon = readl_relaxed(pwm.base + REG_TCON);
 	tcon &= ~TCON_START(channel);
 	writel_relaxed(tcon, pwm.base + REG_TCON);
 
-	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
+	raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
 
 static void samsung_time_setup(unsigned int channel, unsigned long tcnt)
@@ -142,7 +142,7 @@ static void samsung_time_setup(unsigned int channel, unsigned long tcnt)
 	if (tcon_chan > 0)
 		++tcon_chan;
 
-	spin_lock_irqsave(&samsung_pwm_lock, flags);
+	raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
 
 	tcon = readl_relaxed(pwm.base + REG_TCON);
 
@@ -153,7 +153,7 @@ static void samsung_time_setup(unsigned int channel, unsigned long tcnt)
 	writel_relaxed(tcnt, pwm.base + REG_TCMPB(channel));
 	writel_relaxed(tcon, pwm.base + REG_TCON);
 
-	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
+	raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
 
 static void samsung_time_start(unsigned int channel, bool periodic)
@@ -164,7 +164,7 @@ static void samsung_time_start(unsigned int channel, bool periodic)
 	if (channel > 0)
 		++channel;
 
-	spin_lock_irqsave(&samsung_pwm_lock, flags);
+	raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
 
 	tcon = readl_relaxed(pwm.base + REG_TCON);
 
@@ -178,7 +178,7 @@ static void samsung_time_start(unsigned int channel, bool periodic)
 
 	writel_relaxed(tcon, pwm.base + REG_TCON);
 
-	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
+	raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
 
 static int samsung_set_next_event(unsigned long cycles,
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index 331e81f1594a..a30bd7c305ee 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -102,7 +102,7 @@ struct samsung_pwm_chip {
  * IP. Should this change, both drivers will need to be modified to
  * properly synchronize accesses to particular instances.
  */
-static DEFINE_SPINLOCK(samsung_pwm_lock);
+static DEFINE_RAW_SPINLOCK(samsung_pwm_lock);
 #endif
 
 static inline
@@ -141,14 +141,14 @@ static void pwm_samsung_set_divisor(struct samsung_pwm_chip *our_chip,
 
 	bits = (fls(divisor) - 1) - our_chip->variant.div_base;
 
-	spin_lock_irqsave(&samsung_pwm_lock, flags);
+	raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
 
 	reg = readl(our_chip->base + REG_TCFG1);
 	reg &= ~(TCFG1_MUX_MASK << shift);
 	reg |= bits << shift;
 	writel(reg, our_chip->base + REG_TCFG1);
 
-	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
+	raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
 
 static int pwm_samsung_is_tdiv(struct samsung_pwm_chip *our_chip, unsigned int chan)
@@ -249,7 +249,7 @@ static int pwm_samsung_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 	unsigned long flags;
 	u32 tcon;
 
-	spin_lock_irqsave(&samsung_pwm_lock, flags);
+	raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
 
 	tcon = readl(our_chip->base + REG_TCON);
 
@@ -263,7 +263,7 @@ static int pwm_samsung_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 
 	our_chip->disabled_mask &= ~BIT(pwm->hwpwm);
 
-	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
+	raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 
 	return 0;
 }
@@ -275,7 +275,7 @@ static void pwm_samsung_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 	unsigned long flags;
 	u32 tcon;
 
-	spin_lock_irqsave(&samsung_pwm_lock, flags);
+	raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
 
 	tcon = readl(our_chip->base + REG_TCON);
 	tcon &= ~TCON_AUTORELOAD(tcon_chan);
@@ -290,7 +290,7 @@ static void pwm_samsung_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 
 	our_chip->disabled_mask |= BIT(pwm->hwpwm);
 
-	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
+	raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
 
 static void pwm_samsung_manual_update(struct samsung_pwm_chip *our_chip,
@@ -298,11 +298,11 @@ static void pwm_samsung_manual_update(struct samsung_pwm_chip *our_chip,
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&samsung_pwm_lock, flags);
+	raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
 
 	__pwm_samsung_manual_update(our_chip, pwm);
 
-	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
+	raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
 
 static int __pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -390,7 +390,7 @@ static void pwm_samsung_set_invert(struct samsung_pwm_chip *our_chip,
 	unsigned long flags;
 	u32 tcon;
 
-	spin_lock_irqsave(&samsung_pwm_lock, flags);
+	raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
 
 	tcon = readl(our_chip->base + REG_TCON);
 
@@ -404,7 +404,7 @@ static void pwm_samsung_set_invert(struct samsung_pwm_chip *our_chip,
 
 	writel(tcon, our_chip->base + REG_TCON);
 
-	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
+	raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
 
 static int pwm_samsung_set_polarity(struct pwm_chip *chip,
diff --git a/include/clocksource/samsung_pwm.h b/include/clocksource/samsung_pwm.h
index 9b435caa95fe..36f6f246e559 100644
--- a/include/clocksource/samsung_pwm.h
+++ b/include/clocksource/samsung_pwm.h
@@ -15,7 +15,7 @@
  * spinlock is not shared between both drivers.
  */
 #ifdef CONFIG_CLKSRC_SAMSUNG_PWM
-extern spinlock_t samsung_pwm_lock;
+extern raw_spinlock_t samsung_pwm_lock;
 #endif
 
 struct samsung_pwm_variant {
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] clocksource/drivers/samsung_pwm: switch to raw_spinlock_t type
  2026-07-13  8:56 ` [PATCH] clocksource/drivers/samsung_pwm: switch to raw_spinlock_t type Marek Szyprowski
@ 2026-07-13 10:31   ` Sebastian Andrzej Siewior
  2026-07-13 10:49   ` Krzysztof Kozlowski
  2026-07-13 15:25   ` Uwe Kleine-König
  2 siblings, 0 replies; 4+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-07-13 10:31 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Krzysztof Kozlowski, Peter Griffin, Alim Akhtar, Daniel Lezcano,
	Thomas Gleixner, Uwe Kleine-K.nig, linux-arm-kernel,
	linux-samsung-soc, linux-pwm, linux-rt-devel

On 2026-07-13 10:56:53 [+0200], Marek Szyprowski wrote:
> Samsung PWM timer might be used as a clock source on some legacy systems.
> When PREEMPT_RT is enabled on ARM, regular spinlock is converted to a
> sleeping lock (mutex-based), which must not be used in atomic context
> such as hard interrupt handlers. Switch the samsung_pwm_lock to the
> raw_spinlock, which remains a true non-sleeping spinlock even
> under PREEMPT_RT.
> 
> Fixes: 7aac482e6290 ("clocksource: samsung_pwm_timer: Make PWM spinlock global")
> Fixes: f11899894c0a ("clocksource: add samsung pwm timer driver")
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>

Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Sebastian


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] clocksource/drivers/samsung_pwm: switch to raw_spinlock_t type
  2026-07-13  8:56 ` [PATCH] clocksource/drivers/samsung_pwm: switch to raw_spinlock_t type Marek Szyprowski
  2026-07-13 10:31   ` Sebastian Andrzej Siewior
@ 2026-07-13 10:49   ` Krzysztof Kozlowski
  2026-07-13 15:25   ` Uwe Kleine-König
  2 siblings, 0 replies; 4+ messages in thread
From: Krzysztof Kozlowski @ 2026-07-13 10:49 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Peter Griffin, Alim Akhtar, Daniel Lezcano, Thomas Gleixner,
	Uwe Kleine-K.nig, Sebastian Andrzej Siewior, linux-arm-kernel,
	linux-samsung-soc, linux-pwm, linux-rt-devel

On 13/07/2026 10:56, Marek Szyprowski wrote:
> Samsung PWM timer might be used as a clock source on some legacy systems.
> When PREEMPT_RT is enabled on ARM, regular spinlock is converted to a
> sleeping lock (mutex-based), which must not be used in atomic context
> such as hard interrupt handlers. Switch the samsung_pwm_lock to the
> raw_spinlock, which remains a true non-sleeping spinlock even
> under PREEMPT_RT.
> 
> Fixes: 7aac482e6290 ("clocksource: samsung_pwm_timer: Make PWM spinlock global")
> Fixes: f11899894c0a ("clocksource: add samsung pwm timer driver")
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
> This fixes the following warning observed during boot, when
> CONFIG_PROVE_RAW_LOCK_NESTING is set:
> 
>  clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
>  Exynos4210 clocks: sclk_apll = 800000000, sclk_mpll = 800000000
>   sclk_epll = 96000000, sclk_vpll = 108000000, arm_clk = 800000000
>  
>  =============================
>  [ BUG: Invalid wait context ]
>  7.2.0-rc1 #13178 Not tainted

Looks correct. Pieces of the warning could be in commit msg, but anyway:

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] clocksource/drivers/samsung_pwm: switch to raw_spinlock_t type
  2026-07-13  8:56 ` [PATCH] clocksource/drivers/samsung_pwm: switch to raw_spinlock_t type Marek Szyprowski
  2026-07-13 10:31   ` Sebastian Andrzej Siewior
  2026-07-13 10:49   ` Krzysztof Kozlowski
@ 2026-07-13 15:25   ` Uwe Kleine-König
  2 siblings, 0 replies; 4+ messages in thread
From: Uwe Kleine-König @ 2026-07-13 15:25 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Krzysztof Kozlowski, Peter Griffin, Alim Akhtar, Daniel Lezcano,
	Thomas Gleixner, Sebastian Andrzej Siewior, linux-arm-kernel,
	linux-samsung-soc, linux-pwm, linux-rt-devel

[-- Attachment #1: Type: text/plain, Size: 460 bytes --]

Hello,

On Mon, Jul 13, 2026 at 10:56:53AM +0200, Marek Szyprowski wrote:
>  drivers/clocksource/samsung_pwm_timer.c | 22 +++++++++++-----------
>  drivers/pwm/pwm-samsung.c               | 22 +++++++++++-----------
>  include/clocksource/samsung_pwm.h       |  2 +-
>  3 files changed, 23 insertions(+), 23 deletions(-)

Assuming this will be applied via the clocksource tree:

Acked-by: Uwe Kleine-König <ukleinek@kernel.org>

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-07-13 15:25 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <CGME20260713085705eucas1p26616e64d55f903a6f87dd67e8f8da1a9@eucas1p2.samsung.com>
2026-07-13  8:56 ` [PATCH] clocksource/drivers/samsung_pwm: switch to raw_spinlock_t type Marek Szyprowski
2026-07-13 10:31   ` Sebastian Andrzej Siewior
2026-07-13 10:49   ` Krzysztof Kozlowski
2026-07-13 15:25   ` Uwe Kleine-König

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox