Commit 43316044d4f64da008d6aca7d4b60771b9a24eb8

Authored by Wim Van Sebroeck
1 parent 5efc7a6222

watchdog: WatchDog Timer Driver Core - Add basic framework

The WatchDog Timer Driver Core is a framework
that contains the common code for all watchdog-driver's.
It also introduces a watchdog device structure and the
operations that go with it.

This is the introduction of this framework. This part
supports the minimal watchdog userspace API (or with
other words: the functionality to use /dev/watchdog's
open, release and write functionality as defined in
the simplest watchdog API). Extra functionality will
follow in the next set of patches.

Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>

Showing 8 changed files with 566 additions and 0 deletions Side-by-side Diff

Documentation/watchdog/00-INDEX
... ... @@ -8,6 +8,8 @@
8 8 - directory holding watchdog related example programs.
9 9 watchdog-api.txt
10 10 - description of the Linux Watchdog driver API.
  11 +watchdog-kernel-api.txt
  12 + - description of the Linux WatchDog Timer Driver Core kernel API.
11 13 watchdog-parameters.txt
12 14 - information on driver parameters (for drivers other than
13 15 the ones that have driver-specific files here)
Documentation/watchdog/watchdog-kernel-api.txt
  1 +The Linux WatchDog Timer Driver Core kernel API.
  2 +===============================================
  3 +Last reviewed: 22-Jul-2011
  4 +
  5 +Wim Van Sebroeck <wim@iguana.be>
  6 +
  7 +Introduction
  8 +------------
  9 +This document does not describe what a WatchDog Timer (WDT) Driver or Device is.
  10 +It also does not describe the API which can be used by user space to communicate
  11 +with a WatchDog Timer. If you want to know this then please read the following
  12 +file: Documentation/watchdog/watchdog-api.txt .
  13 +
  14 +So what does this document describe? It describes the API that can be used by
  15 +WatchDog Timer Drivers that want to use the WatchDog Timer Driver Core
  16 +Framework. This framework provides all interfacing towards user space so that
  17 +the same code does not have to be reproduced each time. This also means that
  18 +a watchdog timer driver then only needs to provide the different routines
  19 +(operations) that control the watchdog timer (WDT).
  20 +
  21 +The API
  22 +-------
  23 +Each watchdog timer driver that wants to use the WatchDog Timer Driver Core
  24 +must #include <linux/watchdog.h> (you would have to do this anyway when
  25 +writing a watchdog device driver). This include file contains following
  26 +register/unregister routines:
  27 +
  28 +extern int watchdog_register_device(struct watchdog_device *);
  29 +extern void watchdog_unregister_device(struct watchdog_device *);
  30 +
  31 +The watchdog_register_device routine registers a watchdog timer device.
  32 +The parameter of this routine is a pointer to a watchdog_device structure.
  33 +This routine returns zero on success and a negative errno code for failure.
  34 +
  35 +The watchdog_unregister_device routine deregisters a registered watchdog timer
  36 +device. The parameter of this routine is the pointer to the registered
  37 +watchdog_device structure.
  38 +
  39 +The watchdog device structure looks like this:
  40 +
  41 +struct watchdog_device {
  42 + const struct watchdog_info *info;
  43 + const struct watchdog_ops *ops;
  44 + void *driver_data;
  45 + unsigned long status;
  46 +};
  47 +
  48 +It contains following fields:
  49 +* info: a pointer to a watchdog_info structure. This structure gives some
  50 + additional information about the watchdog timer itself. (Like it's unique name)
  51 +* ops: a pointer to the list of watchdog operations that the watchdog supports.
  52 +* driver_data: a pointer to the drivers private data of a watchdog device.
  53 + This data should only be accessed via the watchdog_set_drvadata and
  54 + watchdog_get_drvdata routines.
  55 +* status: this field contains a number of status bits that give extra
  56 + information about the status of the device (Like: is the device opened via
  57 + the /dev/watchdog interface or not, ...).
  58 +
  59 +The list of watchdog operations is defined as:
  60 +
  61 +struct watchdog_ops {
  62 + struct module *owner;
  63 + /* mandatory operations */
  64 + int (*start)(struct watchdog_device *);
  65 + int (*stop)(struct watchdog_device *);
  66 + /* optional operations */
  67 + int (*ping)(struct watchdog_device *);
  68 +};
  69 +
  70 +It is important that you first define the module owner of the watchdog timer
  71 +driver's operations. This module owner will be used to lock the module when
  72 +the watchdog is active. (This to avoid a system crash when you unload the
  73 +module and /dev/watchdog is still open).
  74 +Some operations are mandatory and some are optional. The mandatory operations
  75 +are:
  76 +* start: this is a pointer to the routine that starts the watchdog timer
  77 + device.
  78 + The routine needs a pointer to the watchdog timer device structure as a
  79 + parameter. It returns zero on success or a negative errno code for failure.
  80 +* stop: with this routine the watchdog timer device is being stopped.
  81 + The routine needs a pointer to the watchdog timer device structure as a
  82 + parameter. It returns zero on success or a negative errno code for failure.
  83 + Some watchdog timer hardware can only be started and not be stopped. The
  84 + driver supporting this hardware needs to make sure that a start and stop
  85 + routine is being provided. This can be done by using a timer in the driver
  86 + that regularly sends a keepalive ping to the watchdog timer hardware.
  87 +
  88 +Not all watchdog timer hardware supports the same functionality. That's why
  89 +all other routines/operations are optional. They only need to be provided if
  90 +they are supported. These optional routines/operations are:
  91 +* ping: this is the routine that sends a keepalive ping to the watchdog timer
  92 + hardware.
  93 + The routine needs a pointer to the watchdog timer device structure as a
  94 + parameter. It returns zero on success or a negative errno code for failure.
  95 + Most hardware that does not support this as a separate function uses the
  96 + start function to restart the watchdog timer hardware. And that's also what
  97 + the watchdog timer driver core does: to send a keepalive ping to the watchdog
  98 + timer hardware it will either use the ping operation (when available) or the
  99 + start operation (when the ping operation is not available).
  100 +
  101 +The status bits should (preferably) be set with the set_bit and clear_bit alike
  102 +bit-operations. The status bits that are defined are:
  103 +* WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device
  104 + was opened via /dev/watchdog.
  105 + (This bit should only be used by the WatchDog Timer Driver Core).
  106 +
  107 +To get or set driver specific data the following two helper functions should be
  108 +used:
  109 +
  110 +static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
  111 +static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
  112 +
  113 +The watchdog_set_drvdata function allows you to add driver specific data. The
  114 +arguments of this function are the watchdog device where you want to add the
  115 +driver specific data to and a pointer to the data itself.
  116 +
  117 +The watchdog_get_drvdata function allows you to retrieve driver specific data.
  118 +The argument of this function is the watchdog device where you want to retrieve
  119 +data from. The function retruns the pointer to the driver specific data.
drivers/watchdog/Kconfig
... ... @@ -28,6 +28,17 @@
28 28  
29 29 if WATCHDOG
30 30  
  31 +config WATCHDOG_CORE
  32 + bool "WatchDog Timer Driver Core"
  33 + ---help---
  34 + Say Y here if you want to use the new watchdog timer driver core.
  35 + This driver provides a framework for all watchdog timer drivers
  36 + and gives them the /dev/watchdog interface (and later also the
  37 + sysfs interface).
  38 +
  39 + To compile this driver as a module, choose M here: the module will
  40 + be called watchdog.
  41 +
31 42 config WATCHDOG_NOWAYOUT
32 43 bool "Disable watchdog shutdown on close"
33 44 help
drivers/watchdog/Makefile
... ... @@ -2,6 +2,10 @@
2 2 # Makefile for the WatchDog device drivers.
3 3 #
4 4  
  5 +# The WatchDog Timer Driver Core.
  6 +watchdog-objs += watchdog_core.o watchdog_dev.o
  7 +obj-$(CONFIG_WATCHDOG_CORE) += watchdog.o
  8 +
5 9 # Only one watchdog can succeed. We probe the ISA/PCI/USB based
6 10 # watchdog-cards first, then the architecture specific watchdog
7 11 # drivers and then the architecture independent "softdog" driver.
drivers/watchdog/watchdog_core.c
  1 +/*
  2 + * watchdog_core.c
  3 + *
  4 + * (c) Copyright 2008-2011 Alan Cox <alan@lxorguk.ukuu.org.uk>,
  5 + * All Rights Reserved.
  6 + *
  7 + * (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>.
  8 + *
  9 + * This source code is part of the generic code that can be used
  10 + * by all the watchdog timer drivers.
  11 + *
  12 + * Based on source code of the following authors:
  13 + * Matt Domsch <Matt_Domsch@dell.com>,
  14 + * Rob Radez <rob@osinvestor.com>,
  15 + * Rusty Lynch <rusty@linux.co.intel.com>
  16 + * Satyam Sharma <satyam@infradead.org>
  17 + * Randy Dunlap <randy.dunlap@oracle.com>
  18 + *
  19 + * This program is free software; you can redistribute it and/or
  20 + * modify it under the terms of the GNU General Public License
  21 + * as published by the Free Software Foundation; either version
  22 + * 2 of the License, or (at your option) any later version.
  23 + *
  24 + * Neither Alan Cox, CymruNet Ltd., Wim Van Sebroeck nor Iguana vzw.
  25 + * admit liability nor provide warranty for any of this software.
  26 + * This material is provided "AS-IS" and at no charge.
  27 + */
  28 +
  29 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  30 +
  31 +#include <linux/module.h> /* For EXPORT_SYMBOL/module stuff/... */
  32 +#include <linux/types.h> /* For standard types */
  33 +#include <linux/errno.h> /* For the -ENODEV/... values */
  34 +#include <linux/kernel.h> /* For printk/panic/... */
  35 +#include <linux/watchdog.h> /* For watchdog specific items */
  36 +#include <linux/init.h> /* For __init/__exit/... */
  37 +
  38 +#include "watchdog_dev.h" /* For watchdog_dev_register/... */
  39 +
  40 +/**
  41 + * watchdog_register_device() - register a watchdog device
  42 + * @wdd: watchdog device
  43 + *
  44 + * Register a watchdog device with the kernel so that the
  45 + * watchdog timer can be accessed from userspace.
  46 + *
  47 + * A zero is returned on success and a negative errno code for
  48 + * failure.
  49 + */
  50 +int watchdog_register_device(struct watchdog_device *wdd)
  51 +{
  52 + int ret;
  53 +
  54 + if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
  55 + return -EINVAL;
  56 +
  57 + /* Mandatory operations need to be supported */
  58 + if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
  59 + return -EINVAL;
  60 +
  61 + /*
  62 + * Note: now that all watchdog_device data has been verified, we
  63 + * will not check this anymore in other functions. If data gets
  64 + * corrupted in a later stage then we expect a kernel panic!
  65 + */
  66 +
  67 + /* We only support 1 watchdog device via the /dev/watchdog interface */
  68 + ret = watchdog_dev_register(wdd);
  69 + if (ret) {
  70 + pr_err("error registering /dev/watchdog (err=%d).\n", ret);
  71 + return ret;
  72 + }
  73 +
  74 + return 0;
  75 +}
  76 +EXPORT_SYMBOL_GPL(watchdog_register_device);
  77 +
  78 +/**
  79 + * watchdog_unregister_device() - unregister a watchdog device
  80 + * @wdd: watchdog device to unregister
  81 + *
  82 + * Unregister a watchdog device that was previously successfully
  83 + * registered with watchdog_register_device().
  84 + */
  85 +void watchdog_unregister_device(struct watchdog_device *wdd)
  86 +{
  87 + int ret;
  88 +
  89 + if (wdd == NULL)
  90 + return;
  91 +
  92 + ret = watchdog_dev_unregister(wdd);
  93 + if (ret)
  94 + pr_err("error unregistering /dev/watchdog (err=%d).\n", ret);
  95 +}
  96 +EXPORT_SYMBOL_GPL(watchdog_unregister_device);
  97 +
  98 +MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>");
  99 +MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
  100 +MODULE_DESCRIPTION("WatchDog Timer Driver Core");
  101 +MODULE_LICENSE("GPL");
drivers/watchdog/watchdog_dev.c
  1 +/*
  2 + * watchdog_dev.c
  3 + *
  4 + * (c) Copyright 2008-2011 Alan Cox <alan@lxorguk.ukuu.org.uk>,
  5 + * All Rights Reserved.
  6 + *
  7 + * (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>.
  8 + *
  9 + *
  10 + * This source code is part of the generic code that can be used
  11 + * by all the watchdog timer drivers.
  12 + *
  13 + * This part of the generic code takes care of the following
  14 + * misc device: /dev/watchdog.
  15 + *
  16 + * Based on source code of the following authors:
  17 + * Matt Domsch <Matt_Domsch@dell.com>,
  18 + * Rob Radez <rob@osinvestor.com>,
  19 + * Rusty Lynch <rusty@linux.co.intel.com>
  20 + * Satyam Sharma <satyam@infradead.org>
  21 + * Randy Dunlap <randy.dunlap@oracle.com>
  22 + *
  23 + * This program is free software; you can redistribute it and/or
  24 + * modify it under the terms of the GNU General Public License
  25 + * as published by the Free Software Foundation; either version
  26 + * 2 of the License, or (at your option) any later version.
  27 + *
  28 + * Neither Alan Cox, CymruNet Ltd., Wim Van Sebroeck nor Iguana vzw.
  29 + * admit liability nor provide warranty for any of this software.
  30 + * This material is provided "AS-IS" and at no charge.
  31 + */
  32 +
  33 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  34 +
  35 +#include <linux/module.h> /* For module stuff/... */
  36 +#include <linux/types.h> /* For standard types (like size_t) */
  37 +#include <linux/errno.h> /* For the -ENODEV/... values */
  38 +#include <linux/kernel.h> /* For printk/panic/... */
  39 +#include <linux/fs.h> /* For file operations */
  40 +#include <linux/watchdog.h> /* For watchdog specific items */
  41 +#include <linux/miscdevice.h> /* For handling misc devices */
  42 +#include <linux/init.h> /* For __init/__exit/... */
  43 +#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
  44 +
  45 +/* make sure we only register one /dev/watchdog device */
  46 +static unsigned long watchdog_dev_busy;
  47 +/* the watchdog device behind /dev/watchdog */
  48 +static struct watchdog_device *wdd;
  49 +
  50 +/*
  51 + * watchdog_ping: ping the watchdog.
  52 + * @wddev: the watchdog device to ping
  53 + *
  54 + * If the watchdog has no own ping operation then it needs to be
  55 + * restarted via the start operation. This wrapper function does
  56 + * exactly that.
  57 + */
  58 +
  59 +static int watchdog_ping(struct watchdog_device *wddev)
  60 +{
  61 + if (wddev->ops->ping)
  62 + return wddev->ops->ping(wddev); /* ping the watchdog */
  63 + else
  64 + return wddev->ops->start(wddev); /* restart the watchdog */
  65 +}
  66 +
  67 +/*
  68 + * watchdog_write: writes to the watchdog.
  69 + * @file: file from VFS
  70 + * @data: user address of data
  71 + * @len: length of data
  72 + * @ppos: pointer to the file offset
  73 + *
  74 + * A write to a watchdog device is defined as a keepalive ping.
  75 + */
  76 +
  77 +static ssize_t watchdog_write(struct file *file, const char __user *data,
  78 + size_t len, loff_t *ppos)
  79 +{
  80 + size_t i;
  81 + char c;
  82 +
  83 + if (len == 0)
  84 + return 0;
  85 +
  86 + for (i = 0; i != len; i++) {
  87 + if (get_user(c, data + i))
  88 + return -EFAULT;
  89 + }
  90 +
  91 + /* someone wrote to us, so we send the watchdog a keepalive ping */
  92 + watchdog_ping(wdd);
  93 +
  94 + return len;
  95 +}
  96 +
  97 +/*
  98 + * watchdog_open: open the /dev/watchdog device.
  99 + * @inode: inode of device
  100 + * @file: file handle to device
  101 + *
  102 + * When the /dev/watchdog device gets opened, we start the watchdog.
  103 + * Watch out: the /dev/watchdog device is single open, so we make sure
  104 + * it can only be opened once.
  105 + */
  106 +
  107 +static int watchdog_open(struct inode *inode, struct file *file)
  108 +{
  109 + int err = -EBUSY;
  110 +
  111 + /* the watchdog is single open! */
  112 + if (test_and_set_bit(WDOG_DEV_OPEN, &wdd->status))
  113 + return -EBUSY;
  114 +
  115 + /*
  116 + * If the /dev/watchdog device is open, we don't want the module
  117 + * to be unloaded.
  118 + */
  119 + if (!try_module_get(wdd->ops->owner))
  120 + goto out;
  121 +
  122 + err = wdd->ops->start(wdd);
  123 + if (err < 0)
  124 + goto out_mod;
  125 +
  126 + /* dev/watchdog is a virtual (and thus non-seekable) filesystem */
  127 + return nonseekable_open(inode, file);
  128 +
  129 +out_mod:
  130 + module_put(wdd->ops->owner);
  131 +out:
  132 + clear_bit(WDOG_DEV_OPEN, &wdd->status);
  133 + return err;
  134 +}
  135 +
  136 +/*
  137 + * watchdog_release: release the /dev/watchdog device.
  138 + * @inode: inode of device
  139 + * @file: file handle to device
  140 + *
  141 + * This is the code for when /dev/watchdog gets closed.
  142 + */
  143 +
  144 +static int watchdog_release(struct inode *inode, struct file *file)
  145 +{
  146 + int err;
  147 +
  148 + err = wdd->ops->stop(wdd);
  149 + if (err != 0) {
  150 + pr_crit("%s: watchdog did not stop!\n", wdd->info->identity);
  151 + watchdog_ping(wdd);
  152 + }
  153 +
  154 + /* Allow the owner module to be unloaded again */
  155 + module_put(wdd->ops->owner);
  156 +
  157 + /* make sure that /dev/watchdog can be re-opened */
  158 + clear_bit(WDOG_DEV_OPEN, &wdd->status);
  159 +
  160 + return 0;
  161 +}
  162 +
  163 +static const struct file_operations watchdog_fops = {
  164 + .owner = THIS_MODULE,
  165 + .write = watchdog_write,
  166 + .open = watchdog_open,
  167 + .release = watchdog_release,
  168 +};
  169 +
  170 +static struct miscdevice watchdog_miscdev = {
  171 + .minor = WATCHDOG_MINOR,
  172 + .name = "watchdog",
  173 + .fops = &watchdog_fops,
  174 +};
  175 +
  176 +/*
  177 + * watchdog_dev_register:
  178 + * @watchdog: watchdog device
  179 + *
  180 + * Register a watchdog device as /dev/watchdog. /dev/watchdog
  181 + * is actually a miscdevice and thus we set it up like that.
  182 + */
  183 +
  184 +int watchdog_dev_register(struct watchdog_device *watchdog)
  185 +{
  186 + int err;
  187 +
  188 + /* Only one device can register for /dev/watchdog */
  189 + if (test_and_set_bit(0, &watchdog_dev_busy)) {
  190 + pr_err("only one watchdog can use /dev/watchdog.\n");
  191 + return -EBUSY;
  192 + }
  193 +
  194 + wdd = watchdog;
  195 +
  196 + err = misc_register(&watchdog_miscdev);
  197 + if (err != 0) {
  198 + pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n",
  199 + watchdog->info->identity, WATCHDOG_MINOR, err);
  200 + goto out;
  201 + }
  202 +
  203 + return 0;
  204 +
  205 +out:
  206 + wdd = NULL;
  207 + clear_bit(0, &watchdog_dev_busy);
  208 + return err;
  209 +}
  210 +
  211 +/*
  212 + * watchdog_dev_unregister:
  213 + * @watchdog: watchdog device
  214 + *
  215 + * Deregister the /dev/watchdog device.
  216 + */
  217 +
  218 +int watchdog_dev_unregister(struct watchdog_device *watchdog)
  219 +{
  220 + /* Check that a watchdog device was registered in the past */
  221 + if (!test_bit(0, &watchdog_dev_busy) || !wdd)
  222 + return -ENODEV;
  223 +
  224 + /* We can only unregister the watchdog device that was registered */
  225 + if (watchdog != wdd) {
  226 + pr_err("%s: watchdog was not registered as /dev/watchdog.\n",
  227 + watchdog->info->identity);
  228 + return -ENODEV;
  229 + }
  230 +
  231 + misc_deregister(&watchdog_miscdev);
  232 + wdd = NULL;
  233 + clear_bit(0, &watchdog_dev_busy);
  234 + return 0;
  235 +}
