[PATCH] alpha: Use work_on_cpu() for cross-CPU RTC access
From: Matt Turner
Date: Thu May 28 2026 - 19:08:19 EST
smp_call_function_single() runs its callback in IPI (hardirq)
context. mc146818_set_time() and mc146818_get_time() take rtc_lock
(spinlock_t), which is a sleeping lock on PREEMPT_RT, triggering
a lockdep "Invalid wait context" splat on Marvel SMP.
work_on_cpu() runs the callback in a kthread (process) context,
which can acquire sleeping locks.
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Matt Turner <mattst88@xxxxxxxxx>
---
arch/alpha/kernel/rtc.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git ./arch/alpha/kernel/rtc.c ./arch/alpha/kernel/rtc.c
index cfdf90bc8b3f..4ad5846a1d71 100644
--- ./arch/alpha/kernel/rtc.c
+++ ./arch/alpha/kernel/rtc.c
@@ -15,6 +15,7 @@
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
+#include <linux/workqueue.h>
#include "proto.h"
@@ -155,11 +156,12 @@ union remote_data {
long retval;
};
-static void
+static long
do_remote_read(void *data)
{
union remote_data *x = data;
x->retval = alpha_rtc_read_time(NULL, x->tm);
+ return 0;
}
static int
@@ -168,17 +170,18 @@ remote_read_time(struct device *dev, struct rtc_time *tm)
union remote_data x;
if (smp_processor_id() != boot_cpuid) {
x.tm = tm;
- smp_call_function_single(boot_cpuid, do_remote_read, &x, 1);
+ work_on_cpu(boot_cpuid, do_remote_read, &x);
return x.retval;
}
return alpha_rtc_read_time(NULL, tm);
}
-static void
+static long
do_remote_set(void *data)
{
union remote_data *x = data;
x->retval = alpha_rtc_set_time(NULL, x->tm);
+ return 0;
}
static int
@@ -187,7 +190,7 @@ remote_set_time(struct device *dev, struct rtc_time *tm)
union remote_data x;
if (smp_processor_id() != boot_cpuid) {
x.tm = tm;
- smp_call_function_single(boot_cpuid, do_remote_set, &x, 1);
+ work_on_cpu(boot_cpuid, do_remote_set, &x);
return x.retval;
}
return alpha_rtc_set_time(NULL, tm);
--
2.53.0