From 257f8c4aae392654d4ab846030b9f4518f16ed32 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 12 Mar 2012 09:51:56 +0530 Subject: watchdog: Add watchdog_active() routine Some watchdog may need to check if watchdog is ACTIVE or not, for example in their suspend/resume hooks. This patch adds this routine and changes the core drivers to use it. Signed-off-by: Viresh Kumar Signed-off-by: Wim Van Sebroeck --- include/linux/watchdog.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index ac40716b44e9..1984ea610577 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h @@ -128,6 +128,12 @@ struct watchdog_device { #define WATCHDOG_NOWAYOUT_INIT_STATUS 0 #endif +/* Use the following function to check wether or not the watchdog is active */ +static inline bool watchdog_active(struct watchdog_device *wdd) +{ + return test_bit(WDOG_ACTIVE, &wdd->status); +} + /* Use the following function to set the nowayout feature */ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool nowayout) { -- cgit From 45f5fed30a6460ec58f159ff297a2974153a97de Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 10 May 2012 21:48:59 +0200 Subject: watchdog: Add multiple device support We keep the old /dev/watchdog interface file for the first watchdog via miscdev. This is basically a cut and paste of the relevant interface code from the rtc driver layer tweaked for watchdog. Revised to fix problems noted by Hans de Goede Signed-off-by: Alan Cox Signed-off-by: Hans de Goede Signed-off-by: Tomas Winkler Signed-off-by: Wim Van Sebroeck --- include/linux/watchdog.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index 1984ea610577..508d56399e6d 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h @@ -54,6 +54,8 @@ struct watchdog_info { #ifdef __KERNEL__ #include +#include +#include struct watchdog_ops; struct watchdog_device; @@ -89,6 +91,8 @@ struct watchdog_ops { /** struct watchdog_device - The structure that defines a watchdog device * + * @id: The watchdog's ID. (Allocated by watchdog_register_device) + * @cdev: The watchdog's Character device. * @info: Pointer to a watchdog_info structure. * @ops: Pointer to the list of watchdog operations. * @bootstatus: Status of the watchdog device at boot. @@ -105,6 +109,8 @@ struct watchdog_ops { * via the watchdog_set_drvdata and watchdog_get_drvdata helpers. */ struct watchdog_device { + int id; + struct cdev cdev; const struct watchdog_info *info; const struct watchdog_ops *ops; unsigned int bootstatus; -- cgit From 2bbeed016dd96045ec82c3a309afddcc3a0db1d2 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 11 May 2012 12:00:19 +0200 Subject: watchdog: Add a flag to indicate the watchdog doesn't reboot things Some watchdogs merely trigger external alarms and controls. In a managed environment this is very useful but we want drivers to be able to figure out which is which now multiple dogs can be loaded. Thus add an ALARMONLY feature flag. Signed-off-by: Alan Cox Signed-off-by: Hans de Goede Signed-off-by: Wim Van Sebroeck --- include/linux/watchdog.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index 508d56399e6d..32678a50f98d 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h @@ -45,6 +45,8 @@ struct watchdog_info { #define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */ #define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */ #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_KEEPALIVEPING 0x8000 /* Keep alive ping reply */ #define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */ -- cgit From d6b469d915ae348b3bb8b25034063d6870ff4a00 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 11 May 2012 12:00:20 +0200 Subject: watchdog: create all the proper device files Create the watchdog class and it's associated devices. Signed-off-by: Alan Cox Signed-off-by: Hans de Goede Signed-off-by: Wim Van Sebroeck --- include/linux/watchdog.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux') diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index 32678a50f98d..c3545c5d918a 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h @@ -95,6 +95,8 @@ struct watchdog_ops { * * @id: The watchdog's ID. (Allocated by watchdog_register_device) * @cdev: The watchdog's Character device. + * @dev: The device for our watchdog + * @parent: The parent bus device * @info: Pointer to a watchdog_info structure. * @ops: Pointer to the list of watchdog operations. * @bootstatus: Status of the watchdog device at boot. @@ -113,6 +115,8 @@ struct watchdog_ops { struct watchdog_device { int id; struct cdev cdev; + struct device *dev; + struct device *parent; const struct watchdog_info *info; const struct watchdog_ops *ops; unsigned int bootstatus; -- cgit From f4e9c82f64b524314a390b13d3ba7d483f09258f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 22 May 2012 11:40:26 +0200 Subject: watchdog: Add Locking support This patch fixes some potential multithreading issues, despite only allowing one process to open the /dev/watchdog device, we can still get called multiple times at the same time, since a program could be using thread, or could share the fd after a fork. This causes 2 potential problems: 1) watchdog_start / open do an unlocked test_n_set / test_n_clear, if these 2 race, the watchdog could be stopped while the active bit indicates it is running or visa versa. 2) Most watchdog_dev drivers probably assume that only one watchdog-op will get called at a time, this is not necessary true atm. Signed-off-by: Hans de Goede Signed-off-by: Wim Van Sebroeck --- include/linux/watchdog.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index c3545c5d918a..da1dc1b52744 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h @@ -104,6 +104,7 @@ struct watchdog_ops { * @min_timeout:The watchdog devices minimum timeout value. * @max_timeout:The watchdog devices maximum timeout value. * @driver-data:Pointer to the drivers private data. + * @lock: Lock for watchdog core internal use only. * @status: Field that contains the devices internal status bits. * * The watchdog_device structure contains all information about a @@ -111,6 +112,9 @@ struct watchdog_ops { * * The driver-data field may not be accessed directly. It must be accessed * via the watchdog_set_drvdata and watchdog_get_drvdata helpers. + * + * The lock field is for watchdog core internal use only and should not be + * touched. */ struct watchdog_device { int id; @@ -124,6 +128,7 @@ struct watchdog_device { unsigned int min_timeout; unsigned int max_timeout; void *driver_data; + struct mutex lock; unsigned long status; /* Bit numbers for status flags */ #define WDOG_ACTIVE 0 /* Is the watchdog running/active */ -- cgit From e907df32725204d6d2cb79b872529911c8eadcdf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 22 May 2012 11:40:26 +0200 Subject: watchdog: Add support for dynamically allocated watchdog_device structs If a driver's watchdog_device struct is part of a dynamically allocated struct (which it often will be), merely locking the module is not enough, even with a drivers module locked, the driver can be unbound from the device, examples: 1) The root user can unbind it through sysfd 2) The i2c bus master driver being unloaded for an i2c watchdog I will gladly admit that these are corner cases, but we still need to handle them correctly. The fix for this consists of 2 parts: 1) Add ref / unref operations, so that the driver can refcount the struct holding the watchdog_device struct and delay freeing it until any open filehandles referring to it are closed 2) Most driver operations will do IO on the device and the driver should not do any IO on the device after it has been unbound. Rather then letting each driver deal with this internally, it is better to ensure at the watchdog core level that no operations (other then unref) will get called after the driver has called watchdog_unregister_device(). This actually is the bulk of this patch. Signed-off-by: Hans de Goede Signed-off-by: Wim Van Sebroeck --- include/linux/watchdog.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index da1dc1b52744..da70f0facd2b 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h @@ -71,6 +71,8 @@ struct watchdog_device; * @status: The routine that shows the status of the watchdog device. * @set_timeout:The routine for setting the watchdog devices timeout value. * @get_timeleft:The routine that get's the time that's left before a reset. + * @ref: The ref operation for dyn. allocated watchdog_device structs + * @unref: The unref operation for dyn. allocated watchdog_device structs * @ioctl: The routines that handles extra ioctl calls. * * The watchdog_ops structure contains a list of low-level operations @@ -88,6 +90,8 @@ struct watchdog_ops { unsigned int (*status)(struct watchdog_device *); int (*set_timeout)(struct watchdog_device *, unsigned int); unsigned int (*get_timeleft)(struct watchdog_device *); + void (*ref)(struct watchdog_device *); + void (*unref)(struct watchdog_device *); long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); }; @@ -135,6 +139,7 @@ struct watchdog_device { #define WDOG_DEV_OPEN 1 /* Opened via /dev/watchdog ? */ #define WDOG_ALLOW_RELEASE 2 /* Did we receive the magic char ? */ #define WDOG_NO_WAY_OUT 3 /* Is 'nowayout' feature set ? */ +#define WDOG_UNREGISTERED 4 /* Has the device been unregistered */ }; #ifdef CONFIG_WATCHDOG_NOWAYOUT -- cgit