[PATCH 2/2] watchdog: softdog_rs: add Rust software watchdog driver

From: Artem Lytkin

Date: Mon Mar 23 2026 - 15:54:12 EST


Add a Rust software watchdog driver that uses the new Rust watchdog
abstraction. This demonstrates that the abstraction is functional and
can be used to write real watchdog drivers.

The driver implements start and stop operations. Unlike the C softdog,
this simplified version does not use hrtimers for the actual countdown
-- the watchdog core handles the timeout expiry and keepalive
management. This makes it suitable as a proof-of-concept driver for the
Rust watchdog abstraction.

The driver registers as "Rust Software Watchdog" with a default timeout
of 60 seconds, matching the C softdog's defaults.

The Kconfig option SOFT_WATCHDOG_RS depends on !SOFT_WATCHDOG to
prevent both drivers from being enabled simultaneously.

Signed-off-by: Artem Lytkin <iprintercanon@xxxxxxxxx>
---
drivers/watchdog/Kconfig | 12 +++++
drivers/watchdog/Makefile | 1 +
drivers/watchdog/softdog_rs.rs | 88 ++++++++++++++++++++++++++++++++++
3 files changed, 101 insertions(+)
create mode 100644 drivers/watchdog/softdog_rs.rs

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index d3b9df7d466b0..b7aad39f0de01 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -160,6 +160,18 @@ config SOFT_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called softdog.

+config SOFT_WATCHDOG_RS
+ tristate "Rust software watchdog"
+ depends on RUST && !SOFT_WATCHDOG
+ select WATCHDOG_CORE
+ help
+ A software watchdog driver written in Rust using the Rust watchdog
+ device abstraction. This is a simplified Rust equivalent of the
+ C softdog driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called softdog_rs.
+
config SOFT_WATCHDOG_PRETIMEOUT
bool "Software watchdog pretimeout governor support"
depends on SOFT_WATCHDOG && WATCHDOG_PRETIMEOUT_GOV
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index ba52099b12539..3039e5068f835 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -239,6 +239,7 @@ obj-$(CONFIG_MAX77620_WATCHDOG) += max77620_wdt.o
obj-$(CONFIG_NCT6694_WATCHDOG) += nct6694_wdt.o
obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o
obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
+obj-$(CONFIG_SOFT_WATCHDOG_RS) += softdog_rs.o
obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o
obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
diff --git a/drivers/watchdog/softdog_rs.rs b/drivers/watchdog/softdog_rs.rs
new file mode 100644
index 0000000000000..c8ff125e817bc
--- /dev/null
+++ b/drivers/watchdog/softdog_rs.rs
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust software watchdog driver.
+//!
+//! A simplified Rust implementation of the software watchdog, demonstrating
+//! the Rust watchdog device abstraction.
+
+use kernel::prelude::*;
+use kernel::watchdog;
+
+const DEFAULT_MARGIN: u32 = 60;
+const MAX_MARGIN: u32 = 65535;
+
+module! {
+ type: SoftdogModule,
+ name: "softdog_rs",
+ authors: ["Artem Lytkin"],
+ description: "Rust Software Watchdog Device Driver",
+ license: "GPL",
+}
+
+struct SoftdogOps;
+
+#[vtable]
+impl watchdog::WatchdogOps for SoftdogOps {
+ fn start(dev: &mut watchdog::Device) -> Result {
+ pr_info!("watchdog started (timeout={}s)\n", dev.timeout());
+ Ok(())
+ }
+
+ fn stop(_dev: &mut watchdog::Device) -> Result {
+ pr_info!("watchdog stopped\n");
+ Ok(())
+ }
+}
+
+static SOFTDOG_INFO: bindings::watchdog_info = bindings::watchdog_info {
+ options: bindings::WDIOF_SETTIMEOUT
+ | bindings::WDIOF_KEEPALIVEPING
+ | bindings::WDIOF_MAGICCLOSE,
+ firmware_version: 0,
+ identity: {
+ let mut id = [0u8; 32];
+ let s = b"Rust Software Watchdog";
+ let mut i = 0;
+ while i < s.len() {
+ id[i] = s[i];
+ i += 1;
+ }
+ id
+ },
+};
+
+static mut SOFTDOG_OPS: bindings::watchdog_ops =
+ watchdog::create_watchdog_ops::<SoftdogOps>();
+
+struct SoftdogModule {
+ _reg: watchdog::Registration,
+}
+
+impl kernel::Module for SoftdogModule {
+ fn init(module: &'static ThisModule) -> Result<Self> {
+ // SAFETY: SOFTDOG_OPS is only mutated here, before registration,
+ // and this function is called exactly once during module init.
+ let ops = unsafe { &mut *core::ptr::addr_of_mut!(SOFTDOG_OPS) };
+
+ let reg = watchdog::Registration::register(
+ module,
+ None,
+ &SOFTDOG_INFO,
+ ops,
+ DEFAULT_MARGIN,
+ 1,
+ MAX_MARGIN,
+ false,
+ )?;
+
+ pr_info!("initialized (timeout={}s)\n", DEFAULT_MARGIN);
+
+ Ok(SoftdogModule { _reg: reg })
+ }
+}
+
+impl Drop for SoftdogModule {
+ fn drop(&mut self) {
+ pr_info!("exit\n");
+ }
+}
--
2.43.0