aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/ib700wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/ib700wdt.c')
-rw-r--r--drivers/watchdog/ib700wdt.c123
1 files changed, 60 insertions, 63 deletions
diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
index 4b89f401691a..05a28106e8eb 100644
--- a/drivers/watchdog/ib700wdt.c
+++ b/drivers/watchdog/ib700wdt.c
@@ -41,9 +41,9 @@
41#include <linux/spinlock.h> 41#include <linux/spinlock.h>
42#include <linux/moduleparam.h> 42#include <linux/moduleparam.h>
43#include <linux/platform_device.h> 43#include <linux/platform_device.h>
44#include <linux/io.h>
45#include <linux/uaccess.h>
44 46
45#include <asm/io.h>
46#include <asm/uaccess.h>
47#include <asm/system.h> 47#include <asm/system.h>
48 48
49static struct platform_device *ibwdt_platform_device; 49static struct platform_device *ibwdt_platform_device;
@@ -120,15 +120,16 @@ static int wd_margin = WD_TIMO;
120 120
121static int nowayout = WATCHDOG_NOWAYOUT; 121static int nowayout = WATCHDOG_NOWAYOUT;
122module_param(nowayout, int, 0); 122module_param(nowayout, int, 0);
123MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 123MODULE_PARM_DESC(nowayout,
124 "Watchdog cannot be stopped once started (default="
125 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
124 126
125 127
126/* 128/*
127 * Watchdog Operations 129 * Watchdog Operations
128 */ 130 */
129 131
130static void 132static void ibwdt_ping(void)
131ibwdt_ping(void)
132{ 133{
133 spin_lock(&ibwdt_lock); 134 spin_lock(&ibwdt_lock);
134 135
@@ -138,16 +139,14 @@ ibwdt_ping(void)
138 spin_unlock(&ibwdt_lock); 139 spin_unlock(&ibwdt_lock);
139} 140}
140 141
141static void 142static void ibwdt_disable(void)
142ibwdt_disable(void)
143{ 143{
144 spin_lock(&ibwdt_lock); 144 spin_lock(&ibwdt_lock);
145 outb_p(0, WDT_STOP); 145 outb_p(0, WDT_STOP);
146 spin_unlock(&ibwdt_lock); 146 spin_unlock(&ibwdt_lock);
147} 147}
148 148
149static int 149static int ibwdt_set_heartbeat(int t)
150ibwdt_set_heartbeat(int t)
151{ 150{
152 int i; 151 int i;
153 152
@@ -165,8 +164,8 @@ ibwdt_set_heartbeat(int t)
165 * /dev/watchdog handling 164 * /dev/watchdog handling
166 */ 165 */
167 166
168static ssize_t 167static ssize_t ibwdt_write(struct file *file, const char __user *buf,
169ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 168 size_t count, loff_t *ppos)
170{ 169{
171 if (count) { 170 if (count) {
172 if (!nowayout) { 171 if (!nowayout) {
@@ -188,77 +187,71 @@ ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppo
188 return count; 187 return count;
189} 188}
190 189
191static int 190static long ibwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
192ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
193 unsigned long arg)
194{ 191{
195 int new_margin; 192 int new_margin;
196 void __user *argp = (void __user *)arg; 193 void __user *argp = (void __user *)arg;
197 int __user *p = argp; 194 int __user *p = argp;
198 195
199 static struct watchdog_info ident = { 196 static struct watchdog_info ident = {
200 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 197 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
198 | WDIOF_MAGICCLOSE,
201 .firmware_version = 1, 199 .firmware_version = 1,
202 .identity = "IB700 WDT", 200 .identity = "IB700 WDT",
203 }; 201 };
204 202
205 switch (cmd) { 203 switch (cmd) {
206 case WDIOC_GETSUPPORT: 204 case WDIOC_GETSUPPORT:
207 if (copy_to_user(argp, &ident, sizeof(ident))) 205 if (copy_to_user(argp, &ident, sizeof(ident)))
208 return -EFAULT; 206 return -EFAULT;
209 break; 207 break;
210 208
211 case WDIOC_GETSTATUS: 209 case WDIOC_GETSTATUS:
212 case WDIOC_GETBOOTSTATUS: 210 case WDIOC_GETBOOTSTATUS:
213 return put_user(0, p); 211 return put_user(0, p);
214
215 case WDIOC_KEEPALIVE:
216 ibwdt_ping();
217 break;
218
219 case WDIOC_SETTIMEOUT:
220 if (get_user(new_margin, p))
221 return -EFAULT;
222 if (ibwdt_set_heartbeat(new_margin))
223 return -EINVAL;
224 ibwdt_ping();
225 /* Fall */
226
227 case WDIOC_GETTIMEOUT:
228 return put_user(wd_times[wd_margin], p);
229 212
230 case WDIOC_SETOPTIONS: 213 case WDIOC_SETOPTIONS:
231 { 214 {
232 int options, retval = -EINVAL; 215 int options, retval = -EINVAL;
233 216
234 if (get_user(options, p)) 217 if (get_user(options, p))
235 return -EFAULT; 218 return -EFAULT;
236 219
237 if (options & WDIOS_DISABLECARD) { 220 if (options & WDIOS_DISABLECARD) {
238 ibwdt_disable(); 221 ibwdt_disable();
239 retval = 0; 222 retval = 0;
240 } 223 }
224 if (options & WDIOS_ENABLECARD) {
225 ibwdt_ping();
226 retval = 0;
227 }
228 return retval;
229 }
230 case WDIOC_KEEPALIVE:
231 ibwdt_ping();
232 break;
241 233
242 if (options & WDIOS_ENABLECARD) { 234 case WDIOC_SETTIMEOUT:
243 ibwdt_ping(); 235 if (get_user(new_margin, p))
244 retval = 0; 236 return -EFAULT;
245 } 237 if (ibwdt_set_heartbeat(new_margin))
238 return -EINVAL;
239 ibwdt_ping();
240 /* Fall */
246 241
247 return retval; 242 case WDIOC_GETTIMEOUT:
248 } 243 return put_user(wd_times[wd_margin], p);
249 244
250 default: 245 default:
251 return -ENOTTY; 246 return -ENOTTY;
252 } 247 }
253 return 0; 248 return 0;
254} 249}
255 250
256static int 251static int ibwdt_open(struct inode *inode, struct file *file)
257ibwdt_open(struct inode *inode, struct file *file)
258{ 252{
259 if (test_and_set_bit(0, &ibwdt_is_open)) { 253 if (test_and_set_bit(0, &ibwdt_is_open))
260 return -EBUSY; 254 return -EBUSY;
261 }
262 if (nowayout) 255 if (nowayout)
263 __module_get(THIS_MODULE); 256 __module_get(THIS_MODULE);
264 257
@@ -267,13 +260,13 @@ ibwdt_open(struct inode *inode, struct file *file)
267 return nonseekable_open(inode, file); 260 return nonseekable_open(inode, file);
268} 261}
269 262
270static int 263static int ibwdt_close(struct inode *inode, struct file *file)
271ibwdt_close(struct inode *inode, struct file *file)
272{ 264{
273 if (expect_close == 42) { 265 if (expect_close == 42) {
274 ibwdt_disable(); 266 ibwdt_disable();
275 } else { 267 } else {
276 printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); 268 printk(KERN_CRIT PFX
269 "WDT device closed unexpectedly. WDT will not stop!\n");
277 ibwdt_ping(); 270 ibwdt_ping();
278 } 271 }
279 clear_bit(0, &ibwdt_is_open); 272 clear_bit(0, &ibwdt_is_open);
@@ -289,7 +282,7 @@ static const struct file_operations ibwdt_fops = {
289 .owner = THIS_MODULE, 282 .owner = THIS_MODULE,
290 .llseek = no_llseek, 283 .llseek = no_llseek,
291 .write = ibwdt_write, 284 .write = ibwdt_write,
292 .ioctl = ibwdt_ioctl, 285 .unlocked_ioctl = ibwdt_ioctl,
293 .open = ibwdt_open, 286 .open = ibwdt_open,
294 .release = ibwdt_close, 287 .release = ibwdt_close,
295}; 288};
@@ -310,21 +303,23 @@ static int __devinit ibwdt_probe(struct platform_device *dev)
310 303
311#if WDT_START != WDT_STOP 304#if WDT_START != WDT_STOP
312 if (!request_region(WDT_STOP, 1, "IB700 WDT")) { 305 if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
313 printk (KERN_ERR PFX "STOP method I/O %X is not available.\n", WDT_STOP); 306 printk(KERN_ERR PFX "STOP method I/O %X is not available.\n",
307 WDT_STOP);
314 res = -EIO; 308 res = -EIO;
315 goto out_nostopreg; 309 goto out_nostopreg;
316 } 310 }
317#endif 311#endif
318 312
319 if (!request_region(WDT_START, 1, "IB700 WDT")) { 313 if (!request_region(WDT_START, 1, "IB700 WDT")) {
320 printk (KERN_ERR PFX "START method I/O %X is not available.\n", WDT_START); 314 printk(KERN_ERR PFX "START method I/O %X is not available.\n",
315 WDT_START);
321 res = -EIO; 316 res = -EIO;
322 goto out_nostartreg; 317 goto out_nostartreg;
323 } 318 }
324 319
325 res = misc_register(&ibwdt_miscdev); 320 res = misc_register(&ibwdt_miscdev);
326 if (res) { 321 if (res) {
327 printk (KERN_ERR PFX "failed to register misc device\n"); 322 printk(KERN_ERR PFX "failed to register misc device\n");
328 goto out_nomisc; 323 goto out_nomisc;
329 } 324 }
330 return 0; 325 return 0;
@@ -342,9 +337,9 @@ out_nostopreg:
342static int __devexit ibwdt_remove(struct platform_device *dev) 337static int __devexit ibwdt_remove(struct platform_device *dev)
343{ 338{
344 misc_deregister(&ibwdt_miscdev); 339 misc_deregister(&ibwdt_miscdev);
345 release_region(WDT_START,1); 340 release_region(WDT_START, 1);
346#if WDT_START != WDT_STOP 341#if WDT_START != WDT_STOP
347 release_region(WDT_STOP,1); 342 release_region(WDT_STOP, 1);
348#endif 343#endif
349 return 0; 344 return 0;
350} 345}
@@ -369,13 +364,15 @@ static int __init ibwdt_init(void)
369{ 364{
370 int err; 365 int err;
371 366
372 printk(KERN_INFO PFX "WDT driver for IB700 single board computer initialising.\n"); 367 printk(KERN_INFO PFX
368 "WDT driver for IB700 single board computer initialising.\n");
373 369
374 err = platform_driver_register(&ibwdt_driver); 370 err = platform_driver_register(&ibwdt_driver);
375 if (err) 371 if (err)
376 return err; 372 return err;
377 373
378 ibwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); 374 ibwdt_platform_device = platform_device_register_simple(DRV_NAME,
375 -1, NULL, 0);
379 if (IS_ERR(ibwdt_platform_device)) { 376 if (IS_ERR(ibwdt_platform_device)) {
380 err = PTR_ERR(ibwdt_platform_device); 377 err = PTR_ERR(ibwdt_platform_device);
381 goto unreg_platform_driver; 378 goto unreg_platform_driver;