diff options
Diffstat (limited to 'drivers/watchdog/softdog.c')
-rw-r--r-- | drivers/watchdog/softdog.c | 87 |
1 files changed, 46 insertions, 41 deletions
diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index 9c3694909243..c650464c5c63 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c | |||
@@ -47,19 +47,22 @@ | |||
47 | #include <linux/reboot.h> | 47 | #include <linux/reboot.h> |
48 | #include <linux/init.h> | 48 | #include <linux/init.h> |
49 | #include <linux/jiffies.h> | 49 | #include <linux/jiffies.h> |
50 | 50 | #include <linux/uaccess.h> | |
51 | #include <asm/uaccess.h> | ||
52 | 51 | ||
53 | #define PFX "SoftDog: " | 52 | #define PFX "SoftDog: " |
54 | 53 | ||
55 | #define TIMER_MARGIN 60 /* Default is 60 seconds */ | 54 | #define TIMER_MARGIN 60 /* Default is 60 seconds */ |
56 | static int soft_margin = TIMER_MARGIN; /* in seconds */ | 55 | static int soft_margin = TIMER_MARGIN; /* in seconds */ |
57 | module_param(soft_margin, int, 0); | 56 | module_param(soft_margin, int, 0); |
58 | MODULE_PARM_DESC(soft_margin, "Watchdog soft_margin in seconds. (0<soft_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")"); | 57 | MODULE_PARM_DESC(soft_margin, |
58 | "Watchdog soft_margin in seconds. (0 < soft_margin < 65536, default=" | ||
59 | __MODULE_STRING(TIMER_MARGIN) ")"); | ||
59 | 60 | ||
60 | static int nowayout = WATCHDOG_NOWAYOUT; | 61 | static int nowayout = WATCHDOG_NOWAYOUT; |
61 | module_param(nowayout, int, 0); | 62 | module_param(nowayout, int, 0); |
62 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 63 | MODULE_PARM_DESC(nowayout, |
64 | "Watchdog cannot be stopped once started (default=" | ||
65 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
63 | 66 | ||
64 | #ifdef ONLY_TESTING | 67 | #ifdef ONLY_TESTING |
65 | static int soft_noboot = 1; | 68 | static int soft_noboot = 1; |
@@ -93,8 +96,7 @@ static void watchdog_fire(unsigned long data) | |||
93 | 96 | ||
94 | if (soft_noboot) | 97 | if (soft_noboot) |
95 | printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n"); | 98 | printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n"); |
96 | else | 99 | else { |
97 | { | ||
98 | printk(KERN_CRIT PFX "Initiating system reboot.\n"); | 100 | printk(KERN_CRIT PFX "Initiating system reboot.\n"); |
99 | emergency_restart(); | 101 | emergency_restart(); |
100 | printk(KERN_CRIT PFX "Reboot didn't ?????\n"); | 102 | printk(KERN_CRIT PFX "Reboot didn't ?????\n"); |
@@ -153,7 +155,8 @@ static int softdog_release(struct inode *inode, struct file *file) | |||
153 | softdog_stop(); | 155 | softdog_stop(); |
154 | module_put(THIS_MODULE); | 156 | module_put(THIS_MODULE); |
155 | } else { | 157 | } else { |
156 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 158 | printk(KERN_CRIT PFX |
159 | "Unexpected close, not stopping watchdog!\n"); | ||
157 | set_bit(0, &orphan_timer); | 160 | set_bit(0, &orphan_timer); |
158 | softdog_keepalive(); | 161 | softdog_keepalive(); |
159 | } | 162 | } |
@@ -162,12 +165,13 @@ static int softdog_release(struct inode *inode, struct file *file) | |||
162 | return 0; | 165 | return 0; |
163 | } | 166 | } |
164 | 167 | ||
165 | static ssize_t softdog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) | 168 | static ssize_t softdog_write(struct file *file, const char __user *data, |
169 | size_t len, loff_t *ppos) | ||
166 | { | 170 | { |
167 | /* | 171 | /* |
168 | * Refresh the timer. | 172 | * Refresh the timer. |
169 | */ | 173 | */ |
170 | if(len) { | 174 | if (len) { |
171 | if (!nowayout) { | 175 | if (!nowayout) { |
172 | size_t i; | 176 | size_t i; |
173 | 177 | ||
@@ -188,13 +192,13 @@ static ssize_t softdog_write(struct file *file, const char __user *data, size_t | |||
188 | return len; | 192 | return len; |
189 | } | 193 | } |
190 | 194 | ||
191 | static int softdog_ioctl(struct inode *inode, struct file *file, | 195 | static long softdog_ioctl(struct file *file, unsigned int cmd, |
192 | unsigned int cmd, unsigned long arg) | 196 | unsigned long arg) |
193 | { | 197 | { |
194 | void __user *argp = (void __user *)arg; | 198 | void __user *argp = (void __user *)arg; |
195 | int __user *p = argp; | 199 | int __user *p = argp; |
196 | int new_margin; | 200 | int new_margin; |
197 | static struct watchdog_info ident = { | 201 | static const struct watchdog_info ident = { |
198 | .options = WDIOF_SETTIMEOUT | | 202 | .options = WDIOF_SETTIMEOUT | |
199 | WDIOF_KEEPALIVEPING | | 203 | WDIOF_KEEPALIVEPING | |
200 | WDIOF_MAGICCLOSE, | 204 | WDIOF_MAGICCLOSE, |
@@ -202,26 +206,25 @@ static int softdog_ioctl(struct inode *inode, struct file *file, | |||
202 | .identity = "Software Watchdog", | 206 | .identity = "Software Watchdog", |
203 | }; | 207 | }; |
204 | switch (cmd) { | 208 | switch (cmd) { |
205 | default: | 209 | case WDIOC_GETSUPPORT: |
206 | return -ENOTTY; | 210 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
207 | case WDIOC_GETSUPPORT: | 211 | case WDIOC_GETSTATUS: |
208 | return copy_to_user(argp, &ident, | 212 | case WDIOC_GETBOOTSTATUS: |
209 | sizeof(ident)) ? -EFAULT : 0; | 213 | return put_user(0, p); |
210 | case WDIOC_GETSTATUS: | 214 | case WDIOC_KEEPALIVE: |
211 | case WDIOC_GETBOOTSTATUS: | 215 | softdog_keepalive(); |
212 | return put_user(0, p); | 216 | return 0; |
213 | case WDIOC_KEEPALIVE: | 217 | case WDIOC_SETTIMEOUT: |
214 | softdog_keepalive(); | 218 | if (get_user(new_margin, p)) |
215 | return 0; | 219 | return -EFAULT; |
216 | case WDIOC_SETTIMEOUT: | 220 | if (softdog_set_heartbeat(new_margin)) |
217 | if (get_user(new_margin, p)) | 221 | return -EINVAL; |
218 | return -EFAULT; | 222 | softdog_keepalive(); |
219 | if (softdog_set_heartbeat(new_margin)) | 223 | /* Fall */ |
220 | return -EINVAL; | 224 | case WDIOC_GETTIMEOUT: |
221 | softdog_keepalive(); | 225 | return put_user(soft_margin, p); |
222 | /* Fall */ | 226 | default: |
223 | case WDIOC_GETTIMEOUT: | 227 | return -ENOTTY; |
224 | return put_user(soft_margin, p); | ||
225 | } | 228 | } |
226 | } | 229 | } |
227 | 230 | ||
@@ -232,10 +235,9 @@ static int softdog_ioctl(struct inode *inode, struct file *file, | |||
232 | static int softdog_notify_sys(struct notifier_block *this, unsigned long code, | 235 | static int softdog_notify_sys(struct notifier_block *this, unsigned long code, |
233 | void *unused) | 236 | void *unused) |
234 | { | 237 | { |
235 | if(code==SYS_DOWN || code==SYS_HALT) { | 238 | if (code == SYS_DOWN || code == SYS_HALT) |
236 | /* Turn the WDT off */ | 239 | /* Turn the WDT off */ |
237 | softdog_stop(); | 240 | softdog_stop(); |
238 | } | ||
239 | return NOTIFY_DONE; | 241 | return NOTIFY_DONE; |
240 | } | 242 | } |
241 | 243 | ||
@@ -247,7 +249,7 @@ static const struct file_operations softdog_fops = { | |||
247 | .owner = THIS_MODULE, | 249 | .owner = THIS_MODULE, |
248 | .llseek = no_llseek, | 250 | .llseek = no_llseek, |
249 | .write = softdog_write, | 251 | .write = softdog_write, |
250 | .ioctl = softdog_ioctl, | 252 | .unlocked_ioctl = softdog_ioctl, |
251 | .open = softdog_open, | 253 | .open = softdog_open, |
252 | .release = softdog_release, | 254 | .release = softdog_release, |
253 | }; | 255 | }; |
@@ -268,24 +270,27 @@ static int __init watchdog_init(void) | |||
268 | { | 270 | { |
269 | int ret; | 271 | int ret; |
270 | 272 | ||
271 | /* Check that the soft_margin value is within it's range ; if not reset to the default */ | 273 | /* Check that the soft_margin value is within it's range; |
274 | if not reset to the default */ | ||
272 | if (softdog_set_heartbeat(soft_margin)) { | 275 | if (softdog_set_heartbeat(soft_margin)) { |
273 | softdog_set_heartbeat(TIMER_MARGIN); | 276 | softdog_set_heartbeat(TIMER_MARGIN); |
274 | printk(KERN_INFO PFX "soft_margin value must be 0<soft_margin<65536, using %d\n", | 277 | printk(KERN_INFO PFX |
278 | "soft_margin must be 0 < soft_margin < 65536, using %d\n", | ||
275 | TIMER_MARGIN); | 279 | TIMER_MARGIN); |
276 | } | 280 | } |
277 | 281 | ||
278 | ret = register_reboot_notifier(&softdog_notifier); | 282 | ret = register_reboot_notifier(&softdog_notifier); |
279 | if (ret) { | 283 | if (ret) { |
280 | printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 284 | printk(KERN_ERR PFX |
281 | ret); | 285 | "cannot register reboot notifier (err=%d)\n", ret); |
282 | return ret; | 286 | return ret; |
283 | } | 287 | } |
284 | 288 | ||
285 | ret = misc_register(&softdog_miscdev); | 289 | ret = misc_register(&softdog_miscdev); |
286 | if (ret) { | 290 | if (ret) { |
287 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 291 | printk(KERN_ERR PFX |
288 | WATCHDOG_MINOR, ret); | 292 | "cannot register miscdev on minor=%d (err=%d)\n", |
293 | WATCHDOG_MINOR, ret); | ||
289 | unregister_reboot_notifier(&softdog_notifier); | 294 | unregister_reboot_notifier(&softdog_notifier); |
290 | return ret; | 295 | return ret; |
291 | } | 296 | } |