Merge tag 'linux-watchdog-5.9-rc1' of git://www.linux-watchdog.org/linux-watchdog

Pull watchdog updates from Wim Van Sebroeck:

 - f71808e_wdt imporvements

 - dw_wdt improvements

 - mlx-wdt: support new watchdog type with longer timeout period

 - fallthrough pseudo-keyword replacements

 - overall small fixes and improvements

* tag 'linux-watchdog-5.9-rc1' of git://www.linux-watchdog.org/linux-watchdog: (35 commits)
  watchdog: rti-wdt: balance pm runtime enable calls
  watchdog: rti-wdt: attach to running watchdog during probe
  watchdog: add support for adjusting last known HW keepalive time
  watchdog: use __watchdog_ping in startup
  watchdog: softdog: Add options 'soft_reboot_cmd' and 'soft_active_on_boot'
  watchdog: pcwd_usb: remove needless check before usb_free_coherent()
  watchdog: Replace HTTP links with HTTPS ones
  dt-bindings: watchdog: renesas,wdt: Document r8a774e1 support
  watchdog: initialize device before misc_register
  watchdog: booke_wdt: Add common nowayout parameter driver
  watchdog: scx200_wdt: Use fallthrough pseudo-keyword
  watchdog: Use fallthrough pseudo-keyword
  watchdog: f71808e_wdt: do stricter parameter validation
  watchdog: f71808e_wdt: clear watchdog timeout occurred flag
  watchdog: f71808e_wdt: remove use of wrong watchdog_info option
  watchdog: f71808e_wdt: indicate WDIOF_CARDRESET support in watchdog_info.options
  docs: watchdog: codify ident.options as superset of possible status flags
  dt-bindings: watchdog: Add compatible for QCS404, SC7180, SDM845, SM8150
  dt-bindings: watchdog: Convert QCOM watchdog timer bindings to YAML
  watchdog: dw_wdt: Add DebugFS files
  ...
This commit is contained in:
Linus Torvalds
2020-08-12 12:13:44 -07:00
62 changed files with 1033 additions and 211 deletions

View File

@@ -275,15 +275,18 @@ static int watchdog_start(struct watchdog_device *wdd)
set_bit(_WDOG_KEEPALIVE, &wd_data->status);
started_at = ktime_get();
if (watchdog_hw_running(wdd) && wdd->ops->ping)
err = wdd->ops->ping(wdd);
else
if (watchdog_hw_running(wdd) && wdd->ops->ping) {
err = __watchdog_ping(wdd);
if (err == 0)
set_bit(WDOG_ACTIVE, &wdd->status);
} else {
err = wdd->ops->start(wdd);
if (err == 0) {
set_bit(WDOG_ACTIVE, &wdd->status);
wd_data->last_keepalive = started_at;
wd_data->last_hw_keepalive = started_at;
watchdog_update_worker(wdd);
if (err == 0) {
set_bit(WDOG_ACTIVE, &wdd->status);
wd_data->last_keepalive = started_at;
wd_data->last_hw_keepalive = started_at;
watchdog_update_worker(wdd);
}
}
return err;
@@ -587,7 +590,7 @@ static DEVICE_ATTR_RW(pretimeout_governor);
static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr,
int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct watchdog_device *wdd = dev_get_drvdata(dev);
umode_t mode = attr->mode;
@@ -776,7 +779,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
err = watchdog_ping(wdd);
if (err < 0)
break;
/* fall through */
fallthrough;
case WDIOC_GETTIMEOUT:
/* timeout == 0 means that we don't know the timeout */
if (wdd->timeout == 0) {
@@ -916,7 +919,7 @@ static int watchdog_release(struct inode *inode, struct file *file)
* or if WDIOF_MAGICCLOSE is not set. If nowayout was set then
* watchdog_stop will fail.
*/
if (!test_bit(WDOG_ACTIVE, &wdd->status))
if (!watchdog_active(wdd))
err = 0;
else if (test_and_clear_bit(_WDOG_ALLOW_RELEASE, &wd_data->status) ||
!(wdd->info->options & WDIOF_MAGICCLOSE))
@@ -994,6 +997,15 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
if (IS_ERR_OR_NULL(watchdog_kworker))
return -ENODEV;
device_initialize(&wd_data->dev);
wd_data->dev.devt = MKDEV(MAJOR(watchdog_devt), wdd->id);
wd_data->dev.class = &watchdog_class;
wd_data->dev.parent = wdd->parent;
wd_data->dev.groups = wdd->groups;
wd_data->dev.release = watchdog_core_data_release;
dev_set_drvdata(&wd_data->dev, wdd);
dev_set_name(&wd_data->dev, "watchdog%d", wdd->id);
kthread_init_work(&wd_data->work, watchdog_ping_work);
hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
wd_data->timer.function = watchdog_timer_expired;
@@ -1014,15 +1026,6 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
}
}
device_initialize(&wd_data->dev);
wd_data->dev.devt = MKDEV(MAJOR(watchdog_devt), wdd->id);
wd_data->dev.class = &watchdog_class;
wd_data->dev.parent = wdd->parent;
wd_data->dev.groups = wdd->groups;
wd_data->dev.release = watchdog_core_data_release;
dev_set_drvdata(&wd_data->dev, wdd);
dev_set_name(&wd_data->dev, "watchdog%d", wdd->id);
/* Fill in the data structures */
cdev_init(&wd_data->cdev, &watchdog_fops);
@@ -1135,6 +1138,36 @@ void watchdog_dev_unregister(struct watchdog_device *wdd)
watchdog_cdev_unregister(wdd);
}
/*
* watchdog_set_last_hw_keepalive: set last HW keepalive time for watchdog
* @wdd: watchdog device
* @last_ping_ms: time since last HW heartbeat
*
* Adjusts the last known HW keepalive time for a watchdog timer.
* This is needed if the watchdog is already running when the probe
* function is called, and it can't be pinged immediately. This
* function must be called immediately after watchdog registration,
* and min_hw_heartbeat_ms must be set for this to be useful.
*/
int watchdog_set_last_hw_keepalive(struct watchdog_device *wdd,
unsigned int last_ping_ms)
{
struct watchdog_core_data *wd_data;
ktime_t now;
if (!wdd)
return -EINVAL;
wd_data = wdd->wd_data;
now = ktime_get();
wd_data->last_hw_keepalive = ktime_sub(now, ms_to_ktime(last_ping_ms));
return __watchdog_ping(wdd);
}
EXPORT_SYMBOL_GPL(watchdog_set_last_hw_keepalive);
/*
* watchdog_dev_init: init dev part of watchdog core
*