Sysfs based watchdog infrastructure
Subsystems (2)
PATCH 1/1 Sysfs based watchdog infrastructure
The following is a resubmit of the sysfs based watchdog driver infrastructure diff'ed against the 2.5.63 kernel, along with a few fixes for bugs that I have found will testing the ported softdog watchdog driver and the new zt55XX watchdog driver.
I also made the sysfs file creation based on the available support for a given feature. For example if your watchdog device doesn't not have the ability to provide a firmware version, and leaves the get_firmware_version function pointer as null, then there will be no 'firmware_version' file in your drivers sysfs directory.
The softdog driver does not support the status, bootstatus, temppanic (panic on over temperature), or the ability go get a firmware version.
static struct watchdog_ops softdog_ops = {
.start = softdog_start, .stop = softdog_stop, .keepalive = softdog_keepalive, .get_timeout = softdog_get_timeout, .set_timeout = softdog_set_timeout, .get_nowayout = softdog_get_nowayout, .set_nowayout = softdog_set_nowayout, .get_options = softdog_get_options, /* get_bootstatus not implemented */ /* get_status not implemented */ /* get/set_temppanic not implemented */ /* get_firmware_version not implemented */
};
Which translates into the following directory listing in sysfs:
[root@penguin2 root]# tree /sys/class/watchdog/drivers/system\:softdog/ /sys/class/watchdog/drivers/system:softdog/
|-- keepalive |-- nowayout |-- options |-- soft_noboot |-- start |-- stop
`-- timeout
drivers/char/watchdog/Makefile +2 -0
@@ -7,6 +7,8 @@ # watchdog dies or is 'borrowed' for some reason the software watchdog # still gives you some cover. +obj-y += base.o + obj-$(CONFIG_PCWATCHDOG) += pcwd.o obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
drivers/char/watchdog/base.c new file +623 -0
623 lines not on this page · raw message
include/linux/watchdog.h +36 -0
@@ -10,9 +10,17 @@#define _LINUX_WATCHDOG_H#include <linux/ioctl.h> +#include <linux/device.h> #define WATCHDOG_IOCTL_BASE 'W' +#define to_watchdog_driver (n) container_of(n, struct watchdog_driver, driver) + +struct watchdog_driver ; +struct watchdog_ops ; + +extern struct device_class watchdog_devclass; +struct watchdog_info {__u32 options;/* Options the card/driver supports */ __u32 firmware_version;/* Firmware version of the card */
@@ -46,4 +54,32 @@#define WDIOS_ENABLECARD 0x0002/* Turn on the watchdog timer */ #define WDIOS_TEMPPANIC 0x0004/* Kernel panic on temperature trip */ +#ifdef __KERNEL__ + +struct watchdog_driver { +struct watchdog_ops *ops; +struct device_driver driver; +}; + +struct watchdog_ops { +int (*start)(struct watchdog_driver *); +int (*stop)(struct watchdog_driver *); +int (*keepalive)(struct watchdog_driver *); +int (*get_timeout)(struct watchdog_driver *,int *); +int (*set_timeout)(struct watchdog_driver *,int ); +int (*get_nowayout)(struct watchdog_driver *,int *); +int (*set_nowayout)(struct watchdog_driver *,int ); +int (*get_status)(struct watchdog_driver *,int *); +int (*get_bootstatus)(struct watchdog_driver *,int *); +int (*get_options)(struct watchdog_driver *,int *); +int (*get_temperature)(struct watchdog_driver *,int *); +int (*get_temppanic)(struct watchdog_driver *,int *); +int (*set_temppanic)(struct watchdog_driver *,int ); +int (*get_firmware_version)(struct watchdog_driver *,int *); +}; + +int watchdog_driver_register (struct watchdog_driver *); +void watchdog_driver_unregister (struct watchdog_driver *); + +#endif /* ifdef __KERNEL__ */ #endif /* ifndef _LINUX_WATCHDOG_H */
Here is a port of the softdog watchdog driver for the new infrastructure.
--rustyl
drivers/char/watchdog/softdog.c +122 -113
@@ -1,5 +1,5 @@/* -* SoftDog 0.06: A Software Watchdog Device +* SoftDog 0.07: A Software Watchdog Device * * (c) Copyright 1996 Alan Cox <[email protected]>, All Rights Reserved. * http://www.redhat.com
@@ -34,52 +34,41 @@* * 20020530 Joel Becker <[email protected]> * Added Matt Domsch's nowayout module option. +* +* 20030221 Rusty Lynch <[email protected]> +* Moved implementation to use the new watchdog infrastructure. This +* adds the softdog to the sysfs topography and moves the common +* miscdevice functions to the infrastructure as well. +* */ #include <linux/module.h> +#include <linux/moduleparam.h> #include <linux/config.h> #include <linux/types.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/reboot.h> #include <linux/init.h> #include <asm/uaccess.h> #define TIMER_MARGIN 60/* (secs) Default is 1 minute */ - -static int expect_close =0 ;static int soft_margin =TIMER_MARGIN ;/* in seconds */ -#ifdef ONLY_TESTING -static int soft_noboot =1 ; -#else -static int soft_noboot =0 ; -#endif /* ONLY_TESTING */ +module_param (soft_margin,int,0 ); +MODULE_PARM_DESC (soft_margin,"Watchdog timer margin (timeout) in seconds" ); -MODULE_PARM (soft_margin,"i" ); -MODULE_PARM (soft_noboot,"i" ); -MODULE_LICENSE ("GPL" ); +static int soft_noboot =0 ; +module_param (soft_noboot,int,0 ); +MODULE_PARM_DESC (soft_noboot,"Disable machine restarts on watchdog timeout" );#ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout =1 ;#else static int nowayout =0 ;#endif - -MODULE_PARM (nowayout,"i" ); +module_param (nowayout,int,0 );MODULE_PARM_DESC (nowayout,"Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)" );/* -* Our timer -*/ - -static void watchdog_fire (unsigned long ); - -static struct timer_list watchdog_ticktock = -TIMER_INITIALIZER (watchdog_fire,0 ,0 ); -static unsigned long timer_alive; - - -/* * If the timer expires.. */
@@ -96,135 +85,155 @@ }/* -* Allow only one person to hold it open +* Software timer */ -static int softdog_open (struct inode *inode,struct file *file) -{ -if (test_and_set_bit (0 , &timer_alive)) -return -EBUSY ; +static struct timer_list watchdog_ticktock = +TIMER_INITIALIZER (watchdog_fire,0 ,0 ); -/* -* Activate timer -*/ + +/* +* Watchdog ops callback functions +*/ + +static int softdog_start (struct watchdog_driver *d) +{mod_timer (&watchdog_ticktock, jiffies+(soft_margin*HZ ));return 0 ; } -static int softdog_release (struct inode *inode,struct file *file) +static int softdog_stop (struct watchdog_driver *d) { -/* -* Shut off the timer. -* Lock it in if it's a module and we set nowayout -*/ -if (expect_close) { -del_timer (&watchdog_ticktock); - }else { -printk (KERN_CRIT "SOFTDOG: WDT device closed unexpectedly. WDT will not stop!\n" ); +if (nowayout) { +printk (KERN_CRIT "SOFTDOG: WDT device closed unexpectedly. " +"WDT will not stop!\n" ); +return -1 ; } -clear_bit (0 , &timer_alive); + +del_timer (&watchdog_ticktock);return 0 ; } -static ssize_t softdog_write (struct file *file,const char *data,size_t len,loff_t *ppos) +static int softdog_keepalive (struct watchdog_driver *d) { -/* Can't seek (pwrite) on this device */ -if (ppos != &file->f_pos) -return -ESPIPE ; +mod_timer (&watchdog_ticktock, jiffies+(soft_margin*HZ )); +return 0 ; +} + +static int softdog_get_timeout (struct watchdog_driver *d,int *timeout) +{ + *timeout = soft_margin; +return 0 ; +} -/* -* Refresh the timer. -*/ -if (len) { -if (!nowayout) { -size_t i; +static int softdog_set_timeout (struct watchdog_driver *d,int timeout) +{ +if (timeout <1 ) +return -1 ; -/* In case it was set long ago */ - expect_close =0 ; + soft_margin = timeout; +if (timer_pending (&watchdog_ticktock)) +mod_timer (&watchdog_ticktock, jiffies+(soft_margin*HZ )); +return 0 ; +} -for (i =0 ; i != len; i++) { -char c; +static int softdog_get_options (struct watchdog_driver *d,int *options) +{ + *options =WDIOF_SETTIMEOUT |WDIOF_KEEPALIVEPING ; +return 0 ; +} -if (get_user (c, data + i)) -return -EFAULT ; -if (c =='V' ) - expect_close =1 ; - } - } -mod_timer (&watchdog_ticktock, jiffies+(soft_margin*HZ )); -return 1 ; - } +static int softdog_get_nowayout (struct watchdog_driver *d,int *n) +{ + *n = nowayout;return 0 ; } -static int softdog_ioctl (struct inode *inode,struct file *file, -unsigned int cmd,unsigned long arg) +static int softdog_set_nowayout (struct watchdog_driver *d,int n) { -int new_margin; -static struct watchdog_info ident = { - .options =WDIOF_SETTIMEOUT |WDIOF_MAGICCLOSE , - .identity ="Software Watchdog" , - }; -switch (cmd) { -default : -return -ENOTTY ; -case WDIOC_GETSUPPORT : -if (copy_to_user ((struct watchdog_info *)arg, &ident,sizeof (ident))) -return -EFAULT ; -return 0 ; -case WDIOC_GETSTATUS : -case WDIOC_GETBOOTSTATUS : -return put_user (0 ,(int *)arg); -case WDIOC_KEEPALIVE : -mod_timer (&watchdog_ticktock, jiffies+(soft_margin*HZ )); -return 0 ; -case WDIOC_SETTIMEOUT : -if (get_user (new_margin, (int *)arg)) -return -EFAULT ; -if (new_margin <1 ) -return -EINVAL ; - soft_margin = new_margin; -mod_timer (&watchdog_ticktock, jiffies+(soft_margin*HZ )); -/* Fall */ -case WDIOC_GETTIMEOUT : -return put_user (soft_margin, (int *)arg); - } +if (n) + nowayout =1 ; +else + nowayout =0 ; +return 0 ; } -static struct file_operations softdog_fops = { - .owner =THIS_MODULE , - .write = softdog_write, - .ioctl = softdog_ioctl, - .open = softdog_open, - .release = softdog_release, +/* +* Structures required to register as a watchdog driver +*/ + +static struct watchdog_ops softdog_ops = { + .start = softdog_start, + .stop = softdog_stop, + .keepalive = softdog_keepalive, + .get_timeout = softdog_get_timeout, + .set_timeout = softdog_set_timeout, + .get_nowayout = softdog_get_nowayout, + .set_nowayout = softdog_set_nowayout, + .get_options = softdog_get_options, +/* get_bootstatus not implemented */ +/* get_status not implemented */ +/* get/set_temppanic not implemented */ +/* get_firmware_version not implemented */ }; -static struct miscdevice softdog_miscdev = { - .minor =WATCHDOG_MINOR , - .name ="watchdog" , - .fops = &softdog_fops, +static struct watchdog_driver softdog_driver = { + .ops = &softdog_ops, + .driver = { + .name ="softdog" , + .bus = &system_bus_type, + .devclass = &watchdog_devclass, + } }; -static char banner[]__initdata =KERN_INFO "Software Watchdog Timer: 0.06, soft_margin: %d sec, nowayout: %d\n" ; +/* +* enable testing the of driver to not cause a machine restart +*/ + +static ssize_t soft_noboot_show (struct device_driver * d,char * buf) +{ +return sprintf (buf,"%i\n" ,soft_noboot); +} +static ssize_t soft_noboot_store (struct device_driver *d,const char * buf, +size_t count) +{ +int tmp; + +if (sscanf (buf,"%i" ,&tmp) !=1 ) +return -EINVAL ; + +if (tmp) + soft_noboot =1 ; +else + soft_noboot =0 ; +return count; +} +DRIVER_ATTR (soft_noboot,0644 ,soft_noboot_show,soft_noboot_store); + +static char banner[]__initdata =KERN_INFO "Software Watchdog Timer: 0.07, soft_margin: %d sec, nowayout: %d\n" ;static int __init watchdog_init (void ) {int ret; - ret =misc_register (&softdog_miscdev); - + ret =watchdog_driver_register (&softdog_driver);if (ret)return ret; +driver_create_file (&softdog_driver.driver, &driver_attr_soft_noboot);printk (banner, soft_margin, nowayout); -return 0 ; } static void __exit watchdog_exit(void) -{ -misc_deregister (&softdog_miscdev); +{ +driver_remove_file (&softdog_driver.driver, &driver_attr_soft_noboot); +watchdog_driver_unregister (&softdog_driver); + +/* ensure somebody didn't leave the watchdog ticking */ +del_timer (&watchdog_ticktock); }module_init (watchdog_init);module_exit (watchdog_exit); +MODULE_LICENSE ("GPL" );
Here is a new watchdog driver for the ZT55XX line of CompactPCI single board computers that utilizes the watchdog infrastructure.
--rustyl
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas:
# ChangeSet 1.1132 -> 1.1133
# drivers/char/watchdog/Kconfig 1.8 -> 1.9
# drivers/char/watchdog/Makefile 1.8 -> 1.9
# (new) -> 1.1 drivers/char/watchdog/ztwd.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/02/28 [email protected] 1.1133
# Adding the ztwd watchdog timer
# --------------------------------------------
#
drivers/char/watchdog/Kconfig +14 -0
@@ -377,4 +377,18 @@ The module is called cpu5wdt.o. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. +config ZT55XX_WDT + tristate "ZT55XX Single Board Computer Watchdog" + depends on WATCHDOG + help + This is a driver for the hardware watchdog on the ZT55XX line + of CompactPCI single board computers originally sold by Ziatech, + and then Intel, and then Performance Technologies. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + If you want to compile it as a module, say M here and read + Documentation/modules.txt. The module will be called + ztwd.ko + endmenu
drivers/char/watchdog/Makefile +1 -0
@@ -33,3 +33,4 @@ obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o +obj-$(CONFIG_ZT55XX_WDT) += ztwd.o
drivers/char/watchdog/ztwd.c new file +390 -0
390 lines not on this page · raw message