drivers/watchdog/watchdog_dev.h
  1 +/*
  2 + * watchdog_core.h
  3 + *
  4 + * (c) Copyright 2008-2011 Alan Cox <alan@lxorguk.ukuu.org.uk>,
  5 + * All Rights Reserved.
  6 + *
  7 + * (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>.
  8 + *
  9 + * This source code is part of the generic code that can be used
  10 + * by all the watchdog timer drivers.
  11 + *
  12 + * Based on source code of the following authors:
  13 + * Matt Domsch <Matt_Domsch@dell.com>,
  14 + * Rob Radez <rob@osinvestor.com>,
  15 + * Rusty Lynch <rusty@linux.co.intel.com>
  16 + * Satyam Sharma <satyam@infradead.org>
  17 + * Randy Dunlap <randy.dunlap@oracle.com>
  18 + *
  19 + * This program is free software; you can redistribute it and/or
  20 + * modify it under the terms of the GNU General Public License
  21 + * as published by the Free Software Foundation; either version
  22 + * 2 of the License, or (at your option) any later version.
  23 + *
  24 + * Neither Alan Cox, CymruNet Ltd., Wim Van Sebroeck nor Iguana vzw.
  25 + * admit liability nor provide warranty for any of this software.
  26 + * This material is provided "AS-IS" and at no charge.
  27 + */
  28 +
  29 +/*
  30 + * Functions/procedures to be called by the core
  31 + */
  32 +int watchdog_dev_register(struct watchdog_device *);
  33 +int watchdog_dev_unregister(struct watchdog_device *);
