diff options
Diffstat (limited to 'Documentation/watchdog/watchdog-kernel-api.txt')
-rw-r--r-- | Documentation/watchdog/watchdog-kernel-api.txt | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt index 25fe4304f2fc..086638f6c82d 100644 --- a/Documentation/watchdog/watchdog-kernel-api.txt +++ b/Documentation/watchdog/watchdog-kernel-api.txt | |||
@@ -1,6 +1,6 @@ | |||
1 | The Linux WatchDog Timer Driver Core kernel API. | 1 | The Linux WatchDog Timer Driver Core kernel API. |
2 | =============================================== | 2 | =============================================== |
3 | Last reviewed: 16-Mar-2012 | 3 | Last reviewed: 22-May-2012 |
4 | 4 | ||
5 | Wim Van Sebroeck <wim@iguana.be> | 5 | Wim Van Sebroeck <wim@iguana.be> |
6 | 6 | ||
@@ -39,6 +39,10 @@ watchdog_device structure. | |||
39 | The watchdog device structure looks like this: | 39 | The watchdog device structure looks like this: |
40 | 40 | ||
41 | struct watchdog_device { | 41 | struct watchdog_device { |
42 | int id; | ||
43 | struct cdev cdev; | ||
44 | struct device *dev; | ||
45 | struct device *parent; | ||
42 | const struct watchdog_info *info; | 46 | const struct watchdog_info *info; |
43 | const struct watchdog_ops *ops; | 47 | const struct watchdog_ops *ops; |
44 | unsigned int bootstatus; | 48 | unsigned int bootstatus; |
@@ -46,10 +50,20 @@ struct watchdog_device { | |||
46 | unsigned int min_timeout; | 50 | unsigned int min_timeout; |
47 | unsigned int max_timeout; | 51 | unsigned int max_timeout; |
48 | void *driver_data; | 52 | void *driver_data; |
53 | struct mutex lock; | ||
49 | unsigned long status; | 54 | unsigned long status; |
50 | }; | 55 | }; |
51 | 56 | ||
52 | It contains following fields: | 57 | It contains following fields: |
58 | * id: set by watchdog_register_device, id 0 is special. It has both a | ||
59 | /dev/watchdog0 cdev (dynamic major, minor 0) as well as the old | ||
60 | /dev/watchdog miscdev. The id is set automatically when calling | ||
61 | watchdog_register_device. | ||
62 | * cdev: cdev for the dynamic /dev/watchdog<id> device nodes. This | ||
63 | field is also populated by watchdog_register_device. | ||
64 | * dev: device under the watchdog class (created by watchdog_register_device). | ||
65 | * parent: set this to the parent device (or NULL) before calling | ||
66 | watchdog_register_device. | ||
53 | * info: a pointer to a watchdog_info structure. This structure gives some | 67 | * info: a pointer to a watchdog_info structure. This structure gives some |
54 | additional information about the watchdog timer itself. (Like it's unique name) | 68 | additional information about the watchdog timer itself. (Like it's unique name) |
55 | * ops: a pointer to the list of watchdog operations that the watchdog supports. | 69 | * ops: a pointer to the list of watchdog operations that the watchdog supports. |
@@ -61,6 +75,7 @@ It contains following fields: | |||
61 | * driver_data: a pointer to the drivers private data of a watchdog device. | 75 | * driver_data: a pointer to the drivers private data of a watchdog device. |
62 | This data should only be accessed via the watchdog_set_drvdata and | 76 | This data should only be accessed via the watchdog_set_drvdata and |
63 | watchdog_get_drvdata routines. | 77 | watchdog_get_drvdata routines. |
78 | * lock: Mutex for WatchDog Timer Driver Core internal use only. | ||
64 | * status: this field contains a number of status bits that give extra | 79 | * status: this field contains a number of status bits that give extra |
65 | information about the status of the device (Like: is the watchdog timer | 80 | information about the status of the device (Like: is the watchdog timer |
66 | running/active, is the nowayout bit set, is the device opened via | 81 | running/active, is the nowayout bit set, is the device opened via |
@@ -78,6 +93,8 @@ struct watchdog_ops { | |||
78 | unsigned int (*status)(struct watchdog_device *); | 93 | unsigned int (*status)(struct watchdog_device *); |
79 | int (*set_timeout)(struct watchdog_device *, unsigned int); | 94 | int (*set_timeout)(struct watchdog_device *, unsigned int); |
80 | unsigned int (*get_timeleft)(struct watchdog_device *); | 95 | unsigned int (*get_timeleft)(struct watchdog_device *); |
96 | void (*ref)(struct watchdog_device *); | ||
97 | void (*unref)(struct watchdog_device *); | ||
81 | long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); | 98 | long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); |
82 | }; | 99 | }; |
83 | 100 | ||
@@ -85,6 +102,21 @@ It is important that you first define the module owner of the watchdog timer | |||
85 | driver's operations. This module owner will be used to lock the module when | 102 | driver's operations. This module owner will be used to lock the module when |
86 | the watchdog is active. (This to avoid a system crash when you unload the | 103 | the watchdog is active. (This to avoid a system crash when you unload the |
87 | module and /dev/watchdog is still open). | 104 | module and /dev/watchdog is still open). |
105 | |||
106 | If the watchdog_device struct is dynamically allocated, just locking the module | ||
107 | is not enough and a driver also needs to define the ref and unref operations to | ||
108 | ensure the structure holding the watchdog_device does not go away. | ||
109 | |||
110 | The simplest (and usually sufficient) implementation of this is to: | ||
111 | 1) Add a kref struct to the same structure which is holding the watchdog_device | ||
112 | 2) Define a release callback for the kref which frees the struct holding both | ||
113 | 3) Call kref_init on this kref *before* calling watchdog_register_device() | ||
114 | 4) Define a ref operation calling kref_get on this kref | ||
115 | 5) Define a unref operation calling kref_put on this kref | ||
116 | 6) When it is time to cleanup: | ||
117 | * Do not kfree() the struct holding both, the last kref_put will do this! | ||
118 | * *After* calling watchdog_unregister_device() call kref_put on the kref | ||
119 | |||
88 | Some operations are mandatory and some are optional. The mandatory operations | 120 | Some operations are mandatory and some are optional. The mandatory operations |
89 | are: | 121 | are: |
90 | * start: this is a pointer to the routine that starts the watchdog timer | 122 | * start: this is a pointer to the routine that starts the watchdog timer |
@@ -125,6 +157,10 @@ they are supported. These optional routines/operations are: | |||
125 | (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the | 157 | (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the |
126 | watchdog's info structure). | 158 | watchdog's info structure). |
127 | * get_timeleft: this routines returns the time that's left before a reset. | 159 | * get_timeleft: this routines returns the time that's left before a reset. |
160 | * ref: the operation that calls kref_get on the kref of a dynamically | ||
161 | allocated watchdog_device struct. | ||
162 | * unref: the operation that calls kref_put on the kref of a dynamically | ||
163 | allocated watchdog_device struct. | ||
128 | * ioctl: if this routine is present then it will be called first before we do | 164 | * ioctl: if this routine is present then it will be called first before we do |
129 | our own internal ioctl call handling. This routine should return -ENOIOCTLCMD | 165 | our own internal ioctl call handling. This routine should return -ENOIOCTLCMD |
130 | if a command is not supported. The parameters that are passed to the ioctl | 166 | if a command is not supported. The parameters that are passed to the ioctl |
@@ -144,6 +180,11 @@ bit-operations. The status bits that are defined are: | |||
144 | (This bit should only be used by the WatchDog Timer Driver Core). | 180 | (This bit should only be used by the WatchDog Timer Driver Core). |
145 | * WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog. | 181 | * WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog. |
146 | If this bit is set then the watchdog timer will not be able to stop. | 182 | If this bit is set then the watchdog timer will not be able to stop. |
183 | * WDOG_UNREGISTERED: this bit gets set by the WatchDog Timer Driver Core | ||
184 | after calling watchdog_unregister_device, and then checked before calling | ||
185 | any watchdog_ops, so that you can be sure that no operations (other then | ||
186 | unref) will get called after unregister, even if userspace still holds a | ||
187 | reference to /dev/watchdog | ||
147 | 188 | ||
148 | To set the WDOG_NO_WAY_OUT status bit (before registering your watchdog | 189 | To set the WDOG_NO_WAY_OUT status bit (before registering your watchdog |
149 | timer device) you can either: | 190 | timer device) you can either: |