Watchdog Timeout Pretimeout Ioctls-Free Linux Device Drivers Training Online

PREV_LEC | NEXT_LEC

Watchdog Timeout Pretimeout Ioctls

Querying watchdog capabilities and identity, then reading and setting timeout, pretimeout, and time-left values from user space

Chapter 13 · Lecture 6
Watchdog Device Drivers
Free Linux Kernel Course

Once your supervisor can open, ping, and cleanly stop a watchdog, the next question in any real deployment is: what can this particular watchdog actually do, and how much time is really left before it fires? Not every driver supports every feature — some hardware watchdogs have a fixed timeout burned into silicon, others let you tune it on the fly, and only some support a pretimeout warning before the reset. This lecture in our free linux device drivers course covers the ioctl set that answers those questions: capability discovery, timeout get/set, pretimeout get/set, and time-left queries. Getting this right is what separates a watchdog client that merely compiles from one that behaves correctly across different hardware in a free embedded systems course style product line.

watchdog_info struct WDIOC_GETSUPPORT WDIOC_SETTIMEOUT WDIOC_SETPRETIMEOUT free linux kernel development course free linux development course

What You Will Learn

Reading watchdog identity and capability flags Gating features on advertised WDIOF_* flags before using them Getting and setting the timeout at runtime Getting and setting the pretimeout warning Querying time left before a reset Building an original watchdog inspection tool

Prerequisites

Comfortable opening, pinging, and closing /dev/watchdog (previous lecture) Familiar with the watchdog_ops callback table from earlier in this chapter Basic ioctl() usage in C

Discovering Capabilities With WDIOC_GETSUPPORT

Every watchdog driver is required to fill in a struct watchdog_info, and user space can read a copy of it with the WDIOC_GETSUPPORT ioctl. This struct is the single source of truth for what a given watchdog node can do — its human-readable identity string, an optional firmware version number, and an options bitmask of WDIOF_* flags describing supported features. A disciplined client always checks this before touching timeout or pretimeout ioctls, rather than assuming every driver behaves the same way.

struct watchdog_info info;

if (ioctl(wdfd, WDIOC_GETSUPPORT, &info) == -1) {
    fprintf(stderr, "ep_wdt_info: GETSUPPORT failed: %s\n", strerror(errno));
    exit(EXIT_FAILURE);
}

printf("identity        : %s\n", info.identity);
printf("firmware_version: %u\n", info.firmware_version);
printf("options bitmask : 0x%08x\n", info.options);

The bitmask is then tested field by field against the flags you actually depend on:

if (info.options & WDIOF_KEEPALIVEPING)
    printf("supports keep-alive pings\n");

if (info.options & WDIOF_SETTIMEOUT)
    printf("supports runtime timeout changes\n");

if (info.options & WDIOF_PRETIMEOUT)
    printf("supports pretimeout warning\n");
FlagMeaning
WDIOF_KEEPALIVEPINGDriver accepts keep-alive pings via write or WDIOC_KEEPALIVE
WDIOF_SETTIMEOUTTimeout can be changed at runtime via WDIOC_SETTIMEOUT
WDIOF_PRETIMEOUTDriver supports a pretimeout warning before the actual reset
WDIOF_MAGICCLOSEDriver honours the magic ‘V’ close sequence from the previous lecture

Getting and Setting the Timeout

If WDIOF_SETTIMEOUT is set, the driver exposes a .set_timeout callback, and you can adjust the countdown length at runtime with WDIOC_SETTIMEOUT. The value you pass is in whole seconds, but hardware limitations mean the value the driver actually applies can differ from what you asked for — always re-read the same variable after the call rather than assuming your request was honoured exactly.

int timeout = 45;

if (ioctl(wdfd, WDIOC_SETTIMEOUT, &timeout) == -1)
    fprintf(stderr, "ep_wdt_info: SETTIMEOUT failed: %s\n", strerror(errno));
else
    printf("timeout applied by hardware: %d seconds\n", timeout);

To simply read the current value without changing anything, use WDIOC_GETTIMEOUT:

int current_timeout;
ioctl(wdfd, WDIOC_GETTIMEOUT, &current_timeout);
printf("current timeout: %d seconds\n", current_timeout);

Getting and Setting the Pretimeout

A pretimeout is an earlier warning point before the actual reset — useful for logging state, flushing storage, or alerting an operator in the last few seconds before the hard reset happens. It requires the driver to advertise WDIOF_PRETIMEOUT and provide a .set_pretimeout callback. The value is set with WDIOC_SETPRETIMEOUT, and must be strictly between zero and the current timeout — a value of zero or one that is not smaller than the timeout returns -EINVAL.

int pretimeout = 10;

if (ioctl(wdfd, WDIOC_SETPRETIMEOUT, &pretimeout) == -1) {
    if (errno == EINVAL)
        fprintf(stderr, "ep_wdt_info: pretimeout must be 0 < p < timeout\n");
    else
        fprintf(stderr, "ep_wdt_info: SETPRETIMEOUT failed: %s\n", strerror(errno));
}
Timeout vs Pretimeout Relationship
0s ———————- pretimeout ———————- timeout
| | |
watchdog armed pretimeout event hard reset fires
(warning window opens) (if never serviced)

Checking the Time Left

Beyond the static timeout value, WDIOC_GETTIMELEFT answers a more dynamic question: right now, how many seconds remain before this watchdog resets the board if nobody pings it again? This is invaluable for diagnostics and for supervisors that want to log a warning if the remaining time ever drops below a safety margin. Support for this ioctl depends on the driver providing a .get_timeleft() callback — if it does not, the call fails with EOPNOTSUPP rather than returning a wrong number.

int timeleft;

if (ioctl(wdfd, WDIOC_GETTIMELEFT, &timeleft) == -1) {
    if (errno == EOPNOTSUPP)
        printf("this driver does not report time left\n");
    else
        fprintf(stderr, "ep_wdt_info: GETTIMELEFT failed: %s\n", strerror(errno));
} else {
    printf("time left before reset: %d seconds\n", timeleft);
}

Building ep_wdt_status: A Watchdog Inspection Tool

The following original tool combines everything above into a single diagnostic pass: identity, capabilities, current timeout, and time left — printing “n/a” for anything the driver does not support instead of guessing.

// ep_wdt_status.c — watchdog capability and status inspector
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/watchdog.h>

int main(int argc, char *argv[])
{
    const char *node = (argc > 1) ? argv[1] : "/dev/watchdog0";
    int fd = open(node, O_RDWR);

    if (fd == -1) {
        fprintf(stderr, "ep_wdt_status: open(%s): %s\n", node, strerror(errno));
        return EXIT_FAILURE;
    }

    struct watchdog_info info;
    if (ioctl(fd, WDIOC_GETSUPPORT, &info) == 0) {
        printf("identity : %s\n", info.identity);
        printf("firmware : %u\n", info.firmware_version);
        printf("keepalive: %s\n", (info.options & WDIOF_KEEPALIVEPING) ? "yes" : "no");
        printf("settimeout: %s\n", (info.options & WDIOF_SETTIMEOUT) ? "yes" : "no");
        printf("pretimeout: %s\n", (info.options & WDIOF_PRETIMEOUT) ? "yes" : "no");
    }

    int timeout;
    if (ioctl(fd, WDIOC_GETTIMEOUT, &timeout) == 0)
        printf("timeout  : %d s\n", timeout);
    else
        printf("timeout  : n/a\n");

    int timeleft;
    if (ioctl(fd, WDIOC_GETTIMELEFT, &timeleft) == 0)
        printf("timeleft : %d s\n", timeleft);
    else
        printf("timeleft : n/a (EOPNOTSUPP)\n");

    close(fd);
    return EXIT_SUCCESS;
}
Build and Run
$ gcc -o ep_wdt_status ep_wdt_status.c
$ sudo ./ep_wdt_status /dev/watchdog0
identity : ep_swwdt
firmware : 0
keepalive: yes
settimeout: yes
pretimeout: no
timeout : 30 s
timeleft : n/a (EOPNOTSUPP)

Common Mistakes and Troubleshooting

Calling SETTIMEOUT without checking WDIOF_SETTIMEOUT

Some drivers have a fixed hardware timeout; blindly calling the ioctl on those wastes an error path you should have avoided by checking the flag first.

Assuming the requested timeout was applied exactly

Hardware granularity can round your requested value; always re-read the variable after WDIOC_SETTIMEOUT returns.

Setting a pretimeout equal to or above the timeout

This always returns -EINVAL — the pretimeout must be strictly smaller than the current timeout.

Treating EOPNOTSUPP on GETTIMELEFT as a fatal error

It simply means the driver has no .get_timeleft() callback — handle it gracefully rather than aborting the supervisor.

Best Practices

Always query WDIOC_GETSUPPORT once at startup and cache the flags Gate every optional ioctl behind its corresponding WDIOF_* flag Re-read timeout after setting it, never assume the requested value stuck Use pretimeout, when available, to flush logs before a hard reset Log GETTIMELEFT periodically in long-running services for early warning

Performance Considerations

All of these ioctls are cheap, synchronous kernel calls with no meaningful overhead — there is no performance reason to avoid querying capabilities or time left frequently. The only real cost is polling too aggressively for no benefit; querying time left once every few seconds in a supervisor loop is more than sufficient.

Summary and Key Takeaways

The watchdog_info struct returned by WDIOC_GETSUPPORT is the authoritative description of what a given watchdog node can do, and every optional ioctl — timeout changes, pretimeout, time-left queries — should be gated on its corresponding WDIOF_* flag rather than assumed. Timeout and pretimeout can both be read and adjusted at runtime within the constraints the hardware allows, and WDIOC_GETTIMELEFT gives a live countdown for diagnostics. Together with the open/stop/ping lifecycle from the previous lecture, this completes the full user-space contract for building a correct watchdog supervisor.

Frequently Asked Questions

What does WDIOC_GETSUPPORT actually return?

It fills a struct watchdog_info with the driver’s identity string, firmware version, and a bitmask of supported WDIOF_* capability flags.

Why did my WDIOC_SETTIMEOUT value come back different from what I requested?

Hardware timing granularity means the driver may round your requested value to the nearest value it can actually apply; always re-read it after the call.

Why does WDIOC_SETPRETIMEOUT return -EINVAL?

The pretimeout value must be greater than zero and strictly smaller than the current timeout, or the kernel rejects it.

What does EOPNOTSUPP mean on WDIOC_GETTIMELEFT?

It means the driver did not implement a .get_timeleft() callback, so time-left reporting simply is not available on that device.

Should I check capability flags before calling every ioctl?

Yes — not all watchdog drivers support timeout changes or pretimeout, and checking WDIOF_* flags first avoids relying on undefined behaviour.

Can I use these ioctls on any Linux watchdog driver?

The ioctl interface itself is generic and part of the watchdog framework, but which specific ioctls succeed depends entirely on the capabilities that particular driver advertises.

Continue the Free Linux Kernel Development Course

Next: the last reboot reason and diagnosing whether the watchdog caused a reset.

Next Lecture Back to Course Index

PREV_LEC | NEXT_LEC

Leave a Reply

Your email address will not be published. Required fields are marked *