diff options
| author | Mark Brown <broonie@kernel.org> | 2024-01-31 13:17:06 +0000 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2024-01-31 13:17:06 +0000 |
| commit | b25c4e5684cd4e5a3528485918e34f04a4bea3e5 (patch) | |
| tree | d90c34ef9bdd7b21ada3ac9a6fb027ba9715e7f2 /kernel/time/clocksource.c | |
| parent | 9a6d7c4fb2801b675a9c31a7ceb78c84b8c439bc (diff) | |
| parent | 260b08aed4a770335ece16781d8023e9ff488ae0 (diff) | |
| download | lwn-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.c | 25 |
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) { |
