[PATCH v4 3/3] pps: convert pps_kc_hardpps_lock to raw_spinlock for PREEMPT_RT
From: Michael Byczkowski
Date: Fri Apr 10 2026 - 06:18:28 EST
Convert pps_kc_hardpps_lock from spinlock_t to raw_spinlock_t. This
lock is held in pps_kc_event() which calls hardpps(). hardpps() takes
tk_core.lock which is already a raw_spinlock — nesting a sleeping lock
(PREEMPT_RT spinlock_t) over a raw_spinlock is invalid.
The locked section only checks a pointer comparison and calls
hardpps(), both of which are non-sleeping.
On non-RT kernels, raw_spinlock_t compiles to identical code as
spinlock_t — no behavioral change.
Signed-off-by: Michael Byczkowski <by@xxxxxxxxxxxx>
Acked-by: Rodolfo Giometti <giometti@xxxxxxxxxxxx>
Tested-by: Michael Byczkowski <by@xxxxxxxxxxxx>
Tested-by: Calvin Owens <calvin@xxxxxxxxxx>
---
drivers/pps/kc.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/pps/kc.c b/drivers/pps/kc.c
index fbd23295afd7..9c6c024d5083 100644
--- a/drivers/pps/kc.c
+++ b/drivers/pps/kc.c
@@ -21,7 +21,7 @@
*/
/* state variables to bind kernel consumer */
-static DEFINE_SPINLOCK(pps_kc_hardpps_lock);
+static DEFINE_RAW_SPINLOCK(pps_kc_hardpps_lock);
/* PPS API (RFC 2783): current source and mode for kernel consumer */
static struct pps_device *pps_kc_hardpps_dev; /* unique pointer to device */
static int pps_kc_hardpps_mode; /* mode bits for kernel consumer */
@@ -36,17 +36,17 @@ static int pps_kc_hardpps_mode; /* mode bits for kernel consumer */
int pps_kc_bind(struct pps_device *pps, struct pps_bind_args *bind_args)
{
/* Check if another consumer is already bound */
- spin_lock_irq(&pps_kc_hardpps_lock);
+ raw_spin_lock_irq(&pps_kc_hardpps_lock);
if (bind_args->edge == 0)
if (pps_kc_hardpps_dev == pps) {
pps_kc_hardpps_mode = 0;
pps_kc_hardpps_dev = NULL;
- spin_unlock_irq(&pps_kc_hardpps_lock);
+ raw_spin_unlock_irq(&pps_kc_hardpps_lock);
dev_info(&pps->dev, "unbound kernel"
" consumer\n");
} else {
- spin_unlock_irq(&pps_kc_hardpps_lock);
+ raw_spin_unlock_irq(&pps_kc_hardpps_lock);
dev_err(&pps->dev, "selected kernel consumer"
" is not bound\n");
return -EINVAL;
@@ -56,11 +56,11 @@ int pps_kc_bind(struct pps_device *pps, struct pps_bind_args *bind_args)
pps_kc_hardpps_dev == pps) {
pps_kc_hardpps_mode = bind_args->edge;
pps_kc_hardpps_dev = pps;
- spin_unlock_irq(&pps_kc_hardpps_lock);
+ raw_spin_unlock_irq(&pps_kc_hardpps_lock);
dev_info(&pps->dev, "bound kernel consumer: "
"edge=0x%x\n", bind_args->edge);
} else {
- spin_unlock_irq(&pps_kc_hardpps_lock);
+ raw_spin_unlock_irq(&pps_kc_hardpps_lock);
dev_err(&pps->dev, "another kernel consumer"
" is already bound\n");
return -EINVAL;
@@ -78,15 +78,15 @@ int pps_kc_bind(struct pps_device *pps, struct pps_bind_args *bind_args)
*/
void pps_kc_remove(struct pps_device *pps)
{
- spin_lock_irq(&pps_kc_hardpps_lock);
+ raw_spin_lock_irq(&pps_kc_hardpps_lock);
if (pps == pps_kc_hardpps_dev) {
pps_kc_hardpps_mode = 0;
pps_kc_hardpps_dev = NULL;
- spin_unlock_irq(&pps_kc_hardpps_lock);
+ raw_spin_unlock_irq(&pps_kc_hardpps_lock);
dev_info(&pps->dev, "unbound kernel consumer"
" on device removal\n");
} else
- spin_unlock_irq(&pps_kc_hardpps_lock);
+ raw_spin_unlock_irq(&pps_kc_hardpps_lock);
}
/* pps_kc_event - call hardpps() on PPS event
@@ -102,8 +102,8 @@ void pps_kc_event(struct pps_device *pps, struct pps_event_time *ts,
unsigned long flags;
/* Pass some events to kernel consumer if activated */
- spin_lock_irqsave(&pps_kc_hardpps_lock, flags);
+ raw_spin_lock_irqsave(&pps_kc_hardpps_lock, flags);
if (pps == pps_kc_hardpps_dev && event & pps_kc_hardpps_mode)
hardpps(&ts->ts_real, &ts->ts_raw);
- spin_unlock_irqrestore(&pps_kc_hardpps_lock, flags);
+ raw_spin_unlock_irqrestore(&pps_kc_hardpps_lock, flags);
}
--
2.47.3