Commit 2fa03560 authored by Wim Van Sebroeck's avatar Wim Van Sebroeck

watchdog: WatchDog Timer Driver Core - Add basic ioctl functionality

This part add's the basic ioctl functionality to the
WatchDog Timer Driver Core framework. The supported
ioctl call's are:
	WDIOC_GETSUPPORT
	WDIOC_GETSTATUS
	WDIOC_GETBOOTSTATUS
Signed-off-by: default avatarAlan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: default avatarWim Van Sebroeck <wim@iguana.be>
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
Acked-by: default avatarWolfram Sang <w.sang@pengutronix.de>
parent 43316044
...@@ -41,6 +41,7 @@ The watchdog device structure looks like this: ...@@ -41,6 +41,7 @@ The watchdog device structure looks like this:
struct watchdog_device { struct watchdog_device {
const struct watchdog_info *info; const struct watchdog_info *info;
const struct watchdog_ops *ops; const struct watchdog_ops *ops;
unsigned int bootstatus;
void *driver_data; void *driver_data;
unsigned long status; unsigned long status;
}; };
...@@ -49,6 +50,8 @@ It contains following fields: ...@@ -49,6 +50,8 @@ It contains following fields:
* info: a pointer to a watchdog_info structure. This structure gives some * info: a pointer to a watchdog_info structure. This structure gives some
additional information about the watchdog timer itself. (Like it's unique name) 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. * ops: a pointer to the list of watchdog operations that the watchdog supports.
* bootstatus: status of the device after booting (reported with watchdog
WDIOF_* status bits).
* driver_data: a pointer to the drivers private data of a watchdog device. * driver_data: a pointer to the drivers private data of a watchdog device.
This data should only be accessed via the watchdog_set_drvadata and This data should only be accessed via the watchdog_set_drvadata and
watchdog_get_drvdata routines. watchdog_get_drvdata routines.
...@@ -65,6 +68,7 @@ struct watchdog_ops { ...@@ -65,6 +68,7 @@ struct watchdog_ops {
int (*stop)(struct watchdog_device *); int (*stop)(struct watchdog_device *);
/* optional operations */ /* optional operations */
int (*ping)(struct watchdog_device *); int (*ping)(struct watchdog_device *);
unsigned int (*status)(struct watchdog_device *);
}; };
It is important that you first define the module owner of the watchdog timer It is important that you first define the module owner of the watchdog timer
...@@ -97,6 +101,8 @@ they are supported. These optional routines/operations are: ...@@ -97,6 +101,8 @@ they are supported. These optional routines/operations are:
the watchdog timer driver core does: to send a keepalive ping to the watchdog the watchdog timer driver core does: to send a keepalive ping to the watchdog
timer hardware it will either use the ping operation (when available) or the timer hardware it will either use the ping operation (when available) or the
start operation (when the ping operation is not available). start operation (when the ping operation is not available).
* status: this routine checks the status of the watchdog timer device. The
status of the device is reported with watchdog WDIOF_* status flags/bits.
The status bits should (preferably) be set with the set_bit and clear_bit alike The status bits should (preferably) be set with the set_bit and clear_bit alike
bit-operations. The status bits that are defined are: bit-operations. The status bits that are defined are:
......
...@@ -94,6 +94,37 @@ static ssize_t watchdog_write(struct file *file, const char __user *data, ...@@ -94,6 +94,37 @@ static ssize_t watchdog_write(struct file *file, const char __user *data,
return len; return len;
} }
/*
* watchdog_ioctl: handle the different ioctl's for the watchdog device.
* @file: file handle to the device
* @cmd: watchdog command
* @arg: argument pointer
*
* The watchdog API defines a common set of functions for all watchdogs
* according to their available features.
*/
static long watchdog_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
unsigned int val;
switch (cmd) {
case WDIOC_GETSUPPORT:
return copy_to_user(argp, wdd->info,
sizeof(struct watchdog_info)) ? -EFAULT : 0;
case WDIOC_GETSTATUS:
val = wdd->ops->status ? wdd->ops->status(wdd) : 0;
return put_user(val, p);
case WDIOC_GETBOOTSTATUS:
return put_user(wdd->bootstatus, p);
default:
return -ENOTTY;
}
}
/* /*
* watchdog_open: open the /dev/watchdog device. * watchdog_open: open the /dev/watchdog device.
* @inode: inode of device * @inode: inode of device
...@@ -163,6 +194,7 @@ static int watchdog_release(struct inode *inode, struct file *file) ...@@ -163,6 +194,7 @@ static int watchdog_release(struct inode *inode, struct file *file)
static const struct file_operations watchdog_fops = { static const struct file_operations watchdog_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.write = watchdog_write, .write = watchdog_write,
.unlocked_ioctl = watchdog_ioctl,
.open = watchdog_open, .open = watchdog_open,
.release = watchdog_release, .release = watchdog_release,
}; };
......
...@@ -68,6 +68,7 @@ struct watchdog_device; ...@@ -68,6 +68,7 @@ struct watchdog_device;
* @start: The routine for starting the watchdog device. * @start: The routine for starting the watchdog device.
* @stop: The routine for stopping the watchdog device. * @stop: The routine for stopping the watchdog device.
* @ping: The routine that sends a keepalive ping to the watchdog device. * @ping: The routine that sends a keepalive ping to the watchdog device.
* @status: The routine that shows the status of the watchdog device.
* *
* The watchdog_ops structure contains a list of low-level operations * The watchdog_ops structure contains a list of low-level operations
* that control a watchdog device. It also contains the module that owns * that control a watchdog device. It also contains the module that owns
...@@ -81,12 +82,14 @@ struct watchdog_ops { ...@@ -81,12 +82,14 @@ struct watchdog_ops {
int (*stop)(struct watchdog_device *); int (*stop)(struct watchdog_device *);
/* optional operations */ /* optional operations */
int (*ping)(struct watchdog_device *); int (*ping)(struct watchdog_device *);
unsigned int (*status)(struct watchdog_device *);
}; };
/** struct watchdog_device - The structure that defines a watchdog device /** struct watchdog_device - The structure that defines a watchdog device
* *
* @info: Pointer to a watchdog_info structure. * @info: Pointer to a watchdog_info structure.
* @ops: Pointer to the list of watchdog operations. * @ops: Pointer to the list of watchdog operations.
* @bootstatus: Status of the watchdog device at boot.
* @driver-data:Pointer to the drivers private data. * @driver-data:Pointer to the drivers private data.
* @status: Field that contains the devices internal status bits. * @status: Field that contains the devices internal status bits.
* *
...@@ -99,6 +102,7 @@ struct watchdog_ops { ...@@ -99,6 +102,7 @@ struct watchdog_ops {
struct watchdog_device { struct watchdog_device {
const struct watchdog_info *info; const struct watchdog_info *info;
const struct watchdog_ops *ops; const struct watchdog_ops *ops;
unsigned int bootstatus;
void *driver_data; void *driver_data;
unsigned long status; unsigned long status;
/* Bit numbers for status flags */ /* Bit numbers for status flags */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment