public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: "Markus Stockhausen" <markus.stockhausen@gmx.de>,
	"Daniel Lezcano" <daniel.lezcano@linaro.org>,
	"Stephen Howell" <howels@allthatwemight.be>,
	"Bjørn Mork" <bjorn@mork.no>, "Sasha Levin" <sashal@kernel.org>,
	tglx@linutronix.de, linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.17-6.12] clocksource/drivers/timer-rtl-otto: Do not interfere with interrupts
Date: Thu,  9 Oct 2025 11:56:15 -0400	[thread overview]
Message-ID: <20251009155752.773732-109-sashal@kernel.org> (raw)
In-Reply-To: <20251009155752.773732-1-sashal@kernel.org>

From: Markus Stockhausen <markus.stockhausen@gmx.de>

[ Upstream commit c445bffbf28f721e05d0ce06895045fc62aaff7c ]

During normal operation the timers are reprogrammed including an
interrupt acknowledgement. This has no effect as the whole timer
is setup from scratch afterwards. Especially in an interrupt this
has already been done by rttm_timer_interrupt().

Change the behaviour as follows:

- Use rttm_disable_timer() during reprogramming
- Keep rttm_stop_timer() for all other use cases.

Downstream has already tested and confirmed a patch. See
https://github.com/openwrt/openwrt/pull/19468
https://forum.openwrt.org/t/support-for-rtl838x-based-managed-switches/57875/3788

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Stephen Howell <howels@allthatwemight.be>
Tested-by: Bjørn Mork <bjorn@mork.no>
Link: https://lore.kernel.org/r/20250804080328.2609287-4-markus.stockhausen@gmx.de
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

YES

- What it fixes
  - The driver was acknowledging the interrupt (“W1C” PENDING bit) as
    part of routine timer reprogramming, not just in the interrupt
    handler. That read-modify-write ack can race with new pending
    interrupts and clear them, leading to occasional lost timer
    interrupts. The change confines IRQ acknowledgement to the interrupt
    handler and explicit stop/shutdown paths, preventing interference
    with in-flight or newly arriving interrupts.

- Exact code changes
  - In the reprogramming paths, `rttm_stop_timer()` (which disables the
    timer and acks the IRQ) is replaced with `rttm_disable_timer()`
    (disable only), so the PENDING bit is no longer touched during
    normal reprogramming:
    - `drivers/clocksource/timer-rtl-otto.c:141-146` changes
      reprogramming for oneshot next-event (now disable → set period →
      start, without ack).
    - `drivers/clocksource/timer-rtl-otto.c:153-159` changes
      `rttm_state_oneshot()` similarly.
    - `drivers/clocksource/timer-rtl-otto.c:166-172` changes
      `rttm_state_periodic()` similarly.
  - IRQ acknowledgement remains where it belongs:
    - Interrupt handler acks before invoking the event handler:
      `drivers/clocksource/timer-rtl-otto.c:97-106` and specifically the
      ack helper at `drivers/clocksource/timer-rtl-otto.c:77-80`.
    - Stop/shutdown/init paths still ack via `rttm_stop_timer()`:
      - Shutdown: `drivers/clocksource/timer-rtl-otto.c:175-182`
      - Setup: `drivers/clocksource/timer-rtl-otto.c:185-190`
      - `rttm_stop_timer()` itself still does disable + ack:
        `drivers/clocksource/timer-rtl-otto.c:125-129`.

- Why the original behavior is problematic
  - The ack function is implemented as a read-modify-write to a W1C bit:
    `ioread32(base + RTTM_INT) | RTTM_INT_PENDING` followed by a write
    (`drivers/clocksource/timer-rtl-otto.c:77-80`). If a new interrupt
    becomes pending between the read and the write, the write will still
    set the PENDING bit in the value and clear it on write, effectively
    dropping that freshly latched interrupt. Calling this sequence
    outside the ISR (e.g., during reprogramming) can therefore interfere
    with normal interrupt delivery.

- Why this change is safe
  - In-ISR reprogramming: The handler already acknowledges the interrupt
    at entry (`drivers/clocksource/timer-rtl-otto.c:102`). Removing a
    second ack during reprogramming eliminates a window where a new
    pending interrupt could be inadvertently cleared.
  - Non-ISR reprogramming: If a pending bit exists, not acking ensures
    it will be properly handled by the ISR when it fires, rather than
    being silently cleared by a stray reprogramming ack.
  - Ack is still performed at shutdown/setup where it is appropriate to
    clear stale state (`drivers/clocksource/timer-rtl-otto.c:175-190`),
    so there is no accumulation of stale flags.

- Context and related fixes
  - This change is part of a small, focused series addressing timer
    reliability on Realtek Otto platforms:
    - “Work around dying timers” added `rttm_bounce_timer()` to avoid
      reprogramming in a critical ~5us window before expiry (hardware
      peculiarity) and is used directly before reprogramming in all the
      altered paths (`drivers/clocksource/timer-rtl-otto.c:109-123` and
      calls at 141, 154, 167).
    - “Drop set_counter” cleaned up a no-op write to the current
      counter.
  - The series was tested downstream (OpenWrt) and carries multiple
    Tested-by tags; the commit under review also notes downstream
    confirmation.

- Backport considerations
  - Scope: Single driver file; changes are three substitutions of
    `rttm_stop_timer()` with `rttm_disable_timer()` in reprogramming
    paths. No functional/ABI changes outside this driver.
  - Dependencies: None strict. If a stable branch does not yet have
    `rttm_bounce_timer()`, the underlying correctness argument for using
    `rttm_disable_timer()` instead of `rttm_stop_timer()` during
    reprogramming still holds. For branches already including the bounce
    patch (as in newer stables), this applies cleanly.
  - Risk: Low. Potential for an extra immediate interrupt if a PENDING
    bit remained set is mitigated because the ISR acks and the
    clockevents layer tolerates such re-entries; conversely, the change
    removes a race that could drop interrupts, which is more severe.

- Stable policy fit
  - Fixes a real bug affecting users (lost or interfered interrupts on
    rtl-otto platforms).
  - Small, contained, and without architectural changes.
  - Confined to `drivers/clocksource/timer-rtl-otto.c`.
  - Already tested downstream and reviewed/merged upstream (commit
    c445bffbf28f7).
  - While there is no explicit “Cc: stable” in the commit message, the
    change meets stable backport criteria and aligns with the prior
    reliability fix series for this driver.

Conclusion: Backporting this patch reduces the risk of lost timer
interrupts by avoiding unnecessary and racy IRQ acknowledgements during
reprogramming, with minimal regression risk and limited scope.

 drivers/clocksource/timer-rtl-otto.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/timer-rtl-otto.c b/drivers/clocksource/timer-rtl-otto.c
index 8be45a11fb8b6..24c4aa6a30131 100644
--- a/drivers/clocksource/timer-rtl-otto.c
+++ b/drivers/clocksource/timer-rtl-otto.c
@@ -147,7 +147,7 @@ static int rttm_next_event(unsigned long delta, struct clock_event_device *clkev
 
 	RTTM_DEBUG(to->of_base.base);
 	rttm_bounce_timer(to->of_base.base, RTTM_CTRL_COUNTER);
-	rttm_stop_timer(to->of_base.base);
+	rttm_disable_timer(to->of_base.base);
 	rttm_set_period(to->of_base.base, delta);
 	rttm_start_timer(to, RTTM_CTRL_COUNTER);
 
@@ -160,7 +160,7 @@ static int rttm_state_oneshot(struct clock_event_device *clkevt)
 
 	RTTM_DEBUG(to->of_base.base);
 	rttm_bounce_timer(to->of_base.base, RTTM_CTRL_COUNTER);
-	rttm_stop_timer(to->of_base.base);
+	rttm_disable_timer(to->of_base.base);
 	rttm_set_period(to->of_base.base, RTTM_TICKS_PER_SEC / HZ);
 	rttm_start_timer(to, RTTM_CTRL_COUNTER);
 
@@ -173,7 +173,7 @@ static int rttm_state_periodic(struct clock_event_device *clkevt)
 
 	RTTM_DEBUG(to->of_base.base);
 	rttm_bounce_timer(to->of_base.base, RTTM_CTRL_TIMER);
-	rttm_stop_timer(to->of_base.base);
+	rttm_disable_timer(to->of_base.base);
 	rttm_set_period(to->of_base.base, RTTM_TICKS_PER_SEC / HZ);
 	rttm_start_timer(to, RTTM_CTRL_TIMER);
 
-- 
2.51.0


  parent reply	other threads:[~2025-10-09 16:01 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20251009155752.773732-1-sashal@kernel.org>
2025-10-09 15:54 ` [PATCH AUTOSEL 6.17-6.12] clocksource/drivers/timer-rtl-otto: Work around dying timers Sasha Levin
2025-10-09 15:54 ` [PATCH AUTOSEL 6.17-6.16] soc: ti: k3-socinfo: Add information for AM62L SR1.1 Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-5.4] uprobe: Do not emulate/sstep original instruction when ip is changed Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-5.4] cpufreq/longhaul: handle NULL policy in longhaul_exit Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-6.1] irqchip/loongson-pch-lpc: Use legacy domain for PCH-LPC IRQ controller Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-6.16] irqchip/loongson-eiointc: Route interrupt parsed from bios table Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-6.1] irqchip/sifive-plic: Respect mask state when setting affinity Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-5.4] clocksource/drivers/vf-pit: Replace raw_readl/writel to readl/writel Sasha Levin
2025-10-09 15:56 ` [PATCH AUTOSEL 6.17-5.10] soc: ti: pruss: don't use %pK through printk Sasha Levin
2025-10-09 15:56 ` Sasha Levin [this message]
2025-10-09 15:56 ` [PATCH AUTOSEL 6.17-5.4] irqchip/gic-v2m: Handle Multiple MSI base IRQ Alignment Sasha Levin
2025-10-09 15:56 ` [PATCH AUTOSEL 6.17-6.1] futex: Don't leak robust_list pointer on exec race Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251009155752.773732-109-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=bjorn@mork.no \
    --cc=daniel.lezcano@linaro.org \
    --cc=howels@allthatwemight.be \
    --cc=linux-kernel@vger.kernel.org \
    --cc=markus.stockhausen@gmx.de \
    --cc=patches@lists.linux.dev \
    --cc=stable@vger.kernel.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox