summaryrefslogtreecommitdiff
path: root/kernel/time/clocksource.c
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2024-01-31 13:17:06 +0000
committerMark Brown <broonie@kernel.org>2024-01-31 13:17:06 +0000
commitb25c4e5684cd4e5a3528485918e34f04a4bea3e5 (patch)
treed90c34ef9bdd7b21ada3ac9a6fb027ba9715e7f2 /kernel/time/clocksource.c
parent9a6d7c4fb2801b675a9c31a7ceb78c84b8c439bc (diff)
parent260b08aed4a770335ece16781d8023e9ff488ae0 (diff)
downloadlwn-b25c4e5684cd4e5a3528485918e34f04a4bea3e5.tar.gz
lwn-b25c4e5684cd4e5a3528485918e34f04a4bea3e5.zip
soundwire/SOF: add SoundWire Interface support for
Merge series from Vijendar Mukunda <Vijendar.Mukunda@amd.com>: This patch series is to redesign existing platform device creation logic for SoundWire managers and Implement generic functions for SoundWire manager probe, start and exit sequence which are common for both Legacy (NO DSP enabled) and SOF stack, and add SoundWire Interface support for AMD SOF stack (ACP 6.3 based platform). The patch series was reviewed in https://github.com/thesofproject/linux/pull/4699
Diffstat (limited to 'kernel/time/clocksource.c')
-rw-r--r--kernel/time/clocksource.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index c108ed8a9804..3052b1f1168e 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -99,6 +99,7 @@ static u64 suspend_start;
* Interval: 0.5sec.
*/
#define WATCHDOG_INTERVAL (HZ >> 1)
+#define WATCHDOG_INTERVAL_MAX_NS ((2 * WATCHDOG_INTERVAL) * (NSEC_PER_SEC / HZ))
/*
* Threshold: 0.0312s, when doubled: 0.0625s.
@@ -134,6 +135,7 @@ static DECLARE_WORK(watchdog_work, clocksource_watchdog_work);
static DEFINE_SPINLOCK(watchdog_lock);
static int watchdog_running;
static atomic_t watchdog_reset_pending;
+static int64_t watchdog_max_interval;
static inline void clocksource_watchdog_lock(unsigned long *flags)
{
@@ -399,8 +401,8 @@ static inline void clocksource_reset_watchdog(void)
static void clocksource_watchdog(struct timer_list *unused)
{
u64 csnow, wdnow, cslast, wdlast, delta;
+ int64_t wd_nsec, cs_nsec, interval;
int next_cpu, reset_pending;
- int64_t wd_nsec, cs_nsec;
struct clocksource *cs;
enum wd_read_status read_ret;
unsigned long extra_wait = 0;
@@ -470,6 +472,27 @@ static void clocksource_watchdog(struct timer_list *unused)
if (atomic_read(&watchdog_reset_pending))
continue;
+ /*
+ * The processing of timer softirqs can get delayed (usually
+ * on account of ksoftirqd not getting to run in a timely
+ * manner), which causes the watchdog interval to stretch.
+ * Skew detection may fail for longer watchdog intervals
+ * on account of fixed margins being used.
+ * Some clocksources, e.g. acpi_pm, cannot tolerate
+ * watchdog intervals longer than a few seconds.
+ */
+ interval = max(cs_nsec, wd_nsec);
+ if (unlikely(interval > WATCHDOG_INTERVAL_MAX_NS)) {
+ if (system_state > SYSTEM_SCHEDULING &&
+ interval > 2 * watchdog_max_interval) {
+ watchdog_max_interval = interval;
+ pr_warn("Long readout interval, skipping watchdog check: cs_nsec: %lld wd_nsec: %lld\n",
+ cs_nsec, wd_nsec);
+ }
+ watchdog_timer.expires = jiffies;
+ continue;
+ }
+
/* Check the deviation from the watchdog clocksource. */
md = cs->uncertainty_margin + watchdog->uncertainty_margin;
if (abs(cs_nsec - wd_nsec) > md) {