From patchwork Sat Jun 20 17:33:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 11616171 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D3FBE14E3 for ; Sat, 20 Jun 2020 17:35:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B26FD2405E for ; Sat, 20 Jun 2020 17:35:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ioJCILsk" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728126AbgFTRfH (ORCPT ); Sat, 20 Jun 2020 13:35:07 -0400 Received: from mail-oi1-f194.google.com ([209.85.167.194]:36342 "EHLO mail-oi1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728349AbgFTRfF (ORCPT ); Sat, 20 Jun 2020 13:35:05 -0400 Received: by mail-oi1-f194.google.com with SMTP id a137so11587118oii.3 for ; Sat, 20 Jun 2020 10:35:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=HOVBYX09s4vb3dCiShBG4NSsb19cgNGL44yivBt9AqQ=; b=ioJCILskKb7oD4HN+oRp0Xb7bCKYZgLEUbxjkk+m9AMKBg7srdQhlvulVDHO8I0ATQ VAolcNgU5Zj9svSjp6saOjl+sn0XNXkNk9ObjJCUP+II3W6pLEatemkwcwyU9eNLCcut ZhLyStdZtq4/ESsc/K/xd1m0xwVgB5Os9sPTYSYHrxwUNSrfjKsqsOb/ikUZ50J8vj3c 09XOuTlbV9KJ84Uf+WB91Pewqjf5iVWnQQe49VjTzVeLDDEbEQfnNmlDO2h4Mc36HS2L mc6XwSDtA/ljrBb6flI+O7SLzBsHnSoo+GD97UPqhIPvbAs4M1U4Bxtd6bLH1UiOcOmI 25bw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=HOVBYX09s4vb3dCiShBG4NSsb19cgNGL44yivBt9AqQ=; b=pZqi8bXQ4YfTYV1C/nuzOSo1qP8C6a/8/A06wgNm/llqZfm3Pxy6kXo0snbdM3mlx8 M0Iv7c2xNVE6Euf+7kXpWaGY4nThnc1NTbX3+D21WrP5obIxynUz8/MQl85mFJYU09Fw 1bZturHKvAmeiBRBgMOO6hH8SpZn+vPdw/koU9FP7evGEgKwS9vNzUcTLwEm5l2aJLki F5S2c3Ff6tt7JzsVTjCq4lGOVQ4sR7+Y4Jk86M7OI5v4qssgdESnq5yjefvVEh+mTMSs XicEnsu6jwvIMw3gUAWvVCgWjH0Jrs+QH3ISeg/BOOQypdLBRS2KWizF1raZpyD0I0Zc 1sQw== X-Gm-Message-State: AOAM530dSAdjW3Iy2ij4ZOysqIJxJkad8RTBrw0tFnyU7ZuVWm/jSosZ KadYOLKOMmtzIsY5YEyEJ+goxR4= X-Google-Smtp-Source: ABdhPJzJ/aOvpOMypiS7YmUOUcr7cGrxm74otNl6GSmSwuphL4reMsApF68JVR3YLlZVALQSCF8KdA== X-Received: by 2002:a05:6808:c2:: with SMTP id t2mr7599544oic.44.1592674442594; Sat, 20 Jun 2020 10:34:02 -0700 (PDT) Received: from serve.minyard.net ([47.184.146.204]) by smtp.gmail.com with ESMTPSA id y206sm2128230ooa.32.2020.06.20.10.34.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Jun 2020 10:34:01 -0700 (PDT) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:f17b:b355:b0a4:2592]) by serve.minyard.net (Postfix) with ESMTPA id 68241180171; Sat, 20 Jun 2020 17:34:00 +0000 (UTC) From: minyard@acm.org To: Guenter Roeck , Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org, Gabriele Paoloni , Corey Minyard Subject: [PATCH 1/6] watchdog: Allow a driver to use milliseconds instead of seconds Date: Sat, 20 Jun 2020 12:33:46 -0500 Message-Id: <20200620173351.18752-2-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200620173351.18752-1-minyard@acm.org> References: <20200620173351.18752-1-minyard@acm.org> Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org From: Corey Minyard If the WDIOF_MSECTIMER is set, then all the timeouts in the watchdog structure are expected to be in milliseconds. Add the flag and the various conversions. This should have no effect on existing drivers. Signed-off-by: Corey Minyard --- drivers/watchdog/watchdog_core.c | 30 +++++++++++++------- drivers/watchdog/watchdog_dev.c | 47 ++++++++++++++++++++++++++------ include/linux/watchdog.h | 29 +++++++++++++++----- include/uapi/linux/watchdog.h | 1 + 4 files changed, 82 insertions(+), 25 deletions(-) diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index 423844757812..b54451a9a336 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -116,17 +116,17 @@ int watchdog_init_timeout(struct watchdog_device *wdd, { const char *dev_str = wdd->parent ? dev_name(wdd->parent) : (const char *)wdd->info->identity; - unsigned int t = 0; int ret = 0; watchdog_check_min_max_timeout(wdd); /* check the driver supplied value (likely a module parameter) first */ if (timeout_parm) { - if (!watchdog_timeout_invalid(wdd, timeout_parm)) { - wdd->timeout = timeout_parm; - return 0; - } + if (wdd->info->options & WDIOF_MSECTIMER) { + if (!_watchdog_timeout_invalid(wdd, timeout_parm)) + goto set_timeout; + } else if (!watchdog_timeout_invalid(wdd, timeout_parm)) + goto set_timeout; pr_err("%s: driver supplied timeout (%u) out of range\n", dev_str, timeout_parm); ret = -EINVAL; @@ -134,12 +134,18 @@ int watchdog_init_timeout(struct watchdog_device *wdd, /* try to get the timeout_sec property */ if (dev && dev->of_node && - of_property_read_u32(dev->of_node, "timeout-sec", &t) == 0) { - if (t && !watchdog_timeout_invalid(wdd, t)) { - wdd->timeout = t; - return 0; + of_property_read_u32(dev->of_node, "timeout-sec", + &timeout_parm) == 0) { + if (timeout_parm && + !watchdog_timeout_invalid(wdd, timeout_parm)) { + if (!(wdd->info->options & WDIOF_MSECTIMER)) + /* Convert to msecs if not already so. */ + timeout_parm *= 1000; + goto set_timeout; } - pr_err("%s: DT supplied timeout (%u) out of range\n", dev_str, t); + + pr_err("%s: DT supplied timeout (%u) out of range\n", dev_str, + timeout_parm); ret = -EINVAL; } @@ -148,6 +154,10 @@ int watchdog_init_timeout(struct watchdog_device *wdd, wdd->timeout); return ret; + +set_timeout: + wdd->timeout = timeout_parm; + return 0; } EXPORT_SYMBOL_GPL(watchdog_init_timeout); diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 7e4cd34a8c20..480460b89c16 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -99,7 +99,11 @@ static inline bool watchdog_need_worker(struct watchdog_device *wdd) { /* All variables in milli-seconds */ unsigned int hm = wdd->max_hw_heartbeat_ms; - unsigned int t = wdd->timeout * 1000; + unsigned int t = wdd->timeout; + + if (!(wdd->info->options & WDIOF_MSECTIMER)) + /* Convert to msecs if not already so. */ + t *= 1000; /* * A worker to generate heartbeat requests is needed if all of the @@ -121,12 +125,16 @@ static inline bool watchdog_need_worker(struct watchdog_device *wdd) static ktime_t watchdog_next_keepalive(struct watchdog_device *wdd) { struct watchdog_core_data *wd_data = wdd->wd_data; - unsigned int timeout_ms = wdd->timeout * 1000; + unsigned int timeout_ms = wdd->timeout; ktime_t keepalive_interval; ktime_t last_heartbeat, latest_heartbeat; ktime_t virt_timeout; unsigned int hw_heartbeat_ms; + if (!(wdd->info->options & WDIOF_MSECTIMER)) + /* Convert to msecs if not already so. */ + timeout_ms *= 1000; + if (watchdog_active(wdd)) virt_timeout = ktime_add(wd_data->last_keepalive, ms_to_ktime(timeout_ms)); @@ -137,7 +145,7 @@ static ktime_t watchdog_next_keepalive(struct watchdog_device *wdd) keepalive_interval = ms_to_ktime(hw_heartbeat_ms / 2); /* - * To ensure that the watchdog times out wdd->timeout seconds + * To ensure that the watchdog times out wdd->timeout seconds/msecs * after the most recent ping from userspace, the last * worker ping has to come in hw_heartbeat_ms before this timeout. */ @@ -382,6 +390,8 @@ static int watchdog_set_timeout(struct watchdog_device *wdd, if (watchdog_timeout_invalid(wdd, timeout)) return -EINVAL; + if (wdd->info->options & WDIOF_MSECTIMER) + timeout *= 1000; if (wdd->ops->set_timeout) { err = wdd->ops->set_timeout(wdd, timeout); } else { @@ -413,6 +423,8 @@ static int watchdog_set_pretimeout(struct watchdog_device *wdd, if (watchdog_pretimeout_invalid(wdd, timeout)) return -EINVAL; + if (wdd->info->options & WDIOF_MSECTIMER) + timeout *= 1000; if (wdd->ops->set_pretimeout) err = wdd->ops->set_pretimeout(wdd, timeout); else @@ -440,6 +452,8 @@ static int watchdog_get_timeleft(struct watchdog_device *wdd, return -EOPNOTSUPP; *timeleft = wdd->ops->get_timeleft(wdd); + if (wdd->info->options & WDIOF_MSECTIMER) + *timeleft /= 1000; return 0; } @@ -508,8 +522,11 @@ static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr, mutex_lock(&wd_data->lock); status = watchdog_get_timeleft(wdd, &val); mutex_unlock(&wd_data->lock); - if (!status) + if (!status) { + if (wdd->info->options & WDIOF_MSECTIMER) + val /= 1000; status = sprintf(buf, "%u\n", val); + } return status; } @@ -519,8 +536,12 @@ static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, char *buf) { struct watchdog_device *wdd = dev_get_drvdata(dev); + unsigned int t = wdd->timeout; + + if (wdd->info->options & WDIOF_MSECTIMER) + t /= 1000; - return sprintf(buf, "%u\n", wdd->timeout); + return sprintf(buf, "%u\n", t); } static DEVICE_ATTR_RO(timeout); @@ -528,8 +549,12 @@ static ssize_t pretimeout_show(struct device *dev, struct device_attribute *attr, char *buf) { struct watchdog_device *wdd = dev_get_drvdata(dev); + unsigned int t = wdd->pretimeout; - return sprintf(buf, "%u\n", wdd->pretimeout); + if (wdd->info->options & WDIOF_MSECTIMER) + t /= 1000; + + return sprintf(buf, "%u\n", t); } static DEVICE_ATTR_RO(pretimeout); @@ -783,7 +808,10 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd, err = -EOPNOTSUPP; break; } - err = put_user(wdd->timeout, p); + val = wdd->timeout; + if (wdd->info->options & WDIOF_MSECTIMER) + val /= 1000; + err = put_user(val, p); break; case WDIOC_GETTIMELEFT: err = watchdog_get_timeleft(wdd, &val); @@ -799,7 +827,10 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd, err = watchdog_set_pretimeout(wdd, val); break; case WDIOC_GETPRETIMEOUT: - err = put_user(wdd->pretimeout, p); + val = wdd->pretimeout; + if (wdd->info->options & WDIOF_MSECTIMER) + val /= 1000; + err = put_user(val, p); break; default: err = -ENOTTY; diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index 1464ce6ffa31..49bfaf986b37 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h @@ -55,7 +55,9 @@ struct watchdog_ops { long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); }; -/** struct watchdog_device - The structure that defines a watchdog device +/** struct watchdog_device - The structure that defines a watchdog device. + * Unless otherwise specified, all timeouts are in seconds unless + * WDIOF_MSECTIMER is set, then they are in milliseconds. * * @id: The watchdog's ID. (Allocated by watchdog_register_device) * @parent: The parent bus device @@ -65,10 +67,10 @@ struct watchdog_ops { * @ops: Pointer to the list of watchdog operations. * @gov: Pointer to watchdog pretimeout governor. * @bootstatus: Status of the watchdog device at boot. - * @timeout: The watchdog devices timeout value (in seconds). + * @timeout: The watchdog devices timeout value. * @pretimeout: The watchdog devices pre_timeout value. - * @min_timeout:The watchdog devices minimum timeout value (in seconds). - * @max_timeout:The watchdog devices maximum timeout value (in seconds) + * @min_timeout:The watchdog devices minimum timeout value. + * @max_timeout:The watchdog devices maximum timeout value * as configurable from user space. Only relevant if * max_hw_heartbeat_ms is not provided. * @min_hw_heartbeat_ms: @@ -156,6 +158,17 @@ static inline void watchdog_stop_on_unregister(struct watchdog_device *wdd) set_bit(WDOG_STOP_ON_UNREGISTER, &wdd->status); } +/* + * Use the following function to check if a timeout value is + * internally consistent with the range parameters. t is in milliseconds. + */ +static inline bool _watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t) +{ + return t < wdd->min_timeout || + (!wdd->max_hw_heartbeat_ms && wdd->max_timeout && + t > wdd->max_timeout); +} + /* Use the following function to check if a timeout value is invalid */ static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t) { @@ -170,9 +183,11 @@ static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigne * is configured, and the requested value is larger than the * configured maximum timeout. */ - return t > UINT_MAX / 1000 || t < wdd->min_timeout || - (!wdd->max_hw_heartbeat_ms && wdd->max_timeout && - t > wdd->max_timeout); + if (t > UINT_MAX / 1000) + return true; + if (wdd->info->options & WDIOF_MSECTIMER) + t *= 1000; + return _watchdog_timeout_invalid(wdd, t); } /* Use the following function to check if a pretimeout value is invalid */ diff --git a/include/uapi/linux/watchdog.h b/include/uapi/linux/watchdog.h index b15cde5c9054..feb3bcc46993 100644 --- a/include/uapi/linux/watchdog.h +++ b/include/uapi/linux/watchdog.h @@ -48,6 +48,7 @@ struct watchdog_info { #define WDIOF_PRETIMEOUT 0x0200 /* Pretimeout (in seconds), get/set */ #define WDIOF_ALARMONLY 0x0400 /* Watchdog triggers a management or other external alarm not a reboot */ +#define WDIOF_MSECTIMER 0x0800 /* Driver can use milliseconds for timeouts */ #define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */ #define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */ From patchwork Sat Jun 20 17:33:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 11616169 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 81F3E1746 for ; Sat, 20 Jun 2020 17:35:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 647242405C for ; Sat, 20 Jun 2020 17:35:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DTmFYFHf" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728357AbgFTRfG (ORCPT ); Sat, 20 Jun 2020 13:35:06 -0400 Received: from mail-ot1-f67.google.com ([209.85.210.67]:44684 "EHLO mail-ot1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728126AbgFTRfF (ORCPT ); Sat, 20 Jun 2020 13:35:05 -0400 Received: by mail-ot1-f67.google.com with SMTP id e5so9780531ote.11 for ; Sat, 20 Jun 2020 10:35:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=f4PL0T6GCERZ/YEDo14hZLuC450xWsmw+SQUtlVusaM=; b=DTmFYFHf2N8OTI5tCrUf5rn2dn4VZ1Y3PK6m11rb3lNXWDWU9Ike6gABkBFEuT4/xl NocJI/qCR9HYx1rUjX9yLpocA8UmMRM7zEyoVviOte0I5SMQY71vpNdcgA9rG4pNNU2V DnxkYCNzfR1ksSUjIztkXT3ooXwIupGfNDMBZvJtJgA+Cxl+10e0vXV/iMhkHPKToOMN X+CrnJF3sNUFTYtVS0F3owIqk67u/lBX65aZcVNuJZVL4nBuE7Rx5OnSdBDqUA4OuIDd b3+inw+nrYbsEJU/BGkR7wAYQalZTDzb7EtJhBKS3yxbH+Wk4KxebHRkaPkW3eJCXTs5 3FcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=f4PL0T6GCERZ/YEDo14hZLuC450xWsmw+SQUtlVusaM=; b=V//qciAGV8UEKN8xzK6lK+m40iPMDikMdDKhX5bt17Nkc+jtl1ncM8aUIS+y7MM0JT StF6RBe3z4zvS9WMCWcCDi4zZr0BgtZBINlIvTjQeHhVxXA8nitPKeKeXfWCy2qluxNK PQCfjzWEtt6O9dK+11R/RE9mml8OQaAWBa1u3+OEfG2ovT08KFsKir0lmgloYLvLw/uR 7XcnwwZmagFTGqoDB1ckVpOo1ayisWwfXEm6Og6+579gcurZBBeSybsxBE2zzqN9ieSb xhhUoThiqoS/xba3isg410M40DxbM3bBlrTdXZVDbHnttAKEOJukCwomTQBmViJ30rYz OCIg== X-Gm-Message-State: AOAM53070PjLEbRda16n6BcFIsqMiqyAhoAp5ITB48l1z3+qLq/+RFsi NGlrd8kWpCY1rnSQfbx+pUsnDJo= X-Google-Smtp-Source: ABdhPJzaqfVKX6ZRV8gBsTlcbwKJXnTzYBdGNtAEhZDTPBi5QD7morWMsndmGyEbK36ECY7sg641Rg== X-Received: by 2002:a9d:6e0a:: with SMTP id e10mr7997634otr.171.1592674443480; Sat, 20 Jun 2020 10:34:03 -0700 (PDT) Received: from serve.minyard.net (serve.minyard.net. [2001:470:b8f6:1b::1]) by smtp.gmail.com with ESMTPSA id u125sm1982816oif.57.2020.06.20.10.34.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Jun 2020 10:34:01 -0700 (PDT) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:f17b:b355:b0a4:2592]) by serve.minyard.net (Postfix) with ESMTPA id 87777180545; Sat, 20 Jun 2020 17:34:00 +0000 (UTC) From: minyard@acm.org To: Guenter Roeck , Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org, Gabriele Paoloni , Corey Minyard Subject: [PATCH 2/6] watchdog: Add ioctls for millisecond timeout handling Date: Sat, 20 Jun 2020 12:33:47 -0500 Message-Id: <20200620173351.18752-3-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200620173351.18752-1-minyard@acm.org> References: <20200620173351.18752-1-minyard@acm.org> Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org From: Corey Minyard Add millisecond ioctls for the five timeout ioctls in the watchdog. If the driver being used doesn't support milliseconds, the appropriate conversions are done. Signed-off-by: Corey Minyard --- drivers/watchdog/watchdog_core.c | 5 +- drivers/watchdog/watchdog_core.h | 2 + drivers/watchdog/watchdog_dev.c | 123 ++++++++++++++++++++++--------- include/uapi/linux/watchdog.h | 5 ++ 4 files changed, 98 insertions(+), 37 deletions(-) diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index b54451a9a336..9c531ae05c46 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -138,9 +138,8 @@ int watchdog_init_timeout(struct watchdog_device *wdd, &timeout_parm) == 0) { if (timeout_parm && !watchdog_timeout_invalid(wdd, timeout_parm)) { - if (!(wdd->info->options & WDIOF_MSECTIMER)) - /* Convert to msecs if not already so. */ - timeout_parm *= 1000; + timeout_parm = watchdog_timeout_tointernal(wdd, false, + timeout_parm); goto set_timeout; } diff --git a/drivers/watchdog/watchdog_core.h b/drivers/watchdog/watchdog_core.h index a5062e8e0d13..151806073d58 100644 --- a/drivers/watchdog/watchdog_core.h +++ b/drivers/watchdog/watchdog_core.h @@ -31,3 +31,5 @@ extern int watchdog_dev_register(struct watchdog_device *); extern void watchdog_dev_unregister(struct watchdog_device *); extern int __init watchdog_dev_init(void); extern void __exit watchdog_dev_exit(void); +extern unsigned int watchdog_timeout_tointernal(struct watchdog_device *, + bool, unsigned int); diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 480460b89c16..eca13ce1dc91 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -371,6 +371,56 @@ static unsigned int watchdog_get_status(struct watchdog_device *wdd) return status; } +/* + * watchdog_timeout_tointernal: Convert to internal time representation + * @wdd: the watchdog device + * @in_msecs: false - timeout in seconds, true - timeout in milliseconds + * @timeout: timeout to convert + * + * Convert from an external representation of the timeout in + * seconds (or milliseconds if in_msecs is true) to the internal + * timeout in seconds or milliseconds, depending on + * WDIOF_MSECTIMER. + */ +unsigned int watchdog_timeout_tointernal(struct watchdog_device *wdd, + bool in_msecs, + unsigned int timeout) +{ + if (wdd->info->options & WDIOF_MSECTIMER) { + if (!in_msecs) + timeout *= 1000; + } else if (in_msecs) { + /* Truncate up. */ + timeout = (timeout + 999) / 1000; + } + return timeout; +} + +/* + * watchdog_timeout_toexternal: Convert to external time representation + * @wdd: the watchdog device + * @in_msecs: false - returns seconds, true - returns milliseconds + * @timeout: timeout in seconds (or milliseconds if WDIOF_MSECTIMER is set) + * + * Convert from an internal representation of the timeout in + * seconds (or milliseconds if WDIOF_MSECTIMER is set) to the + * external timeout in seconds or milliseconds, depending on + * in_msecs. + */ +static unsigned int watchdog_timeout_toexternal(struct watchdog_device *wdd, + bool in_msecs, + unsigned int timeout) +{ + if (wdd->info->options & WDIOF_MSECTIMER) { + if (!in_msecs) + timeout /= 1000; + } else if (in_msecs) { + timeout *= 1000; + } + + return timeout; +} + /* * watchdog_set_timeout: set the watchdog timer timeout * @wdd: the watchdog device to set the timeout for @@ -379,7 +429,7 @@ static unsigned int watchdog_get_status(struct watchdog_device *wdd) * The caller must hold wd_data->lock. */ -static int watchdog_set_timeout(struct watchdog_device *wdd, +static int watchdog_set_timeout(struct watchdog_device *wdd, bool in_msecs, unsigned int timeout) { int err = 0; @@ -387,11 +437,13 @@ static int watchdog_set_timeout(struct watchdog_device *wdd, if (!(wdd->info->options & WDIOF_SETTIMEOUT)) return -EOPNOTSUPP; - if (watchdog_timeout_invalid(wdd, timeout)) + if (in_msecs) { + if (_watchdog_timeout_invalid(wdd, timeout)) + return -EINVAL; + } else if (watchdog_timeout_invalid(wdd, timeout)) return -EINVAL; - if (wdd->info->options & WDIOF_MSECTIMER) - timeout *= 1000; + timeout = watchdog_timeout_tointernal(wdd, in_msecs, timeout); if (wdd->ops->set_timeout) { err = wdd->ops->set_timeout(wdd, timeout); } else { @@ -413,6 +465,7 @@ static int watchdog_set_timeout(struct watchdog_device *wdd, */ static int watchdog_set_pretimeout(struct watchdog_device *wdd, + bool in_msecs, unsigned int timeout) { int err = 0; @@ -423,8 +476,7 @@ static int watchdog_set_pretimeout(struct watchdog_device *wdd, if (watchdog_pretimeout_invalid(wdd, timeout)) return -EINVAL; - if (wdd->info->options & WDIOF_MSECTIMER) - timeout *= 1000; + timeout = watchdog_timeout_tointernal(wdd, in_msecs, timeout); if (wdd->ops->set_pretimeout) err = wdd->ops->set_pretimeout(wdd, timeout); else @@ -443,7 +495,7 @@ static int watchdog_set_pretimeout(struct watchdog_device *wdd, * Get the time before a watchdog will reboot (if not pinged). */ -static int watchdog_get_timeleft(struct watchdog_device *wdd, +static int watchdog_get_timeleft(struct watchdog_device *wdd, bool in_msecs, unsigned int *timeleft) { *timeleft = 0; @@ -452,8 +504,7 @@ static int watchdog_get_timeleft(struct watchdog_device *wdd, return -EOPNOTSUPP; *timeleft = wdd->ops->get_timeleft(wdd); - if (wdd->info->options & WDIOF_MSECTIMER) - *timeleft /= 1000; + *timeleft = watchdog_timeout_toexternal(wdd, in_msecs, *timeleft); return 0; } @@ -520,13 +571,11 @@ static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr, unsigned int val; mutex_lock(&wd_data->lock); - status = watchdog_get_timeleft(wdd, &val); + status = watchdog_get_timeleft(wdd, false, &val); mutex_unlock(&wd_data->lock); - if (!status) { - if (wdd->info->options & WDIOF_MSECTIMER) - val /= 1000; - status = sprintf(buf, "%u\n", val); - } + if (!status) + status = sprintf(buf, "%u\n", + watchdog_timeout_toexternal(wdd, false, val)); return status; } @@ -536,12 +585,9 @@ static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, char *buf) { struct watchdog_device *wdd = dev_get_drvdata(dev); - unsigned int t = wdd->timeout; - if (wdd->info->options & WDIOF_MSECTIMER) - t /= 1000; - - return sprintf(buf, "%u\n", t); + return sprintf(buf, "%u\n", + watchdog_timeout_toexternal(wdd, false, wdd->timeout)); } static DEVICE_ATTR_RO(timeout); @@ -549,12 +595,10 @@ static ssize_t pretimeout_show(struct device *dev, struct device_attribute *attr, char *buf) { struct watchdog_device *wdd = dev_get_drvdata(dev); - unsigned int t = wdd->pretimeout; - - if (wdd->info->options & WDIOF_MSECTIMER) - t /= 1000; - return sprintf(buf, "%u\n", t); + return sprintf(buf, "%u\n", + watchdog_timeout_toexternal(wdd, false, + wdd->pretimeout)); } static DEVICE_ATTR_RO(pretimeout); @@ -788,11 +832,13 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd, err = watchdog_ping(wdd); break; case WDIOC_SETTIMEOUT: + case WDIOC_SETTIMEOUT_MS: if (get_user(val, p)) { err = -EFAULT; break; } - err = watchdog_set_timeout(wdd, val); + err = watchdog_set_timeout(wdd, cmd == WDIOC_SETTIMEOUT_MS, + val); if (err < 0) break; /* If the watchdog is active then we send a keepalive ping @@ -803,33 +849,42 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd, break; /* fall through */ case WDIOC_GETTIMEOUT: + case WDIOC_GETTIMEOUT_MS: /* timeout == 0 means that we don't know the timeout */ if (wdd->timeout == 0) { err = -EOPNOTSUPP; break; } - val = wdd->timeout; - if (wdd->info->options & WDIOF_MSECTIMER) - val /= 1000; + val = watchdog_timeout_toexternal(wdd, + (cmd == WDIOC_SETTIMEOUT_MS || + cmd == WDIOC_GETTIMEOUT_MS), + wdd->timeout); err = put_user(val, p); break; case WDIOC_GETTIMELEFT: - err = watchdog_get_timeleft(wdd, &val); + case WDIOC_GETTIMELEFT_MS: + err = watchdog_get_timeleft(wdd, cmd == WDIOC_GETTIMELEFT_MS, + &val); if (err < 0) break; err = put_user(val, p); break; case WDIOC_SETPRETIMEOUT: + case WDIOC_SETPRETIMEOUT_MS: if (get_user(val, p)) { err = -EFAULT; break; } - err = watchdog_set_pretimeout(wdd, val); + err = watchdog_set_pretimeout(wdd, + cmd == WDIOC_SETPRETIMEOUT_MS, + val); break; case WDIOC_GETPRETIMEOUT: - val = wdd->pretimeout; - if (wdd->info->options & WDIOF_MSECTIMER) - val /= 1000; + case WDIOC_GETPRETIMEOUT_MS: + val = watchdog_timeout_toexternal(wdd, + (cmd == WDIOC_SETPRETIMEOUT_MS || + cmd == WDIOC_GETPRETIMEOUT_MS), + wdd->pretimeout); err = put_user(val, p); break; default: diff --git a/include/uapi/linux/watchdog.h b/include/uapi/linux/watchdog.h index feb3bcc46993..3df7880c6fca 100644 --- a/include/uapi/linux/watchdog.h +++ b/include/uapi/linux/watchdog.h @@ -32,6 +32,11 @@ struct watchdog_info { #define WDIOC_SETPRETIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 8, int) #define WDIOC_GETPRETIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 9, int) #define WDIOC_GETTIMELEFT _IOR(WATCHDOG_IOCTL_BASE, 10, int) +#define WDIOC_SETTIMEOUT_MS _IOWR(WATCHDOG_IOCTL_BASE, 11, int) +#define WDIOC_GETTIMEOUT_MS _IOR(WATCHDOG_IOCTL_BASE, 12, int) +#define WDIOC_SETPRETIMEOUT_MS _IOWR(WATCHDOG_IOCTL_BASE, 13, int) +#define WDIOC_GETPRETIMEOUT_MS _IOR(WATCHDOG_IOCTL_BASE, 14, int) +#define WDIOC_GETTIMELEFT_MS _IOR(WATCHDOG_IOCTL_BASE, 15, int) #define WDIOF_UNKNOWN -1 /* Unknown flag error */ #define WDIOS_UNKNOWN -1 /* Unknown status error */ From patchwork Sat Jun 20 17:33:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 11616167 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5F5FA1392 for ; Sat, 20 Jun 2020 17:35:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 44C0A2405F for ; Sat, 20 Jun 2020 17:35:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="sIXqVXcl" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728256AbgFTRfE (ORCPT ); Sat, 20 Jun 2020 13:35:04 -0400 Received: from mail-oi1-f193.google.com ([209.85.167.193]:36340 "EHLO mail-oi1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728191AbgFTRfD (ORCPT ); Sat, 20 Jun 2020 13:35:03 -0400 Received: by mail-oi1-f193.google.com with SMTP id a137so11587106oii.3 for ; Sat, 20 Jun 2020 10:35:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=jIos/cHbqrurStkzPZEPZkdct3JfDCiT1Al2g34v7+M=; b=sIXqVXclo+4Ck3UmWBwJpEjM7CkUr955y0iqifo5W1GC5s72/oIvM5vc2HLkkTI6xK mBgv8FPt6kP79GSevYV+5BLsIKgX185uFW7S1rRckhLqfuqjA8aXSBtS5QIByCirrdIt bDIH29yncc4MfCglZPBmLmEzi4dBLN1eYLI+yFeO78/d21bu8oK5aZuYP7EIL/ldJV+z J5FLX6V2NAKPUEtKiFPYzvt+IaNgdMOqNpkGEhL2d/Qnocy/LEibPZ2cZejTu1m1sc3Y BPCtTRNlXuT9pBT91sQz3ag7vT9VtYjxtK3k3mFrwSBV65t0ps6wiyad54WMA2TARidp zp1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=jIos/cHbqrurStkzPZEPZkdct3JfDCiT1Al2g34v7+M=; b=Hd5K9tRm0NYAp9YtQgTWt38RDY/nFI0ib60SDiHsPHxOAtYzR9uUd3Mn/PNkr5ZFhl bGbU1gRcH4KqWHZbIP5wa20B3Q0xxzA0hX+tbiRnILM2h1p1To81f9sFqfWUbtD8j5mg Vy5xhSLqcDgyiKRVdo/n1iewx+nXNPoqL7yEt6P9GyAw1MOyYzttdSh1BhMfgCkTpa5U bv/aapfJRfMqM2/X8hmhOr2oA/rdCJoFzbLsanQfcBbzZJYIYuTdddTz4sZa9dzRcjhi PbhGfTmf/D3lO1/dnrujST4pvDb9MZgCrMF0U9wPYO1r5xHr/ukOoyXct1QmXbFqcM5c 27XA== X-Gm-Message-State: AOAM531/mBDaivvh6/pBz5CTAuQguPGv7i+fE2s4Fi4di98jNwjxmFr6 3YrSxO2cX5Ne+rvZ1qhHAFaQL4w= X-Google-Smtp-Source: ABdhPJyMI9Agja2ULN/bm4Egbo2YH898dHbUAjVl/L/cn90eadqH8UlZmHFsy5vR/qOhQi/NwX5q/Q== X-Received: by 2002:aca:d956:: with SMTP id q83mr7020231oig.78.1592674442133; Sat, 20 Jun 2020 10:34:02 -0700 (PDT) Received: from serve.minyard.net ([47.184.146.204]) by smtp.gmail.com with ESMTPSA id w10sm2167357oon.40.2020.06.20.10.34.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Jun 2020 10:34:01 -0700 (PDT) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:f17b:b355:b0a4:2592]) by serve.minyard.net (Postfix) with ESMTPA id 9377818054B; Sat, 20 Jun 2020 17:34:00 +0000 (UTC) From: minyard@acm.org To: Guenter Roeck , Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org, Gabriele Paoloni , Corey Minyard Subject: [PATCH 3/6] watchdog: Add millisecond precision device attributes Date: Sat, 20 Jun 2020 12:33:48 -0500 Message-Id: <20200620173351.18752-4-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200620173351.18752-1-minyard@acm.org> References: <20200620173351.18752-1-minyard@acm.org> Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org From: Corey Minyard Add timeleft_ms, timeout_ms, and pretimeout_ms that print microsecond values. Signed-off-by: Corey Minyard --- drivers/watchdog/watchdog_dev.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index eca13ce1dc91..b82049896204 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -562,6 +562,21 @@ static ssize_t bootstatus_show(struct device *dev, } static DEVICE_ATTR_RO(bootstatus); +/* + * If _ms is in the attribute name, return milliseconds, otherwise + * return seconds. + */ +static unsigned int conv_time_to_attr_display(struct watchdog_device *wdd, + struct device_attribute *attr, + unsigned int val) +{ + bool in_msec = false; + + if (strstr(attr->attr.name, "_ms")) + in_msec = true; + return watchdog_timeout_toexternal(wdd, in_msec, val); +} + static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -575,11 +590,12 @@ static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr, mutex_unlock(&wd_data->lock); if (!status) status = sprintf(buf, "%u\n", - watchdog_timeout_toexternal(wdd, false, val)); + conv_time_to_attr_display(wdd, attr, val)); return status; } static DEVICE_ATTR_RO(timeleft); +static DEVICE_ATTR(timeleft_ms, 0444, timeleft_show, NULL); static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -587,9 +603,10 @@ static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, struct watchdog_device *wdd = dev_get_drvdata(dev); return sprintf(buf, "%u\n", - watchdog_timeout_toexternal(wdd, false, wdd->timeout)); + conv_time_to_attr_display(wdd, attr, wdd->timeout)); } static DEVICE_ATTR_RO(timeout); +static DEVICE_ATTR(timeout_ms, 0444, timeout_show, NULL); static ssize_t pretimeout_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -597,10 +614,10 @@ static ssize_t pretimeout_show(struct device *dev, struct watchdog_device *wdd = dev_get_drvdata(dev); return sprintf(buf, "%u\n", - watchdog_timeout_toexternal(wdd, false, - wdd->pretimeout)); + conv_time_to_attr_display(wdd, attr, wdd->pretimeout)); } static DEVICE_ATTR_RO(pretimeout); +static DEVICE_ATTR(pretimeout_ms, 0444, pretimeout_show, NULL); static ssize_t identity_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -677,8 +694,11 @@ static struct attribute *wdt_attrs[] = { &dev_attr_state.attr, &dev_attr_identity.attr, &dev_attr_timeout.attr, + &dev_attr_timeout_ms.attr, &dev_attr_pretimeout.attr, + &dev_attr_pretimeout_ms.attr, &dev_attr_timeleft.attr, + &dev_attr_timeleft_ms.attr, &dev_attr_bootstatus.attr, &dev_attr_status.attr, &dev_attr_nowayout.attr, From patchwork Sat Jun 20 17:33:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 11616175 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 856581746 for ; Sat, 20 Jun 2020 17:35:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 691342405E for ; Sat, 20 Jun 2020 17:35:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gEb7CAlA" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728355AbgFTRfH (ORCPT ); Sat, 20 Jun 2020 13:35:07 -0400 Received: from mail-oi1-f194.google.com ([209.85.167.194]:46804 "EHLO mail-oi1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728191AbgFTRfG (ORCPT ); Sat, 20 Jun 2020 13:35:06 -0400 Received: by mail-oi1-f194.google.com with SMTP id 25so11545623oiy.13 for ; Sat, 20 Jun 2020 10:35:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=hz8GqE3JxF+NFjEiQfFD110wPSsNpDnROS/GHJzNG6w=; b=gEb7CAlAMt8j5b2PDqsBqbi4s2llZ0Cjca7ToGkekUhyLRRNIPwiTKTRLTVB7RZgaQ YRaAIJhiYqe8uJyxBD+qeP2vjW+vzvo/AHv8mNVvF6ImYxx3pQTyvOA9iPeTU/MPZB4W bLesGENar78NZLmleSheB/atz/d5nfS+cGzTV8C3TOtrwq7GNOHRJc4yF6o0Uxkw333f 3u6Mxk2B9G50FTRqa2dNTR3sa41QU3Tvhml65MAHggQeAWzcBtrafVzJ9GYXsF6b1Uho uwUGJWH+Y49QPF995bYwQsIWRZOO+nQIS3I9b6Er25cZeWsmw7lOzsh77Vyyn4SURTEr WFKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=hz8GqE3JxF+NFjEiQfFD110wPSsNpDnROS/GHJzNG6w=; b=NtMUaROleW7c9CuVZqBVi3sW3Liz9ryrelHhJo3S7hzTQc6f5WSYnTxidSRq5mN+jN d52Whb2/f2Dm37t7k536ySD4zK9xWl9+lQk4vvxkWKrwQZ4V2aLJxzGRBZhBGgdffcua ybRvHecuTcevJxAMtsk2fNYH8u3iiXTKlYHyXtQBDxioQDyV2/IfDcZrOflCCuX/GtR9 qDo0lASZ5hioBZZTA8LWjimk+RFjiGp2qunj2mSb0vSFv1Su4ql6j6JCfHn5Ywu1e+tF vuiyxO39X1myxP5Y9Tvd7i6cpx2L3zUw0sbREOnDbedNLeRkK/ikPGTfP9tLTTZU9xzE nOHA== X-Gm-Message-State: AOAM532LPoAqOmCAK4yEVv3t5zBiYuLBXPcZOdcHL+07Kd5qIAL4BvWs 0tetZ4MnbjRUQxOkAJxQSw== X-Google-Smtp-Source: ABdhPJxGwM0r7OnhgY1rekJ7pKdQbFs5eU4T5HFVMVsaLm9lm0Xi1i2vtT8F47XPUnplqISCIzuE6w== X-Received: by 2002:aca:603:: with SMTP id 3mr6845193oig.89.1592674443946; Sat, 20 Jun 2020 10:34:03 -0700 (PDT) Received: from serve.minyard.net (serve.minyard.net. [2001:470:b8f6:1b::1]) by smtp.gmail.com with ESMTPSA id q85sm1994205oic.23.2020.06.20.10.34.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Jun 2020 10:34:02 -0700 (PDT) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:f17b:b355:b0a4:2592]) by serve.minyard.net (Postfix) with ESMTPA id A04A618054F; Sat, 20 Jun 2020 17:34:00 +0000 (UTC) From: minyard@acm.org To: Guenter Roeck , Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org, Gabriele Paoloni , Corey Minyard Subject: [PATCH 4/6] watchdog: Add documentation for millisecond interfaces Date: Sat, 20 Jun 2020 12:33:49 -0500 Message-Id: <20200620173351.18752-5-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200620173351.18752-1-minyard@acm.org> References: <20200620173351.18752-1-minyard@acm.org> Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org From: Corey Minyard Document the new interfaces and semantics of how this works. Signed-off-by: Corey Minyard --- Documentation/watchdog/watchdog-api.rst | 59 +++++++++++++++++++ .../watchdog/watchdog-kernel-api.rst | 30 ++++++---- 2 files changed, 78 insertions(+), 11 deletions(-) diff --git a/Documentation/watchdog/watchdog-api.rst b/Documentation/watchdog/watchdog-api.rst index c6c1e9fa9f73..9f9aa1cd7310 100644 --- a/Documentation/watchdog/watchdog-api.rst +++ b/Documentation/watchdog/watchdog-api.rst @@ -112,6 +112,39 @@ current timeout using the GETTIMEOUT ioctl:: ioctl(fd, WDIOC_GETTIMEOUT, &timeout); printf("The timeout was is %d seconds\n", timeout); +There is also millisecond-level ioctls for setting timeouts in +millisecond values. These will work against a watchdog driver that +only supports seconds, but values will be truncated up on setting and +truncated on fetching. So, for instance: + + int timeout = 44001; + ioctl(fd, WDIOC_SETTIMEOUT_MS, &timeout); + printf("The timeout was set to %d milliseconds\n", timeout); + +If the driver only supports seconds, the timeout will be set to 45 +seconds because it's truncated up. + +Fetching does similar conversions. On a driver that supports +milliseconds, if the current value is 39603 milliseconds: + + ioctl(fd, WDIOC_GETTIMEOUT, &timeout); + printf("The timeout was is %d seconds\n", timeout); + ioctl(fd, WDIOC_GETTIMEOUT_MS, &timeout); + printf("The timeout was is %d milliseconds\n", timeout); + +will print 39 seconds and 39603 milliseconds. + +If a driver supports millisecond level precision, it will have the +WDIOF_MSECTIMER flag set in its option field. Note that does not mean +that the driver has millisecond level accuracy. For instance, a +device might have a 10Hz clock, giving 100ms accuracy. The driver +should set the return timeout for WDIOC_SETTIMEOUT_MS to the actual +setting of the timeout, so you can verify the value. + +It would be nice to have a granularity field, but some devices may not +be linear. So a granularity is not a general thing that could be +done. + Pretimeouts =========== @@ -137,6 +170,16 @@ There is also a get function for getting the pretimeout:: Not all watchdog drivers will support a pretimeout. +Like timeouts, pretimeouts also have millisecond-level ioctls: + + pretimeout = 10000; + ioctl(fd, WDIOC_SETPRETIMEOUT_MS, &pretimeout); + ioctl(fd, WDIOC_GETPRETIMEOUT_NS, &pretimeout); + printf("The pretimeout was is %d milliseconds\n", pretimeout); + +These work just like the timeouts, see that discussion for how +conversions are done. + Get the number of seconds before reboot ======================================= @@ -147,6 +190,14 @@ that returns the number of seconds before reboot:: ioctl(fd, WDIOC_GETTIMELEFT, &timeleft); printf("The timeout was is %d seconds\n", timeleft); +There is also a millisecond-level version: + + ioctl(fd, WDIOC_GETTIMELEFT_MS, &timeleft); + printf("The timeout was is %d milliseconds\n", timeleft); + +If the driver only supports seconds, then the value returns is just +1000 times the seconds value. + Environmental monitoring ======================== @@ -223,6 +274,14 @@ sense. The watchdog saw a keepalive ping since it was last queried. + =============== ======================================== + WDIOF_MSECTIMER Driver can use milliseconds for timeouts + =============== ======================================== + +The driver can do millisecond-level timeouts. The seconds-level +interfaces still work, but setting values in milliseconds can result +in finer granularity. + ================ ======================= WDIOF_SETTIMEOUT Can set/get the timeout ================ ======================= diff --git a/Documentation/watchdog/watchdog-kernel-api.rst b/Documentation/watchdog/watchdog-kernel-api.rst index 068a55ee0d4a..bee60e6ae274 100644 --- a/Documentation/watchdog/watchdog-kernel-api.rst +++ b/Documentation/watchdog/watchdog-kernel-api.rst @@ -80,13 +80,13 @@ It contains following fields: additional information about the watchdog timer itself. (Like it's unique name) * ops: a pointer to the list of watchdog operations that the watchdog supports. * gov: a pointer to the assigned watchdog device pretimeout governor or NULL. -* timeout: the watchdog timer's timeout value (in seconds). +* timeout: the watchdog timer's timeout value. This is the time after which the system will reboot if user space does not send a heartbeat request if WDOG_ACTIVE is set. -* pretimeout: the watchdog timer's pretimeout value (in seconds). -* min_timeout: the watchdog timer's minimum timeout value (in seconds). +* pretimeout: the watchdog timer's pretimeout value. +* min_timeout: the watchdog timer's minimum timeout value. If set, the minimum configurable value for 'timeout'. -* max_timeout: the watchdog timer's maximum timeout value (in seconds), +* max_timeout: the watchdog timer's maximum timeout value, as seen from userspace. If set, the maximum configurable value for 'timeout'. Not used if max_hw_heartbeat_ms is non-zero. * min_hw_heartbeat_ms: Hardware limit for minimum time between heartbeats, @@ -96,7 +96,7 @@ It contains following fields: If set, the infrastructure will send heartbeats to the watchdog driver if 'timeout' is larger than max_hw_heartbeat_ms, unless WDOG_ACTIVE is set and userspace failed to send a heartbeat for at least 'timeout' - seconds. max_hw_heartbeat_ms must be set if a driver does not implement + time. max_hw_heartbeat_ms must be set if a driver does not implement the stop function. * reboot_nb: notifier block that is registered for reboot notifications, for internal use only. If the driver calls watchdog_stop_on_reboot, watchdog core @@ -117,6 +117,13 @@ It contains following fields: * deferred: entry in wtd_deferred_reg_list which is used to register early initialized watchdogs. +The time value used to interact with the device can either be in +seconds or milli-seconds except for min_hw_heartbeat_ms and +max_hw_heartbeat_ms, which are always in milli-seconds. If the driver +sets WDIOF_MSECTIMER in the driver info flags, then the time values +will be in milli-seconds. If it is not set, then the time values will +be in seconds. + The list of watchdog operations is defined as:: struct watchdog_ops { @@ -212,12 +219,13 @@ they are supported. These optional routines/operations are: also take care of checking if pretimeout is still valid and set up the timer accordingly. This can't be done in the core without races, so it is the duty of the driver. -* set_pretimeout: this routine checks and changes the pretimeout value of - the watchdog. It is optional because not all watchdogs support pretimeout - notification. The timeout value is not an absolute time, but the number of - seconds before the actual timeout would happen. It returns 0 on success, - -EINVAL for "parameter out of range" and -EIO for "could not write value to - the watchdog". A value of 0 disables pretimeout notification. +* set_pretimeout: this routine checks and changes the pretimeout value + of the watchdog. It is optional because not all watchdogs support + pretimeout notification. The timeout value is not an absolute time, + but the time before the actual timeout would happen. It returns 0 on + success, -EINVAL for "parameter out of range" and -EIO for "could + not write value to the watchdog". A value of 0 disables pretimeout + notification. (Note: the WDIOF_PRETIMEOUT needs to be set in the options field of the watchdog's info structure). From patchwork Sat Jun 20 17:33:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 11616177 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C38E8912 for ; Sat, 20 Jun 2020 17:35:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A7A5F2405E for ; Sat, 20 Jun 2020 17:35:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PEYLqeDb" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728191AbgFTRfI (ORCPT ); Sat, 20 Jun 2020 13:35:08 -0400 Received: from mail-ot1-f68.google.com ([209.85.210.68]:35686 "EHLO mail-ot1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728351AbgFTRfH (ORCPT ); Sat, 20 Jun 2020 13:35:07 -0400 Received: by mail-ot1-f68.google.com with SMTP id d4so9818367otk.2 for ; Sat, 20 Jun 2020 10:35:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=c9eyYnIbSCchZ+Qys6jP+lWq+0wox/nJrkZtPtmSbFE=; b=PEYLqeDbgaF55kY3PIcittV51Y0QoTmaLq7XZdCfTx2NCcJ1u4gOZqM+DKBf/0Zpmu Se+RrqYE03k+1bMsD1JzY4jv05Rj+hEAV27W7hbi/UNT4wcr3LuMWF1k6R0+N1U2qLeL PH+qWgd//mOAnxgS0GtQjtv+OigmUeqS8EkUkMFM11mHGp5lO+l8s0Sv8ROhfaybh2k6 iSg9aPoir5xVKeIZRAxhB2/Vv+uptrqdmdqTAG3srrlYAGzg/LiX5lXU1WoDpxobCn9+ KlvkKeMmmuyQAOQAVabk6Q/8F69mygucCW6NAgrEZIPYzSbrxTYOJuX0uhdxRgm+X6JJ uliA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=c9eyYnIbSCchZ+Qys6jP+lWq+0wox/nJrkZtPtmSbFE=; b=T7GCYuV0nnWJ75LkGELr/sjtDVUo2koubtNKR6+bgznaMQQINZ5qSMsfZdCdfCEt94 vSgfM5AVtUMGpHmkJo0MDluqX6x6s+qfPCLRw19gsuW7ioo8vqaOr915v0ozaZ6zZ6F/ gTONJy8FBYwVu0jiir7km2mzaMZ2DfVK5WS/BCG6dgNCByh0fB7Qm2ve2AFzaApTHpvi U2/CKeB4B6ub0p9FGULXcHTFYFYwtpvf0tw7USqN2uqqFzrUQTrhoBemYsBNXhRTKu+R /b0TfxwyXCjLAK6hwRKInhsvwmmDoV68qEJY6n+dTwca7xlOwbkVRJm4leUjKgx0Ce+z ocAA== X-Gm-Message-State: AOAM531nZ+Oj67IIzaFmhchv4Q7kaWlOmy9kX7TfD/7Ai451v80SaJcY 8OsFIN/eGgAsZKDp8Fxf+w== X-Google-Smtp-Source: ABdhPJwQtNAySJVinmJtwXxWchQmPBLW074FRNyCe6odSbGF6uZHx6I3OQ2coJ/fgmeFSubI9Ste5A== X-Received: by 2002:a9d:7301:: with SMTP id e1mr7723707otk.289.1592674445302; Sat, 20 Jun 2020 10:34:05 -0700 (PDT) Received: from serve.minyard.net ([47.184.146.204]) by smtp.gmail.com with ESMTPSA id l20sm2074368otp.35.2020.06.20.10.34.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Jun 2020 10:34:03 -0700 (PDT) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:f17b:b355:b0a4:2592]) by serve.minyard.net (Postfix) with ESMTPA id B95E518055F; Sat, 20 Jun 2020 17:34:00 +0000 (UTC) From: minyard@acm.org To: Guenter Roeck , Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org, Gabriele Paoloni , Corey Minyard Subject: [PATCH 5/6] watchdog:i6300: Convert to a millisecond watchdog device Date: Sat, 20 Jun 2020 12:33:50 -0500 Message-Id: <20200620173351.18752-6-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200620173351.18752-1-minyard@acm.org> References: <20200620173351.18752-1-minyard@acm.org> Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org From: Corey Minyard The i6300 clock runs at 1Khz, so it's an easy conversion to make it a millisecond timer. Signed-off-by: Corey Minyard --- drivers/watchdog/i6300esb.c | 66 +++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index a30835f547b3..9f5afe6ee622 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -69,12 +69,40 @@ #define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */ #define ESB_UNLOCK2 0x86 /* Step 2 to unlock reset registers */ -/* module parameters */ -/* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ +/* + * Timer clock is driven by a 30ns clock divided by 32768, giving a + * 983.04usec clock. Not really close enough to say it's 1Khz. But + * if we multiply by 101725261 / 100000000, that would give us a + * 1000.0000057 usec per increment of time, which is very close and + * slightly slow, which is preferred to slightly fast. If there is a + * remainder from that calculation, then round up. So if 1 comes in + * for the time, we will have (1 * 101725261) / 100000000 = 1, and + * (1 * 101725261) % 100000000 = 1725261, so we round up the 1 to a 2, which + * will result in 1.96608msecs. Remember, better too long than too short. + * All the arithmetic has to be 64 bit to avoid overflow. + * + * The error gets better as the numbers increase to more reasonable + * values. For 30 seconds, for instance, we get a count of 30518, + * which is 30.0004 seconds. Close enough :). + * + * The 2061582 max time comes in because we have 2 20 bit registers + * that count down. This means that the maximum timeout value we can + * put in the registers is 0x1ffffe. Run that through the calculation + * backwards and we get 0x1ffffe * 100000000 / 101725261 = 2061582. If we + * put that into our calculation, we get 2061582 * 101725261 / 100000000 = + * 0x1ffffd which will round up to 0x1ffffe. + * + * These numbers should never result in an error more than 1ms, so + * there is no need to be more accurate. This is been tested + * exhaustively. + */ #define ESB_HEARTBEAT_MIN 1 -#define ESB_HEARTBEAT_MAX 2046 -#define ESB_HEARTBEAT_DEFAULT 30 -#define ESB_HEARTBEAT_RANGE __MODULE_STRING(ESB_HEARTBEAT_MIN) \ +#define ESB_HEARTBEAT_MAX 2061582 +/* 30 sec default heartbeat */ +#define ESB_HEARTBEAT_DEFAULT 30000 + +/* module parameters */ +#define ESB_HEARTBEAT_RANGE __MODULE_STRING(ESB_HEARTBEAT_MIN) \ " 2 * 512 = 1024 (which is decremented at 1KHz) + /* + * We have two registers that have to count down, so each gets + * loaded with half the time. */ - val = time << 9; + val = ctime / 2; /* Write timer 1 */ esb_unlock_registers(edev); writel(val, ESB_TIMER1_REG(edev)); + /* If the time was odd, add the extra tick to the second register. */ + val += ctime % 2; + /* Write timer 2 */ esb_unlock_registers(edev); writel(val, ESB_TIMER2_REG(edev)); @@ -190,7 +235,8 @@ static int esb_timer_set_heartbeat(struct watchdog_device *wdd, static struct watchdog_info esb_info = { .identity = ESB_MODULE_NAME, - .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, + .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | + WDIOF_MSECTIMER), }; static const struct watchdog_ops esb_ops = { From patchwork Sat Jun 20 17:33:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 11616173 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 30EF81392 for ; Sat, 20 Jun 2020 17:35:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 17FAC2404E for ; Sat, 20 Jun 2020 17:35:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qrrpgqW/" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728349AbgFTRfH (ORCPT ); Sat, 20 Jun 2020 13:35:07 -0400 Received: from mail-ot1-f67.google.com ([209.85.210.67]:42102 "EHLO mail-ot1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728355AbgFTRfG (ORCPT ); Sat, 20 Jun 2020 13:35:06 -0400 Received: by mail-ot1-f67.google.com with SMTP id t6so9786207otk.9 for ; Sat, 20 Jun 2020 10:35:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=arubcjeP8P4OgD7PRFxwikiodHgcbTBKqjnhEpFN4qo=; b=qrrpgqW/xxBWrqSLhU+1IzRXmQxtfRzCZOQZuppzZdRhJgDIlK7eTJafH90SBDQU6X Lay4LjBZpKRCzaV/klH/kmIRIOEQRMUMQNUAmdOn6Qg0cEApgsR7xZ3Xamln0QDEKNAd +hCMiOtDX+pURKs1WV2V87zhjuokOUq3vBPyt9g7qAmsKwl90Rl7+E0mQ5G3eIswQ6l5 ZN8oV4WT1QDcWA5/rWhJ8jutTa/tfJhbQKRxq4g1E/N4wAtmPMf06zilJc/ee+2MbZN2 ze8Dm6sTh4bxwRdveeHHWmLBuFlSiUB4mRybGGIZoSpbVL16Woc6yjYQnZRXAr9TLVgG hUeQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=arubcjeP8P4OgD7PRFxwikiodHgcbTBKqjnhEpFN4qo=; b=PW6SRMe7TRHAvGRYi9eJesUAlV0sLQpRoISsdsUyCBmmTTrRu1VPb+rAgdAFOPiLgs Kgc9aLtfAF6WPJfDR8rKJjfqqJAltHLzq208cbOEzfAgSJ+U/VUfNyMcJgmfLUYyp0u5 rgIJbn5BPhV9yDqPlRODwVMvW5NsAUGzgKSanPuIJt4sO+jGDK913dXYfeC6CJNl3+0H Z43+3M1p+5iB2RG/REJdpCGZm4y3LzWuoXkkUTQiwp+yuq3bgIrvn64OhA9kE5OkqyJN YVi2xJ1MBVGxS+IzSoCSoWQryOvcNwVSVHzn10BRBDbpHUU564wUMg39AT7j1qavrOpk qKXg== X-Gm-Message-State: AOAM533ds9rUA8JqTumjNn3BbQ4V/GUo4YtY2g0zJD4J32sM4EnTkOBj tgksYO2cIO8YEqhKqGsi8s4ZO+Q= X-Google-Smtp-Source: ABdhPJw5fsQ3RoCFa1nP/f8vQ2H/0kq6g1FRncqSilrT2QE6GxXwvg6EF2sSsuQKCxdSxG8sTnYy+A== X-Received: by 2002:a05:6830:1aed:: with SMTP id c13mr8244307otd.78.1592674444846; Sat, 20 Jun 2020 10:34:04 -0700 (PDT) Received: from serve.minyard.net (serve.minyard.net. [2001:470:b8f6:1b::1]) by smtp.gmail.com with ESMTPSA id p9sm2069158ota.24.2020.06.20.10.34.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Jun 2020 10:34:03 -0700 (PDT) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:f17b:b355:b0a4:2592]) by serve.minyard.net (Postfix) with ESMTPA id E13F0180561; Sat, 20 Jun 2020 17:34:00 +0000 (UTC) From: minyard@acm.org To: Guenter Roeck , Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org, Gabriele Paoloni , Corey Minyard Subject: [PATCH 6/6] watchdog:softdog: Convert to a millisecond watchdog Date: Sat, 20 Jun 2020 12:33:51 -0500 Message-Id: <20200620173351.18752-7-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200620173351.18752-1-minyard@acm.org> References: <20200620173351.18752-1-minyard@acm.org> Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org From: Corey Minyard Use milliseconds for the softdog timer to support a higher resolution timeout. Signed-off-by: Corey Minyard --- drivers/watchdog/softdog.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index 3e4885c1545e..794f552db53b 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c @@ -82,13 +82,13 @@ static int softdog_ping(struct watchdog_device *w) { if (!hrtimer_active(&softdog_ticktock)) __module_get(THIS_MODULE); - hrtimer_start(&softdog_ticktock, ktime_set(w->timeout, 0), + hrtimer_start(&softdog_ticktock, ms_to_ktime(w->timeout), HRTIMER_MODE_REL); if (IS_ENABLED(CONFIG_SOFT_WATCHDOG_PRETIMEOUT)) { if (w->pretimeout) hrtimer_start(&softdog_preticktock, - ktime_set(w->timeout - w->pretimeout, 0), + ms_to_ktime(w->timeout - w->pretimeout), HRTIMER_MODE_REL); else hrtimer_cancel(&softdog_preticktock); @@ -110,7 +110,8 @@ static int softdog_stop(struct watchdog_device *w) static struct watchdog_info softdog_info = { .identity = "Software Watchdog", - .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, + .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | + WDIOF_MSECTIMER), }; static const struct watchdog_ops softdog_ops = { @@ -123,15 +124,15 @@ static struct watchdog_device softdog_dev = { .info = &softdog_info, .ops = &softdog_ops, .min_timeout = 1, - .max_timeout = 65535, - .timeout = TIMER_MARGIN, + .max_timeout = 65535000, + .timeout = TIMER_MARGIN * 1000, }; static int __init softdog_init(void) { int ret; - watchdog_init_timeout(&softdog_dev, soft_margin, NULL); + watchdog_init_timeout(&softdog_dev, soft_margin * 1000, NULL); watchdog_set_nowayout(&softdog_dev, nowayout); watchdog_stop_on_reboot(&softdog_dev);