diff --git a/patches-sonic/0023-armhf-armada38x-disable-HW-UIE.patch b/patches-sonic/0023-armhf-armada38x-disable-HW-UIE.patch new file mode 100644 index 000000000..1e6cd0168 --- /dev/null +++ b/patches-sonic/0023-armhf-armada38x-disable-HW-UIE.patch @@ -0,0 +1,81 @@ +From f0c0f9d33c8b0362f270e73d1f87554d8a80f832 Mon Sep 17 00:00:00 2001 +From: Ioannis Fountzoulas +Date: Thu, 9 Jul 2026 05:38:41 -0400 +Subject: [PATCH] rtc: armada38x: do not advertise update interrupt (UIE) + support + +Problem: +chrony enables RTC update interrupts via the RTC_UIE_ON ioctl to track +RTC drift. On the armada38x driver this request is served by the RTC +core's native path, which arms a 1 second periodic timer that is +re-programmed on the alarm and serviced by rtc_timer_do_work(). +If the RTC time is then stepped forward by a large amount while this +timer is active, its scheduled expiry ends up far in the past compared +to the freshly read time. + +Why the CPU hangs: +When rtc_timer_do_work() runs, it expires every timer whose expiry is +not in the future, advancing periodic timers by one period each pass: + while ((next = timerqueue_getnext(&rtc->timerqueue))) { + if (next->expires > now) + break; + ... + timer->node.expires += timer->period; /* += 1s */ + timerqueue_add(&rtc->timerqueue, &timer->node); + } +With a large forward step (seen when the RTC starts far in the past and +chrony corrects it after the first NTP sync), the periodic UIE timer is +overdue by the size of the jump, so this loop must run one iteration per +elapsed second before it can exit. +It never yields in that time, so the workqueue worker pins the CPU and +the watchdog reports a soft lockup / RCU stall, after which the +board reboots: + watchdog: BUG: soft lockup - CPU#1 stuck for 48s! [kworker/1:3:432] + Kernel panic - not syncing: softlockup: hung tasks + Workqueue: events rtc_timer_do_work + rtc_handle_legacy_irq from rtc_timer_do_work + rtc_timer_do_work from process_one_work + process_one_work from worker_thread + +Fix: +Clear RTC_FEATURE_UPDATE_INTERRUPT at probe time so the driver stops +advertising native UIE. RTC_UIE_ON is then served by the poll-based UIE +emulation in rtc-dev (CONFIG_RTC_INTF_DEV_UIE_EMUL), which delivers the +1 Hz update notifications chrony needs without ever queuing the runaway +periodic timer. + +Testing: +Tested on a Marvell Armada 38x board (ARM Cortex-A9). Before the change, +stepping the clock forward while UIE was enabled reproduced the soft +lockup (about 1 in 4 boots). After the change, rtc_timer_do_work() runs +zero loop iterations and returns immediately, chrony still receives +update interrupts via emulation, and no lockups occur over repeated +reboot cycles. + +Signed-off-by: Ioannis Fountzoulas +--- + drivers/rtc/rtc-armada38x.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c +index 569c1054..2e9b7281 100644 +--- a/drivers/rtc/rtc-armada38x.c ++++ b/drivers/rtc/rtc-armada38x.c +@@ -531,6 +531,14 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) + else + clear_bit(RTC_FEATURE_ALARM, rtc->rtc_dev->features); + ++ /* ++ * A large forward step of the RTC time makes ++ * rtc_timer_do_work() replay one period per elapsed second and can ++ * loop long enough to trigger a soft lockup. Do not advertise ++ * native UIE; RTC_UIE_ON then uses the poll-based emulation. ++ */ ++ clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtc_dev->features); ++ + /* Update RTC-MBUS bridge timing parameters */ + rtc->data->update_mbus_timing(rtc); + +-- +2.34.1 + diff --git a/patches-sonic/series b/patches-sonic/series index d8f1128b5..cc9ec902c 100644 --- a/patches-sonic/series +++ b/patches-sonic/series @@ -165,6 +165,7 @@ cisco-npu-disable-other-bars.patch 0018-drivers-i2c-fix-after-kdump-crash.patch 0019-irqchip-mvebu-gicp-Clear-pending-interrupts-on-init.patch 0022-arm64-dts-marvell-Add-DTS-for-cn9131-db-comexpress-trixie.patch +0023-armhf-armada38x-disable-HW-UIE.patch # amd-pensando elba support 0001-Add-support-for-the-TI-TPS53659.patch