forked from rrcarlosr/Jetpack
80 lines
2.3 KiB
Diff
80 lines
2.3 KiB
Diff
From 73d2e0ce2f4979fa774b077286d2e6b91fddbfa7 Mon Sep 17 00:00:00 2001
|
|
From: Steven Rostedt <rostedt@goodmis.org>
|
|
Date: Wed, 26 Jun 2013 15:28:11 -0400
|
|
Subject: [PATCH 323/352] rt,ntp: Move call to schedule_delayed_work() to
|
|
helper thread
|
|
|
|
The ntp code for notify_cmos_timer() is called from a hard interrupt
|
|
context. schedule_delayed_work() under PREEMPT_RT_FULL calls spinlocks
|
|
that have been converted to mutexes, thus calling schedule_delayed_work()
|
|
from interrupt is not safe.
|
|
|
|
Add a helper thread that does the call to schedule_delayed_work and wake
|
|
up that thread instead of calling schedule_delayed_work() directly.
|
|
This is only for CONFIG_PREEMPT_RT_FULL, otherwise the code still calls
|
|
schedule_delayed_work() directly in irq context.
|
|
|
|
Note: There's a few places in the kernel that do this. Perhaps the RT
|
|
code should have a dedicated thread that does the checks. Just register
|
|
a notifier on boot up for your check and wake up the thread when
|
|
needed. This will be a todo.
|
|
|
|
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
[bigeasy: use swork_queue() instead a helper thread]
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
kernel/time/ntp.c | 26 ++++++++++++++++++++++++++
|
|
1 file changed, 26 insertions(+)
|
|
|
|
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
|
|
index 6df8927..05b7391 100644
|
|
--- a/kernel/time/ntp.c
|
|
+++ b/kernel/time/ntp.c
|
|
@@ -17,6 +17,7 @@
|
|
#include <linux/module.h>
|
|
#include <linux/rtc.h>
|
|
#include <linux/math64.h>
|
|
+#include <linux/swork.h>
|
|
|
|
#include "ntp_internal.h"
|
|
#include "timekeeping_internal.h"
|
|
@@ -568,10 +569,35 @@ static void sync_cmos_clock(struct work_struct *work)
|
|
&sync_cmos_work, timespec64_to_jiffies(&next));
|
|
}
|
|
|
|
+#ifdef CONFIG_PREEMPT_RT_FULL
|
|
+
|
|
+static void run_clock_set_delay(struct swork_event *event)
|
|
+{
|
|
+ queue_delayed_work(system_power_efficient_wq, &sync_cmos_work, 0);
|
|
+}
|
|
+
|
|
+static struct swork_event ntp_cmos_swork;
|
|
+
|
|
+void ntp_notify_cmos_timer(void)
|
|
+{
|
|
+ swork_queue(&ntp_cmos_swork);
|
|
+}
|
|
+
|
|
+static __init int create_cmos_delay_thread(void)
|
|
+{
|
|
+ WARN_ON(swork_get());
|
|
+ INIT_SWORK(&ntp_cmos_swork, run_clock_set_delay);
|
|
+ return 0;
|
|
+}
|
|
+early_initcall(create_cmos_delay_thread);
|
|
+
|
|
+#else
|
|
+
|
|
void ntp_notify_cmos_timer(void)
|
|
{
|
|
queue_delayed_work(system_power_efficient_wq, &sync_cmos_work, 0);
|
|
}
|
|
+#endif /* CONFIG_PREEMPT_RT_FULL */
|
|
|
|
#else
|
|
void ntp_notify_cmos_timer(void) { }
|
|
--
|
|
2.7.4
|
|
|