History

Merge tag 'timers-core-2022-01-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer updates from Thomas Gleixner: "Updates for the time(r) subsystem: Core: - Make the clocksource watchdog more robust by better validation checks of the measurement. Drivers: - New drivers for MStar and SSD20xd SOCs - The usual cleanups and improvements all over the place" * tag 'timers-core-2022-01-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: dt-bindings: timer: Add Mstar MSC313e timer devicetree bindings documentation clocksource/drivers/msc313e: Add support for ssd20xd-based platforms clocksource/drivers: Add MStar MSC313e timer support clocksource/drivers/pistachio: Fix -Wunused-but-set-variable warning clocksource/drivers/timer-imx-sysctr: Set cpumask to cpu_possible_mask clocksource/drivers/imx-sysctr: Mark two variable with __ro_after_init clocksource/drivers/renesas,ostm: Make RENESAS_OSTM symbol visible clocksource/drivers/renesas-ostm: Add RZ/G2L OSTM support dt-bindings: timer: renesas: ostm: Document Renesas RZ/G2L OSTM clocksource/drivers/exynos_mct: Fix silly typo resulting in checkpatch warning clocksource: Reduce the default clocksource_watchdog() retries to 2 clocksource: Avoid accidental unstable marking of clocksources dt-bindings: timer: tpm-timer: Add imx8ulp compatible string reset: Add of_reset_control_get_optional_exclusive() clocksource/drivers/exynos_mct: Refactor resources allocation dt-bindings: timer: remove rockchip,rk3066-timer compatible string from rockchip,rk-timer.yaml dt-bindings: timer: cadence_ttc: Add power-domains

Linus Torvalds committed 4 years ago

Commit fd048992 parents 147cc58 35e13e916 files · +475 −44Browse files

Showing the changes to kernel (1 of 16 files). Show all

Unified · Split

kernel/time/clocksource.c+42−10
@@ -107,7 +107,7 @@ static u64 suspend_start; · 106 unmodified lines
107107 * This delay could be due to SMIs, NMIs, or to VCPU preemptions. Used as
108108 * a lower bound for cs->uncertainty_margin values when registering clocks.
109109 */
110−#define WATCHDOG_MAX_SKEW (50 * NSEC_PER_USEC)
110+#define WATCHDOG_MAX_SKEW (100 * NSEC_PER_USEC)
111111
112112 #ifdef CONFIG_CLOCKSOURCE_WATCHDOG
113113 static void clocksource_watchdog_work(struct work_struct *work);
@@ -199,23 +199,30 @@ void clocksource_mark_unstable(struct clocksource *cs) · 85 unmodified lines
199199 spin_unlock_irqrestore(&watchdog_lock, flags);
200200 }
201201
202−ulong max_cswd_read_retries = 3;
202+ulong max_cswd_read_retries = 2;
203203 module_param(max_cswd_read_retries, ulong, 0644);
204204 EXPORT_SYMBOL_GPL(max_cswd_read_retries);
205205 static int verify_n_cpus = 8;
206206 module_param(verify_n_cpus, int, 0644);
207207
208−static bool cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow)
208+enum wd_read_status {
209+ WD_READ_SUCCESS,
210+ WD_READ_UNSTABLE,
211+ WD_READ_SKIP
212+};
213+
214+static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow)
209215 {
210216 unsigned int nretries;
211− u64 wd_end, wd_delta;
212− int64_t wd_delay;
217+ u64 wd_end, wd_end2, wd_delta;
218+ int64_t wd_delay, wd_seq_delay;
213219
214220 for (nretries = 0; nretries <= max_cswd_read_retries; nretries++) {
215221 local_irq_disable();
216222 *wdnow = watchdog->read(watchdog);
217223 *csnow = cs->read(cs);
218224 wd_end = watchdog->read(watchdog);
225+ wd_end2 = watchdog->read(watchdog);
219226 local_irq_enable();
220227
221228 wd_delta = clocksource_delta(wd_end, *wdnow, watchdog->mask);
@@ -226,13 +233,34 @@ static bool cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow) · 4 unmodified lines
226233 pr_warn("timekeeping watchdog on CPU%d: %s retried %d times before success\n",
227234 smp_processor_id(), watchdog->name, nretries);
228235 }
229− return true;
236+ return WD_READ_SUCCESS;
230237 }
238+
239+ /*
240+ * Now compute delay in consecutive watchdog read to see if
241+ * there is too much external interferences that cause
242+ * significant delay in reading both clocksource and watchdog.
243+ *
244+ * If consecutive WD read-back delay > WATCHDOG_MAX_SKEW/2,
245+ * report system busy, reinit the watchdog and skip the current
246+ * watchdog test.
247+ */
248+ wd_delta = clocksource_delta(wd_end2, wd_end, watchdog->mask);
249+ wd_seq_delay = clocksource_cyc2ns(wd_delta, watchdog->mult, watchdog->shift);
250+ if (wd_seq_delay > WATCHDOG_MAX_SKEW/2)
251+ goto skip_test;
231252 }
232253
233254 pr_warn("timekeeping watchdog on CPU%d: %s read-back delay of %lldns, attempt %d, marking unstable\n",
234255 smp_processor_id(), watchdog->name, wd_delay, nretries);
235− return false;
256+ return WD_READ_UNSTABLE;
257+
258+skip_test:
259+ pr_info("timekeeping watchdog on CPU%d: %s wd-wd read-back delay of %lldns\n",
260+ smp_processor_id(), watchdog->name, wd_seq_delay);
261+ pr_info("wd-%s-wd read-back delay of %lldns, clock-skew test skipped!\n",
262+ cs->name, wd_delay);
263+ return WD_READ_SKIP;
236264 }
237265
238266 static u64 csnow_mid;
@@ -356,6 +384,7 @@ static void clocksource_watchdog(struct timer_list *unused) · 117 unmodified lines
356384 int next_cpu, reset_pending;
357385 int64_t wd_nsec, cs_nsec;
358386 struct clocksource *cs;
387+ enum wd_read_status read_ret;
359388 u32 md;
360389
361390 spin_lock(&watchdog_lock);
@@ -373,9 +402,12 @@ static void clocksource_watchdog(struct timer_list *unused) · 11 unmodified lines
373402 continue;
374403 }
375404
376− if (!cs_watchdog_read(cs, &csnow, &wdnow)) {
377− /* Clock readout unreliable, so give it up. */
378− __clocksource_unstable(cs);
405+ read_ret = cs_watchdog_read(cs, &csnow, &wdnow);
406+
407+ if (read_ret != WD_READ_SUCCESS) {
408+ if (read_ret == WD_READ_UNSTABLE)
409+ /* Clock readout unreliable, so give it up. */
410+ __clocksource_unstable(cs);
379411 continue;
380412 }
381413