From nobody Sat Jun 13 23:25:12 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 228092773C3; Sat, 13 Jun 2026 14:33:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781361183; cv=none; b=FjoNdbn0nColCfW3Hp85xcaJsatZJhPgwoY/7Z716lbYEy7Ynnp3c7uxmEzMzHUA+EdrW2313R6XX5JgT8NDyp1nl5qJOTJz4aS88ouEj+cbgkEdocH3itsZU8fNs//VNGExkk9WzaTFZiSiJHLLKmERN1iIG9ZshDf1HVIZmy8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781361183; c=relaxed/simple; bh=f8iQpGSyRcCnaV6K+oGr8islthkBnAWJ7aX2wHLSpXQ=; h=Date:From:To:Subject:Cc:In-Reply-To:References:MIME-Version: Message-ID:Content-Type; b=SSfy1TwSIqr63AKCjYo+UIRbbiRJtAOXiIGGnEAOllyrTcJ/8Cl64x+9CGkSFBHh1AeiBvezUEGBkl+gOMBEmjrooDpe91IZxmMDI/GKB7NvHCxH0zrbEhcdZ26Xm26BToTY0LodjaZY5EC+AwpN7XA/JY2eCZkqTKhSVEr1rIg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=x/mNgir/; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=TiDUM3T4; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="x/mNgir/"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="TiDUM3T4" Date: Sat, 13 Jun 2026 14:32:59 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1781361180; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WKYVzn++Pjmx6y5U+eFJzOBPp+FCa1U3hplU+S3l3ow=; b=x/mNgir/uHhucLELkjBH4QutwT5cTtgg/3RoknPTvlGpdnP7BzSP76V9CFP00THt1HZR9j +YkkEOn15fLH5o0G22ierAjofrlDdD3DoeQ8kl7LwzWcMeJDxCMI6hTwTcX9jlSr09jhYd 6sSpSIREvj/KB6Bh6I8zszFlBvG2Ylefa5op5sOD/nxavicf5m0Xx5qgnzXgdygj9k/gdd 4STZP6+LcCvd5OcE07UxoXGem1KM/aJLy9Q7TnS4RDKrFe1UGWX5w08DEVahECCg7FNNHf 0GcZ/xLoAYr1o00PYFH9IclAlV00QI0XRWpDRGx24Xd9YQq3vnvu6QRcifartg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1781361180; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WKYVzn++Pjmx6y5U+eFJzOBPp+FCa1U3hplU+S3l3ow=; b=TiDUM3T42X1bPda876uOwHMk7aog9rtFp9noyFLNsa2B1K+BAeoPB0bvRj3kfegckxVHPX B4Yv6sRoOUruZmAA== From: "tip-bot2 for Kartik Rajput" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: timers/clocksource] clocksource/drivers/timer-tegra186: Reserve and service a kernel watchdog Cc: Kartik Rajput , Daniel Lezcano , Jon Hunter , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20260507154557.2082697-5-kkartik@nvidia.com> References: <20260507154557.2082697-5-kkartik@nvidia.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <178136117934.1650852.10397009451239786355.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Precedence: bulk Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The following commit has been merged into the timers/clocksource branch of = tip: Commit-ID: 46fb093b87a0d92e391b6f6cadd63c3ef50a59b2 Gitweb: https://git.kernel.org/tip/46fb093b87a0d92e391b6f6cadd63c3ef= 50a59b2 Author: Kartik Rajput AuthorDate: Thu, 07 May 2026 21:15:57 +05:30 Committer: Daniel Lezcano CommitterDate: Wed, 10 Jun 2026 07:25:54 +02:00 clocksource/drivers/timer-tegra186: Reserve and service a kernel watchdog Tegra SoCs supports multiple watchdog timers. If the kernel crashes or hangs before userspace enables a watchdog, the system cannot recover and may remain bricked, e.g. after a failed OTA update. The driver currently leaves all watchdogs disabled until userspace configures them. Reserve first available watchdog as a kernel-only watchdog for Tegra186 and Tegra234. Arm it during probe (120s timeout) and keep it alive in the driver IRQ handler. Do not register it to userspace. Other available watchdogs remain exposed to userspace. This guarantees the system can reset itself in case of a hang or crash even when userspace never starts. Signed-off-by: Kartik Rajput Signed-off-by: Daniel Lezcano Reviewed-by: Jon Hunter Link: https://patch.msgid.link/20260507154557.2082697-5-kkartik@nvidia.com --- drivers/clocksource/timer-tegra186.c | 62 +++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/drivers/clocksource/timer-tegra186.c b/drivers/clocksource/tim= er-tegra186.c index dd1d1a0..78600dd 100644 --- a/drivers/clocksource/timer-tegra186.c +++ b/drivers/clocksource/timer-tegra186.c @@ -57,6 +57,8 @@ #define WDTUR 0x00c #define WDTUR_UNLOCK_PATTERN 0x0000c45a =20 +#define TEGRA186_KERNEL_WDT_TIMEOUT 120 + /* WDT security configuration registers */ #define WDTSCR(x) (0xf02c + (x) * 4) #define WDTSCR_SEC_WEN BIT(28) @@ -82,6 +84,7 @@ struct tegra186_wdt { void __iomem *regs; unsigned int index; bool locked; + bool is_kernel_wdt; =20 struct tegra186_tmr *tmr; }; @@ -182,6 +185,10 @@ static void tegra186_wdt_enable(struct tegra186_wdt *w= dt) value &=3D ~WDTCR_PERIOD_MASK; value |=3D WDTCR_PERIOD(1); =20 + /* enable local interrupt for kernel watchdog */ + if (wdt->is_kernel_wdt) + value |=3D WDTCR_LOCAL_INT_ENABLE; + /* enable system POR reset */ value |=3D WDTCR_SYSTEM_POR_RESET_ENABLE; =20 @@ -219,6 +226,16 @@ static int tegra186_wdt_ping(struct watchdog_device *w= dd) return 0; } =20 +static irqreturn_t tegra186_wdt_irq(int irq, void *data) +{ + struct tegra186_wdt *wdt =3D data; + + tegra186_wdt_disable(wdt); + tegra186_wdt_enable(wdt); + + return IRQ_HANDLED; +} + static int tegra186_wdt_set_timeout(struct watchdog_device *wdd, unsigned int timeout) { @@ -361,10 +378,6 @@ static struct tegra186_wdt *tegra186_wdt_create(struct= tegra186_timer *tegra, if (err < 0) return ERR_PTR(err); =20 - err =3D devm_watchdog_register_device(tegra->dev, &wdt->base); - if (err < 0) - return ERR_PTR(err); - return wdt; } =20 @@ -446,9 +459,11 @@ static int tegra186_timer_usec_init(struct tegra186_ti= mer *tegra) =20 static int tegra186_timer_probe(struct platform_device *pdev) { + struct tegra186_wdt *kernel_wdt =3D NULL; struct device *dev =3D &pdev->dev; struct tegra186_timer *tegra; unsigned int i; + int irq; int err; =20 tegra =3D devm_kzalloc(dev, sizeof(*tegra), GFP_KERNEL); @@ -467,6 +482,8 @@ static int tegra186_timer_probe(struct platform_device = *pdev) if (err < 0) return err; =20 + irq =3D err; + tegra->wdts =3D devm_kcalloc(dev, tegra->soc->num_wdts, sizeof(*tegra->wd= ts), GFP_KERNEL); if (!tegra->wdts) return -ENOMEM; @@ -481,6 +498,17 @@ static int tegra186_timer_probe(struct platform_device= *pdev) if (IS_ERR(tegra->wdts[i])) return dev_err_probe(dev, PTR_ERR(tegra->wdts[i]), "failed to create WDT%u\n", i); + + /* Reserve the first accessible WDT for the Kernel. */ + if (!kernel_wdt) { + kernel_wdt =3D tegra->wdts[i]; + kernel_wdt->is_kernel_wdt =3D true; + } else { + err =3D devm_watchdog_register_device(dev, &tegra->wdts[i]->base); + if (err < 0) + return dev_err_probe(dev, err, + "failed to register WDT%u\n", i); + } } =20 err =3D tegra186_timer_tsc_init(tegra); @@ -501,8 +529,22 @@ static int tegra186_timer_probe(struct platform_device= *pdev) goto unregister_osc; } =20 + if (kernel_wdt) { + err =3D devm_request_irq(dev, irq, tegra186_wdt_irq, 0, + dev_name(dev), kernel_wdt); + if (err < 0) { + dev_err(dev, "failed to request kernel WDT IRQ: %d\n", err); + goto unregister_usec; + } + + tegra186_wdt_set_timeout(&kernel_wdt->base, TEGRA186_KERNEL_WDT_TIMEOUT); + tegra186_wdt_enable(kernel_wdt); + } + return 0; =20 +unregister_usec: + clocksource_unregister(&tegra->usec); unregister_osc: clocksource_unregister(&tegra->osc); unregister_tsc: @@ -525,8 +567,10 @@ static int __maybe_unused tegra186_timer_suspend(struc= t device *dev) unsigned int i; =20 for (i =3D 0; i < tegra->soc->num_wdts; i++) { - if (tegra->wdts[i] && watchdog_active(&tegra->wdts[i]->base)) - tegra186_wdt_disable(tegra->wdts[i]); + struct tegra186_wdt *wdt =3D tegra->wdts[i]; + + if (wdt && (wdt->is_kernel_wdt || watchdog_active(&wdt->base))) + tegra186_wdt_disable(wdt); } =20 return 0; @@ -538,8 +582,10 @@ static int __maybe_unused tegra186_timer_resume(struct= device *dev) unsigned int i; =20 for (i =3D 0; i < tegra->soc->num_wdts; i++) { - if (tegra->wdts[i] && watchdog_active(&tegra->wdts[i]->base)) - tegra186_wdt_enable(tegra->wdts[i]); + struct tegra186_wdt *wdt =3D tegra->wdts[i]; + + if (wdt && (wdt->is_kernel_wdt || watchdog_active(&wdt->base))) + tegra186_wdt_enable(wdt); } =20 return 0;