Skip to content

Commit b0fd1f5

Browse files
groeckWim Van Sebroeck
authored andcommitted
watchdog: Always return time left until watchdog times out
The watchdog core knows when the most recent keepalive was sent. It also knows the configured timeout. With that, it can always calculate and return the time left until a watchdog times out, even if its driver does not support it. Convert watchdog_get_timeleft() into a void function. It never returns an error after this patch is applied, so the error checks in the calling code are now pointless and can be removed. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Reviewed-by: Wim Van Sebroeck <wim@linux-watchdog.org> Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
1 parent 0bf75b9 commit b0fd1f5

1 file changed

Lines changed: 15 additions & 20 deletions

File tree

drivers/watchdog/watchdog_dev.c

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -424,20 +424,22 @@ static int watchdog_set_pretimeout(struct watchdog_device *wdd,
424424
*
425425
* Get the time before a watchdog will reboot (if not pinged).
426426
* The caller must hold wd_data->lock.
427-
*
428-
* Return: 0 if successful, error otherwise.
429427
*/
430-
static int watchdog_get_timeleft(struct watchdog_device *wdd,
431-
unsigned int *timeleft)
428+
static void watchdog_get_timeleft(struct watchdog_device *wdd,
429+
unsigned int *timeleft)
432430
{
433431
*timeleft = 0;
434432

435-
if (!wdd->ops->get_timeleft)
436-
return -EOPNOTSUPP;
437-
438-
*timeleft = wdd->ops->get_timeleft(wdd);
433+
if (wdd->ops->get_timeleft) {
434+
*timeleft = wdd->ops->get_timeleft(wdd);
435+
} else {
436+
struct watchdog_core_data *wd_data = wdd->wd_data;
437+
s64 last_keepalive_ms = ktime_ms_delta(ktime_get(), wd_data->last_keepalive);
438+
s64 last_keepalive = DIV_ROUND_UP_ULL(last_keepalive_ms, 1000);
439439

440-
return 0;
440+
if (wdd->timeout > last_keepalive)
441+
*timeleft = wdd->timeout - last_keepalive;
442+
}
441443
}
442444

443445
#ifdef CONFIG_WATCHDOG_SYSFS
@@ -499,16 +501,13 @@ static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr,
499501
{
500502
struct watchdog_device *wdd = dev_get_drvdata(dev);
501503
struct watchdog_core_data *wd_data = wdd->wd_data;
502-
ssize_t status;
503504
unsigned int val;
504505

505506
mutex_lock(&wd_data->lock);
506-
status = watchdog_get_timeleft(wdd, &val);
507+
watchdog_get_timeleft(wdd, &val);
507508
mutex_unlock(&wd_data->lock);
508-
if (!status)
509-
status = sysfs_emit(buf, "%u\n", val);
510509

511-
return status;
510+
return sysfs_emit(buf, "%u\n", val);
512511
}
513512
static DEVICE_ATTR_RO(timeleft);
514513

@@ -624,9 +623,7 @@ static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr,
624623
struct watchdog_device *wdd = dev_get_drvdata(dev);
625624
umode_t mode = attr->mode;
626625

627-
if (attr == &dev_attr_timeleft.attr && !wdd->ops->get_timeleft)
628-
mode = 0;
629-
else if (attr == &dev_attr_pretimeout.attr && !watchdog_have_pretimeout(wdd))
626+
if (attr == &dev_attr_pretimeout.attr && !watchdog_have_pretimeout(wdd))
630627
mode = 0;
631628
else if ((attr == &dev_attr_pretimeout_governor.attr ||
632629
attr == &dev_attr_pretimeout_available_governors.attr) &&
@@ -825,9 +822,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
825822
err = put_user(wdd->timeout, p);
826823
break;
827824
case WDIOC_GETTIMELEFT:
828-
err = watchdog_get_timeleft(wdd, &val);
829-
if (err < 0)
830-
break;
825+
watchdog_get_timeleft(wdd, &val);
831826
err = put_user(val, p);
832827
break;
833828
case WDIOC_SETPRETIMEOUT:

0 commit comments

Comments
 (0)