include/linux/watchdog.h
... ... @@ -59,6 +59,67 @@
59 59 #define WATCHDOG_NOWAYOUT 0
60 60 #endif
61 61  
  62 +struct watchdog_ops;
  63 +struct watchdog_device;
  64 +
  65 +/** struct watchdog_ops - The watchdog-devices operations
  66 + *
  67 + * @owner: The module owner.
  68 + * @start: The routine for starting the watchdog device.
  69 + * @stop: The routine for stopping the watchdog device.
  70 + * @ping: The routine that sends a keepalive ping to the watchdog device.
  71 + *
  72 + * The watchdog_ops structure contains a list of low-level operations
  73 + * that control a watchdog device. It also contains the module that owns
  74 + * these operations. The start and stop function are mandatory, all other
  75 + * functions are optonal.
  76 + */
  77 +struct watchdog_ops {
  78 + struct module *owner;
  79 + /* mandatory operations */
  80 + int (*start)(struct watchdog_device *);
  81 + int (*stop)(struct watchdog_device *);
  82 + /* optional operations */
  83 + int (*ping)(struct watchdog_device *);
  84 +};
  85 +
  86 +/** struct watchdog_device - The structure that defines a watchdog device
  87 + *
  88 + * @info: Pointer to a watchdog_info structure.
  89 + * @ops: Pointer to the list of watchdog operations.
  90 + * @driver-data:Pointer to the drivers private data.
  91 + * @status: Field that contains the devices internal status bits.
  92 + *
  93 + * The watchdog_device structure contains all information about a
  94 + * watchdog timer device.
  95 + *
  96 + * The driver-data field may not be accessed directly. It must be accessed
  97 + * via the watchdog_set_drvdata and watchdog_get_drvdata helpers.
  98 + */
  99 +struct watchdog_device {
  100 + const struct watchdog_info *info;
  101 + const struct watchdog_ops *ops;
  102 + void *driver_data;
  103 + unsigned long status;
  104 +/* Bit numbers for status flags */
  105 +#define WDOG_DEV_OPEN 1 /* Opened via /dev/watchdog ? */
  106 +};
  107 +
  108 +/* Use the following functions to manipulate watchdog driver specific data */
  109 +static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
  110 +{
  111 + wdd->driver_data = data;
  112 +}
  113 +
  114 +static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
  115 +{
  116 + return wdd->driver_data;
  117 +}
  118 +
  119 +/* drivers/watchdog/core/watchdog_core.c */
  120 +extern int watchdog_register_device(struct watchdog_device *);
  121 +extern void watchdog_unregister_device(struct watchdog_device *);
  122 +
62 123 #endif /* __KERNEL__ */
63 124  
64 125 #endif /* ifndef _LINUX_WATCHDOG_H */