aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-08-07 04:55:03 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-08-07 04:55:03 -0400
commit4fb8af10d0fd09372d52966b76922b9e82bbc950 (patch)
treed240e4d40357583e3f3eb228dccf20122a5b31ed /drivers/watchdog
parentf44f82e8a20b98558486eb14497b2f71c78fa325 (diff)
parent64a99d2a8c3ed5c4e39f3ae1cc682aa8fd3977fc (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fixes
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/ar7_wdt.c29
-rw-r--r--drivers/watchdog/hpwdt.c2
-rw-r--r--drivers/watchdog/it8712f_wdt.c77
-rw-r--r--drivers/watchdog/s3c2410_wdt.c148
-rw-r--r--drivers/watchdog/sc1200wdt.c205
-rw-r--r--drivers/watchdog/wdt.c176
-rw-r--r--drivers/watchdog/wdt_pci.c301
7 files changed, 504 insertions, 434 deletions
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index 2eb48c0df32c..ef7b0d67095e 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -69,7 +69,8 @@ struct ar7_wdt {
69 u32 prescale; 69 u32 prescale;
70}; 70};
71 71
72static struct semaphore open_semaphore; 72static unsigned long wdt_is_open;
73static spinlock_t wdt_lock;
73static unsigned expect_close; 74static unsigned expect_close;
74 75
75/* XXX currently fixed, allows max margin ~68.72 secs */ 76/* XXX currently fixed, allows max margin ~68.72 secs */
@@ -154,8 +155,10 @@ static void ar7_wdt_update_margin(int new_margin)
154 u32 change; 155 u32 change;
155 156
156 change = new_margin * (ar7_vbus_freq() / prescale_value); 157 change = new_margin * (ar7_vbus_freq() / prescale_value);
157 if (change < 1) change = 1; 158 if (change < 1)
158 if (change > 0xffff) change = 0xffff; 159 change = 1;
160 if (change > 0xffff)
161 change = 0xffff;
159 ar7_wdt_change(change); 162 ar7_wdt_change(change);
160 margin = change * prescale_value / ar7_vbus_freq(); 163 margin = change * prescale_value / ar7_vbus_freq();
161 printk(KERN_INFO DRVNAME 164 printk(KERN_INFO DRVNAME
@@ -179,7 +182,7 @@ static void ar7_wdt_disable_wdt(void)
179static int ar7_wdt_open(struct inode *inode, struct file *file) 182static int ar7_wdt_open(struct inode *inode, struct file *file)
180{ 183{
181 /* only allow one at a time */ 184 /* only allow one at a time */
182 if (down_trylock(&open_semaphore)) 185 if (test_and_set_bit(0, &wdt_is_open))
183 return -EBUSY; 186 return -EBUSY;
184 ar7_wdt_enable_wdt(); 187 ar7_wdt_enable_wdt();
185 expect_close = 0; 188 expect_close = 0;
@@ -195,9 +198,7 @@ static int ar7_wdt_release(struct inode *inode, struct file *file)
195 "will not disable the watchdog timer\n"); 198 "will not disable the watchdog timer\n");
196 else if (!nowayout) 199 else if (!nowayout)
197 ar7_wdt_disable_wdt(); 200 ar7_wdt_disable_wdt();
198 201 clear_bit(0, &wdt_is_open);
199 up(&open_semaphore);
200
201 return 0; 202 return 0;
202} 203}
203 204
@@ -222,7 +223,9 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data,
222 if (len) { 223 if (len) {
223 size_t i; 224 size_t i;
224 225
226 spin_lock(&wdt_lock);
225 ar7_wdt_kick(1); 227 ar7_wdt_kick(1);
228 spin_unlock(&wdt_lock);
226 229
227 expect_close = 0; 230 expect_close = 0;
228 for (i = 0; i < len; ++i) { 231 for (i = 0; i < len; ++i) {
@@ -237,8 +240,8 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data,
237 return len; 240 return len;
238} 241}
239 242
240static int ar7_wdt_ioctl(struct inode *inode, struct file *file, 243static long ar7_wdt_ioctl(struct file *file,
241 unsigned int cmd, unsigned long arg) 244 unsigned int cmd, unsigned long arg)
242{ 245{
243 static struct watchdog_info ident = { 246 static struct watchdog_info ident = {
244 .identity = LONGNAME, 247 .identity = LONGNAME,
@@ -269,8 +272,10 @@ static int ar7_wdt_ioctl(struct inode *inode, struct file *file,
269 if (new_margin < 1) 272 if (new_margin < 1)
270 return -EINVAL; 273 return -EINVAL;
271 274
275 spin_lock(&wdt_lock);
272 ar7_wdt_update_margin(new_margin); 276 ar7_wdt_update_margin(new_margin);
273 ar7_wdt_kick(1); 277 ar7_wdt_kick(1);
278 spin_unlock(&wdt_lock);
274 279
275 case WDIOC_GETTIMEOUT: 280 case WDIOC_GETTIMEOUT:
276 if (put_user(margin, (int *)arg)) 281 if (put_user(margin, (int *)arg))
@@ -282,7 +287,7 @@ static int ar7_wdt_ioctl(struct inode *inode, struct file *file,
282static const struct file_operations ar7_wdt_fops = { 287static const struct file_operations ar7_wdt_fops = {
283 .owner = THIS_MODULE, 288 .owner = THIS_MODULE,
284 .write = ar7_wdt_write, 289 .write = ar7_wdt_write,
285 .ioctl = ar7_wdt_ioctl, 290 .unlocked_ioctl = ar7_wdt_ioctl,
286 .open = ar7_wdt_open, 291 .open = ar7_wdt_open,
287 .release = ar7_wdt_release, 292 .release = ar7_wdt_release,
288}; 293};
@@ -297,6 +302,8 @@ static int __init ar7_wdt_init(void)
297{ 302{
298 int rc; 303 int rc;
299 304
305 spin_lock_init(&wdt_lock);
306
300 ar7_wdt_get_regs(); 307 ar7_wdt_get_regs();
301 308
302 if (!request_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt), 309 if (!request_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt),
@@ -312,8 +319,6 @@ static int __init ar7_wdt_init(void)
312 ar7_wdt_prescale(prescale_value); 319 ar7_wdt_prescale(prescale_value);
313 ar7_wdt_update_margin(margin); 320 ar7_wdt_update_margin(margin);
314 321
315 sema_init(&open_semaphore, 1);
316
317 rc = register_reboot_notifier(&ar7_wdt_notifier); 322 rc = register_reboot_notifier(&ar7_wdt_notifier);
318 if (rc) { 323 if (rc) {
319 printk(KERN_ERR DRVNAME 324 printk(KERN_ERR DRVNAME
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index eaa3f2a79ff5..ccd6c530782d 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -420,7 +420,7 @@ static int __devinit detect_cru_service(void)
420static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, 420static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason,
421 void *data) 421 void *data)
422{ 422{
423 static unsigned long rom_pl; 423 unsigned long rom_pl;
424 static int die_nmi_called; 424 static int die_nmi_called;
425 425
426 if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) 426 if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI)
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index 445b7e812112..51bfd5721833 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -30,9 +30,8 @@
30#include <linux/fs.h> 30#include <linux/fs.h>
31#include <linux/pci.h> 31#include <linux/pci.h>
32#include <linux/spinlock.h> 32#include <linux/spinlock.h>
33 33#include <linux/uaccess.h>
34#include <asm/uaccess.h> 34#include <linux/io.h>
35#include <asm/io.h>
36 35
37#define NAME "it8712f_wdt" 36#define NAME "it8712f_wdt"
38 37
@@ -50,7 +49,7 @@ static int nowayout = WATCHDOG_NOWAYOUT;
50module_param(nowayout, int, 0); 49module_param(nowayout, int, 0);
51MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); 50MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
52 51
53static struct semaphore it8712f_wdt_sem; 52static unsigned long wdt_open;
54static unsigned expect_close; 53static unsigned expect_close;
55static spinlock_t io_lock; 54static spinlock_t io_lock;
56static unsigned char revision; 55static unsigned char revision;
@@ -86,22 +85,19 @@ static unsigned short address;
86#define WDT_OUT_PWROK 0x10 85#define WDT_OUT_PWROK 0x10
87#define WDT_OUT_KRST 0x40 86#define WDT_OUT_KRST 0x40
88 87
89static int 88static int superio_inb(int reg)
90superio_inb(int reg)
91{ 89{
92 outb(reg, REG); 90 outb(reg, REG);
93 return inb(VAL); 91 return inb(VAL);
94} 92}
95 93
96static void 94static void superio_outb(int val, int reg)
97superio_outb(int val, int reg)
98{ 95{
99 outb(reg, REG); 96 outb(reg, REG);
100 outb(val, VAL); 97 outb(val, VAL);
101} 98}
102 99
103static int 100static int superio_inw(int reg)
104superio_inw(int reg)
105{ 101{
106 int val; 102 int val;
107 outb(reg++, REG); 103 outb(reg++, REG);
@@ -111,15 +107,13 @@ superio_inw(int reg)
111 return val; 107 return val;
112} 108}
113 109
114static inline void 110static inline void superio_select(int ldn)
115superio_select(int ldn)
116{ 111{
117 outb(LDN, REG); 112 outb(LDN, REG);
118 outb(ldn, VAL); 113 outb(ldn, VAL);
119} 114}
120 115
121static inline void 116static inline void superio_enter(void)
122superio_enter(void)
123{ 117{
124 spin_lock(&io_lock); 118 spin_lock(&io_lock);
125 outb(0x87, REG); 119 outb(0x87, REG);
@@ -128,22 +122,19 @@ superio_enter(void)
128 outb(0x55, REG); 122 outb(0x55, REG);
129} 123}
130 124
131static inline void 125static inline void superio_exit(void)
132superio_exit(void)
133{ 126{
134 outb(0x02, REG); 127 outb(0x02, REG);
135 outb(0x02, VAL); 128 outb(0x02, VAL);
136 spin_unlock(&io_lock); 129 spin_unlock(&io_lock);
137} 130}
138 131
139static inline void 132static inline void it8712f_wdt_ping(void)
140it8712f_wdt_ping(void)
141{ 133{
142 inb(address); 134 inb(address);
143} 135}
144 136
145static void 137static void it8712f_wdt_update_margin(void)
146it8712f_wdt_update_margin(void)
147{ 138{
148 int config = WDT_OUT_KRST | WDT_OUT_PWROK; 139 int config = WDT_OUT_KRST | WDT_OUT_PWROK;
149 int units = margin; 140 int units = margin;
@@ -165,8 +156,7 @@ it8712f_wdt_update_margin(void)
165 superio_outb(units, WDT_TIMEOUT); 156 superio_outb(units, WDT_TIMEOUT);
166} 157}
167 158
168static int 159static int it8712f_wdt_get_status(void)
169it8712f_wdt_get_status(void)
170{ 160{
171 if (superio_inb(WDT_CONTROL) & 0x01) 161 if (superio_inb(WDT_CONTROL) & 0x01)
172 return WDIOF_CARDRESET; 162 return WDIOF_CARDRESET;
@@ -174,8 +164,7 @@ it8712f_wdt_get_status(void)
174 return 0; 164 return 0;
175} 165}
176 166
177static void 167static void it8712f_wdt_enable(void)
178it8712f_wdt_enable(void)
179{ 168{
180 printk(KERN_DEBUG NAME ": enabling watchdog timer\n"); 169 printk(KERN_DEBUG NAME ": enabling watchdog timer\n");
181 superio_enter(); 170 superio_enter();
@@ -190,8 +179,7 @@ it8712f_wdt_enable(void)
190 it8712f_wdt_ping(); 179 it8712f_wdt_ping();
191} 180}
192 181
193static void 182static void it8712f_wdt_disable(void)
194it8712f_wdt_disable(void)
195{ 183{
196 printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); 184 printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
197 185
@@ -207,8 +195,7 @@ it8712f_wdt_disable(void)
207 superio_exit(); 195 superio_exit();
208} 196}
209 197
210static int 198static int it8712f_wdt_notify(struct notifier_block *this,
211it8712f_wdt_notify(struct notifier_block *this,
212 unsigned long code, void *unused) 199 unsigned long code, void *unused)
213{ 200{
214 if (code == SYS_HALT || code == SYS_POWER_OFF) 201 if (code == SYS_HALT || code == SYS_POWER_OFF)
@@ -222,9 +209,8 @@ static struct notifier_block it8712f_wdt_notifier = {
222 .notifier_call = it8712f_wdt_notify, 209 .notifier_call = it8712f_wdt_notify,
223}; 210};
224 211
225static ssize_t 212static ssize_t it8712f_wdt_write(struct file *file, const char __user *data,
226it8712f_wdt_write(struct file *file, const char __user *data, 213 size_t len, loff_t *ppos)
227 size_t len, loff_t *ppos)
228{ 214{
229 /* check for a magic close character */ 215 /* check for a magic close character */
230 if (len) { 216 if (len) {
@@ -245,9 +231,8 @@ it8712f_wdt_write(struct file *file, const char __user *data,
245 return len; 231 return len;
246} 232}
247 233
248static int 234static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
249it8712f_wdt_ioctl(struct inode *inode, struct file *file, 235 unsigned long arg)
250 unsigned int cmd, unsigned long arg)
251{ 236{
252 void __user *argp = (void __user *)arg; 237 void __user *argp = (void __user *)arg;
253 int __user *p = argp; 238 int __user *p = argp;
@@ -302,19 +287,16 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
302 } 287 }
303} 288}
304 289
305static int 290static int it8712f_wdt_open(struct inode *inode, struct file *file)
306it8712f_wdt_open(struct inode *inode, struct file *file)
307{ 291{
308 /* only allow one at a time */ 292 /* only allow one at a time */
309 if (down_trylock(&it8712f_wdt_sem)) 293 if (test_and_set_bit(0, &wdt_open))
310 return -EBUSY; 294 return -EBUSY;
311 it8712f_wdt_enable(); 295 it8712f_wdt_enable();
312
313 return nonseekable_open(inode, file); 296 return nonseekable_open(inode, file);
314} 297}
315 298
316static int 299static int it8712f_wdt_release(struct inode *inode, struct file *file)
317it8712f_wdt_release(struct inode *inode, struct file *file)
318{ 300{
319 if (expect_close != 42) { 301 if (expect_close != 42) {
320 printk(KERN_WARNING NAME 302 printk(KERN_WARNING NAME
@@ -324,7 +306,7 @@ it8712f_wdt_release(struct inode *inode, struct file *file)
324 it8712f_wdt_disable(); 306 it8712f_wdt_disable();
325 } 307 }
326 expect_close = 0; 308 expect_close = 0;
327 up(&it8712f_wdt_sem); 309 clear_bit(0, &wdt_open);
328 310
329 return 0; 311 return 0;
330} 312}
@@ -333,7 +315,7 @@ static const struct file_operations it8712f_wdt_fops = {
333 .owner = THIS_MODULE, 315 .owner = THIS_MODULE,
334 .llseek = no_llseek, 316 .llseek = no_llseek,
335 .write = it8712f_wdt_write, 317 .write = it8712f_wdt_write,
336 .ioctl = it8712f_wdt_ioctl, 318 .unlocked_ioctl = it8712f_wdt_ioctl,
337 .open = it8712f_wdt_open, 319 .open = it8712f_wdt_open,
338 .release = it8712f_wdt_release, 320 .release = it8712f_wdt_release,
339}; 321};
@@ -344,8 +326,7 @@ static struct miscdevice it8712f_wdt_miscdev = {
344 .fops = &it8712f_wdt_fops, 326 .fops = &it8712f_wdt_fops,
345}; 327};
346 328
347static int __init 329static int __init it8712f_wdt_find(unsigned short *address)
348it8712f_wdt_find(unsigned short *address)
349{ 330{
350 int err = -ENODEV; 331 int err = -ENODEV;
351 int chip_type; 332 int chip_type;
@@ -387,8 +368,7 @@ exit:
387 return err; 368 return err;
388} 369}
389 370
390static int __init 371static int __init it8712f_wdt_init(void)
391it8712f_wdt_init(void)
392{ 372{
393 int err = 0; 373 int err = 0;
394 374
@@ -404,8 +384,6 @@ it8712f_wdt_init(void)
404 384
405 it8712f_wdt_disable(); 385 it8712f_wdt_disable();
406 386
407 sema_init(&it8712f_wdt_sem, 1);
408
409 err = register_reboot_notifier(&it8712f_wdt_notifier); 387 err = register_reboot_notifier(&it8712f_wdt_notifier);
410 if (err) { 388 if (err) {
411 printk(KERN_ERR NAME ": unable to register reboot notifier\n"); 389 printk(KERN_ERR NAME ": unable to register reboot notifier\n");
@@ -430,8 +408,7 @@ out:
430 return err; 408 return err;
431} 409}
432 410
433static void __exit 411static void __exit it8712f_wdt_exit(void)
434it8712f_wdt_exit(void)
435{ 412{
436 misc_deregister(&it8712f_wdt_miscdev); 413 misc_deregister(&it8712f_wdt_miscdev);
437 unregister_reboot_notifier(&it8712f_wdt_notifier); 414 unregister_reboot_notifier(&it8712f_wdt_notifier);
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 98532c0e0689..97b4a2e8eb09 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -46,9 +46,8 @@
46#include <linux/platform_device.h> 46#include <linux/platform_device.h>
47#include <linux/interrupt.h> 47#include <linux/interrupt.h>
48#include <linux/clk.h> 48#include <linux/clk.h>
49 49#include <linux/uaccess.h>
50#include <asm/uaccess.h> 50#include <linux/io.h>
51#include <asm/io.h>
52 51
53#include <asm/arch/map.h> 52#include <asm/arch/map.h>
54 53
@@ -65,8 +64,8 @@
65static int nowayout = WATCHDOG_NOWAYOUT; 64static int nowayout = WATCHDOG_NOWAYOUT;
66static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME; 65static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;
67static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT; 66static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT;
68static int soft_noboot = 0; 67static int soft_noboot;
69static int debug = 0; 68static int debug;
70 69
71module_param(tmr_margin, int, 0); 70module_param(tmr_margin, int, 0);
72module_param(tmr_atboot, int, 0); 71module_param(tmr_atboot, int, 0);
@@ -74,24 +73,23 @@ module_param(nowayout, int, 0);
74module_param(soft_noboot, int, 0); 73module_param(soft_noboot, int, 0);
75module_param(debug, int, 0); 74module_param(debug, int, 0);
76 75
77MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME) ")"); 76MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. default="
78 77 __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME) ")");
79MODULE_PARM_DESC(tmr_atboot, "Watchdog is started at boot time if set to 1, default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT)); 78MODULE_PARM_DESC(tmr_atboot,
80 79 "Watchdog is started at boot time if set to 1, default="
81MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 80 __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT));
82 81MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
82 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
83MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)"); 83MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)");
84
85MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug, (default 0)"); 84MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug, (default 0)");
86 85
87 86
88typedef enum close_state { 87typedef enum close_state {
89 CLOSE_STATE_NOT, 88 CLOSE_STATE_NOT,
90 CLOSE_STATE_ALLOW=0x4021 89 CLOSE_STATE_ALLOW = 0x4021
91} close_state_t; 90} close_state_t;
92 91
93static DECLARE_MUTEX(open_lock); 92static unsigned long open_lock;
94
95static struct device *wdt_dev; /* platform device attached to */ 93static struct device *wdt_dev; /* platform device attached to */
96static struct resource *wdt_mem; 94static struct resource *wdt_mem;
97static struct resource *wdt_irq; 95static struct resource *wdt_irq;
@@ -99,38 +97,58 @@ static struct clk *wdt_clock;
99static void __iomem *wdt_base; 97static void __iomem *wdt_base;
100static unsigned int wdt_count; 98static unsigned int wdt_count;
101static close_state_t allow_close; 99static close_state_t allow_close;
100static DEFINE_SPINLOCK(wdt_lock);
102 101
103/* watchdog control routines */ 102/* watchdog control routines */
104 103
105#define DBG(msg...) do { \ 104#define DBG(msg...) do { \
106 if (debug) \ 105 if (debug) \
107 printk(KERN_INFO msg); \ 106 printk(KERN_INFO msg); \
108 } while(0) 107 } while (0)
109 108
110/* functions */ 109/* functions */
111 110
112static int s3c2410wdt_keepalive(void) 111static void s3c2410wdt_keepalive(void)
113{ 112{
113 spin_lock(&wdt_lock);
114 writel(wdt_count, wdt_base + S3C2410_WTCNT); 114 writel(wdt_count, wdt_base + S3C2410_WTCNT);
115 return 0; 115 spin_unlock(&wdt_lock);
116} 116}
117 117
118static int s3c2410wdt_stop(void) 118static void __s3c2410wdt_stop(void)
119{ 119{
120 unsigned long wtcon; 120 unsigned long wtcon;
121 121
122 spin_lock(&wdt_lock);
122 wtcon = readl(wdt_base + S3C2410_WTCON); 123 wtcon = readl(wdt_base + S3C2410_WTCON);
123 wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN); 124 wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN);
124 writel(wtcon, wdt_base + S3C2410_WTCON); 125 writel(wtcon, wdt_base + S3C2410_WTCON);
126 spin_unlock(&wdt_lock);
127}
125 128
126 return 0; 129static void __s3c2410wdt_stop(void)
130{
131 unsigned long wtcon;
132
133 wtcon = readl(wdt_base + S3C2410_WTCON);
134 wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN);
135 writel(wtcon, wdt_base + S3C2410_WTCON);
136}
137
138static void s3c2410wdt_stop(void)
139{
140 spin_lock(&wdt_lock);
141 __s3c2410wdt_stop();
142 spin_unlock(&wdt_lock);
127} 143}
128 144
129static int s3c2410wdt_start(void) 145static void s3c2410wdt_start(void)
130{ 146{
131 unsigned long wtcon; 147 unsigned long wtcon;
132 148
133 s3c2410wdt_stop(); 149 spin_lock(&wdt_lock);
150
151 __s3c2410wdt_stop();
134 152
135 wtcon = readl(wdt_base + S3C2410_WTCON); 153 wtcon = readl(wdt_base + S3C2410_WTCON);
136 wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128; 154 wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128;
@@ -149,6 +167,7 @@ static int s3c2410wdt_start(void)
149 writel(wdt_count, wdt_base + S3C2410_WTDAT); 167 writel(wdt_count, wdt_base + S3C2410_WTDAT);
150 writel(wdt_count, wdt_base + S3C2410_WTCNT); 168 writel(wdt_count, wdt_base + S3C2410_WTCNT);
151 writel(wtcon, wdt_base + S3C2410_WTCON); 169 writel(wtcon, wdt_base + S3C2410_WTCON);
170 spin_unlock(&wdt_lock);
152 171
153 return 0; 172 return 0;
154} 173}
@@ -211,7 +230,7 @@ static int s3c2410wdt_set_heartbeat(int timeout)
211 230
212static int s3c2410wdt_open(struct inode *inode, struct file *file) 231static int s3c2410wdt_open(struct inode *inode, struct file *file)
213{ 232{
214 if(down_trylock(&open_lock)) 233 if (test_and_set_bit(0, &open_lock))
215 return -EBUSY; 234 return -EBUSY;
216 235
217 if (nowayout) 236 if (nowayout)
@@ -231,15 +250,14 @@ static int s3c2410wdt_release(struct inode *inode, struct file *file)
231 * Lock it in if it's a module and we set nowayout 250 * Lock it in if it's a module and we set nowayout
232 */ 251 */
233 252
234 if (allow_close == CLOSE_STATE_ALLOW) { 253 if (allow_close == CLOSE_STATE_ALLOW)
235 s3c2410wdt_stop(); 254 s3c2410wdt_stop();
236 } else { 255 else {
237 dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n"); 256 dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n");
238 s3c2410wdt_keepalive(); 257 s3c2410wdt_keepalive();
239 } 258 }
240
241 allow_close = CLOSE_STATE_NOT; 259 allow_close = CLOSE_STATE_NOT;
242 up(&open_lock); 260 clear_bit(0, &open_lock);
243 return 0; 261 return 0;
244} 262}
245 263
@@ -249,7 +267,7 @@ static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
249 /* 267 /*
250 * Refresh the timer. 268 * Refresh the timer.
251 */ 269 */
252 if(len) { 270 if (len) {
253 if (!nowayout) { 271 if (!nowayout) {
254 size_t i; 272 size_t i;
255 273
@@ -265,7 +283,6 @@ static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
265 allow_close = CLOSE_STATE_ALLOW; 283 allow_close = CLOSE_STATE_ALLOW;
266 } 284 }
267 } 285 }
268
269 s3c2410wdt_keepalive(); 286 s3c2410wdt_keepalive();
270 } 287 }
271 return len; 288 return len;
@@ -273,48 +290,41 @@ static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
273 290
274#define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE 291#define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE
275 292
276static struct watchdog_info s3c2410_wdt_ident = { 293static const struct watchdog_info s3c2410_wdt_ident = {
277 .options = OPTIONS, 294 .options = OPTIONS,
278 .firmware_version = 0, 295 .firmware_version = 0,
279 .identity = "S3C2410 Watchdog", 296 .identity = "S3C2410 Watchdog",
280}; 297};
281 298
282 299
283static int s3c2410wdt_ioctl(struct inode *inode, struct file *file, 300static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd,
284 unsigned int cmd, unsigned long arg) 301 unsigned long arg)
285{ 302{
286 void __user *argp = (void __user *)arg; 303 void __user *argp = (void __user *)arg;
287 int __user *p = argp; 304 int __user *p = argp;
288 int new_margin; 305 int new_margin;
289 306
290 switch (cmd) { 307 switch (cmd) {
291 default: 308 default:
292 return -ENOTTY; 309 return -ENOTTY;
293 310 case WDIOC_GETSUPPORT:
294 case WDIOC_GETSUPPORT: 311 return copy_to_user(argp, &s3c2410_wdt_ident,
295 return copy_to_user(argp, &s3c2410_wdt_ident, 312 sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0;
296 sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0; 313 case WDIOC_GETSTATUS:
297 314 case WDIOC_GETBOOTSTATUS:
298 case WDIOC_GETSTATUS: 315 return put_user(0, p);
299 case WDIOC_GETBOOTSTATUS: 316 case WDIOC_KEEPALIVE:
300 return put_user(0, p); 317 s3c2410wdt_keepalive();
301 318 return 0;
302 case WDIOC_KEEPALIVE: 319 case WDIOC_SETTIMEOUT:
303 s3c2410wdt_keepalive(); 320 if (get_user(new_margin, p))
304 return 0; 321 return -EFAULT;
305 322 if (s3c2410wdt_set_heartbeat(new_margin))
306 case WDIOC_SETTIMEOUT: 323 return -EINVAL;
307 if (get_user(new_margin, p)) 324 s3c2410wdt_keepalive();
308 return -EFAULT; 325 return put_user(tmr_margin, p);
309 326 case WDIOC_GETTIMEOUT:
310 if (s3c2410wdt_set_heartbeat(new_margin)) 327 return put_user(tmr_margin, p);
311 return -EINVAL;
312
313 s3c2410wdt_keepalive();
314 return put_user(tmr_margin, p);
315
316 case WDIOC_GETTIMEOUT:
317 return put_user(tmr_margin, p);
318 } 328 }
319} 329}
320 330
@@ -324,7 +334,7 @@ static const struct file_operations s3c2410wdt_fops = {
324 .owner = THIS_MODULE, 334 .owner = THIS_MODULE,
325 .llseek = no_llseek, 335 .llseek = no_llseek,
326 .write = s3c2410wdt_write, 336 .write = s3c2410wdt_write,
327 .ioctl = s3c2410wdt_ioctl, 337 .unlocked_ioctl = s3c2410wdt_ioctl,
328 .open = s3c2410wdt_open, 338 .open = s3c2410wdt_open,
329 .release = s3c2410wdt_release, 339 .release = s3c2410wdt_release,
330}; 340};
@@ -411,14 +421,15 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
411 * not, try the default value */ 421 * not, try the default value */
412 422
413 if (s3c2410wdt_set_heartbeat(tmr_margin)) { 423 if (s3c2410wdt_set_heartbeat(tmr_margin)) {
414 started = s3c2410wdt_set_heartbeat(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME); 424 started = s3c2410wdt_set_heartbeat(
425 CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
415 426
416 if (started == 0) { 427 if (started == 0)
417 dev_info(dev,"tmr_margin value out of range, default %d used\n", 428 dev_info(dev,
429 "tmr_margin value out of range, default %d used\n",
418 CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME); 430 CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
419 } else { 431 else
420 dev_info(dev, "default timer value is out of range, cannot start\n"); 432 dev_info(dev, "default timer value is out of range, cannot start\n");
421 }
422 } 433 }
423 434
424 ret = misc_register(&s3c2410wdt_miscdev); 435 ret = misc_register(&s3c2410wdt_miscdev);
@@ -447,7 +458,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
447 (wtcon & S3C2410_WTCON_ENABLE) ? "" : "in", 458 (wtcon & S3C2410_WTCON_ENABLE) ? "" : "in",
448 (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis", 459 (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis",
449 (wtcon & S3C2410_WTCON_INTEN) ? "" : "en"); 460 (wtcon & S3C2410_WTCON_INTEN) ? "" : "en");
450 461
451 return 0; 462 return 0;
452 463
453 err_clk: 464 err_clk:
@@ -487,7 +498,7 @@ static int s3c2410wdt_remove(struct platform_device *dev)
487 498
488static void s3c2410wdt_shutdown(struct platform_device *dev) 499static void s3c2410wdt_shutdown(struct platform_device *dev)
489{ 500{
490 s3c2410wdt_stop(); 501 s3c2410wdt_stop();
491} 502}
492 503
493#ifdef CONFIG_PM 504#ifdef CONFIG_PM
@@ -540,7 +551,8 @@ static struct platform_driver s3c2410wdt_driver = {
540}; 551};
541 552
542 553
543static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"; 554static char banner[] __initdata =
555 KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n";
544 556
545static int __init watchdog_init(void) 557static int __init watchdog_init(void)
546{ 558{
diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c
index 35cddff7020f..621ebad56d86 100644
--- a/drivers/watchdog/sc1200wdt.c
+++ b/drivers/watchdog/sc1200wdt.c
@@ -15,14 +15,18 @@
15 * 15 *
16 * Changelog: 16 * Changelog:
17 * 20020220 Zwane Mwaikambo Code based on datasheet, no hardware. 17 * 20020220 Zwane Mwaikambo Code based on datasheet, no hardware.
18 * 20020221 Zwane Mwaikambo Cleanups as suggested by Jeff Garzik and Alan Cox. 18 * 20020221 Zwane Mwaikambo Cleanups as suggested by Jeff Garzik
19 * and Alan Cox.
19 * 20020222 Zwane Mwaikambo Added probing. 20 * 20020222 Zwane Mwaikambo Added probing.
20 * 20020225 Zwane Mwaikambo Added ISAPNP support. 21 * 20020225 Zwane Mwaikambo Added ISAPNP support.
21 * 20020412 Rob Radez Broke out start/stop functions 22 * 20020412 Rob Radez Broke out start/stop functions
22 * <rob@osinvestor.com> Return proper status instead of temperature warning 23 * <rob@osinvestor.com> Return proper status instead of
23 * Add WDIOC_GETBOOTSTATUS and WDIOC_SETOPTIONS ioctls 24 * temperature warning
25 * Add WDIOC_GETBOOTSTATUS and
26 * WDIOC_SETOPTIONS ioctls
24 * Fix CONFIG_WATCHDOG_NOWAYOUT 27 * Fix CONFIG_WATCHDOG_NOWAYOUT
25 * 20020530 Joel Becker Add Matt Domsch's nowayout module option 28 * 20020530 Joel Becker Add Matt Domsch's nowayout module
29 * option
26 * 20030116 Adam Belay Updated to the latest pnp code 30 * 20030116 Adam Belay Updated to the latest pnp code
27 * 31 *
28 */ 32 */
@@ -39,9 +43,8 @@
39#include <linux/pnp.h> 43#include <linux/pnp.h>
40#include <linux/fs.h> 44#include <linux/fs.h>
41#include <linux/semaphore.h> 45#include <linux/semaphore.h>
42 46#include <linux/io.h>
43#include <asm/io.h> 47#include <linux/uaccess.h>
44#include <asm/uaccess.h>
45 48
46#define SC1200_MODULE_VER "build 20020303" 49#define SC1200_MODULE_VER "build 20020303"
47#define SC1200_MODULE_NAME "sc1200wdt" 50#define SC1200_MODULE_NAME "sc1200wdt"
@@ -72,7 +75,7 @@ static char banner[] __initdata = KERN_INFO PFX SC1200_MODULE_VER;
72static int timeout = 1; 75static int timeout = 1;
73static int io = -1; 76static int io = -1;
74static int io_len = 2; /* for non plug and play */ 77static int io_len = 2; /* for non plug and play */
75static struct semaphore open_sem; 78static unsigned long open_flag;
76static char expect_close; 79static char expect_close;
77static DEFINE_SPINLOCK(sc1200wdt_lock); /* io port access serialisation */ 80static DEFINE_SPINLOCK(sc1200wdt_lock); /* io port access serialisation */
78 81
@@ -81,7 +84,8 @@ static int isapnp = 1;
81static struct pnp_dev *wdt_dev; 84static struct pnp_dev *wdt_dev;
82 85
83module_param(isapnp, int, 0); 86module_param(isapnp, int, 0);
84MODULE_PARM_DESC(isapnp, "When set to 0 driver ISA PnP support will be disabled"); 87MODULE_PARM_DESC(isapnp,
88 "When set to 0 driver ISA PnP support will be disabled");
85#endif 89#endif
86 90
87module_param(io, int, 0); 91module_param(io, int, 0);
@@ -91,26 +95,40 @@ MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1");
91 95
92static int nowayout = WATCHDOG_NOWAYOUT; 96static int nowayout = WATCHDOG_NOWAYOUT;
93module_param(nowayout, int, 0); 97module_param(nowayout, int, 0);
94MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 98MODULE_PARM_DESC(nowayout,
99 "Watchdog cannot be stopped once started (default="
100 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
95 101
96 102
97 103
98/* Read from Data Register */ 104/* Read from Data Register */
99static inline void sc1200wdt_read_data(unsigned char index, unsigned char *data) 105static inline void __sc1200wdt_read_data(unsigned char index,
106 unsigned char *data)
100{ 107{
101 spin_lock(&sc1200wdt_lock);
102 outb_p(index, PMIR); 108 outb_p(index, PMIR);
103 *data = inb(PMDR); 109 *data = inb(PMDR);
104 spin_unlock(&sc1200wdt_lock);
105} 110}
106 111
112static void sc1200wdt_read_data(unsigned char index, unsigned char *data)
113{
114 spin_lock(&sc1200wdt_lock);
115 __sc1200wdt_read_data(index, data);
116 spin_unlock(&sc1200wdt_lock);
117}
107 118
108/* Write to Data Register */ 119/* Write to Data Register */
109static inline void sc1200wdt_write_data(unsigned char index, unsigned char data) 120static inline void __sc1200wdt_write_data(unsigned char index,
121 unsigned char data)
110{ 122{
111 spin_lock(&sc1200wdt_lock);
112 outb_p(index, PMIR); 123 outb_p(index, PMIR);
113 outb(data, PMDR); 124 outb(data, PMDR);
125}
126
127static inline void sc1200wdt_write_data(unsigned char index,
128 unsigned char data)
129{
130 spin_lock(&sc1200wdt_lock);
131 __sc1200wdt_write_data(index, data);
114 spin_unlock(&sc1200wdt_lock); 132 spin_unlock(&sc1200wdt_lock);
115} 133}
116 134
@@ -118,22 +136,23 @@ static inline void sc1200wdt_write_data(unsigned char index, unsigned char data)
118static void sc1200wdt_start(void) 136static void sc1200wdt_start(void)
119{ 137{
120 unsigned char reg; 138 unsigned char reg;
139 spin_lock(&sc1200wdt_lock);
121 140
122 sc1200wdt_read_data(WDCF, &reg); 141 __sc1200wdt_read_data(WDCF, &reg);
123 /* assert WDO when any of the following interrupts are triggered too */ 142 /* assert WDO when any of the following interrupts are triggered too */
124 reg |= (KBC_IRQ | MSE_IRQ | UART1_IRQ | UART2_IRQ); 143 reg |= (KBC_IRQ | MSE_IRQ | UART1_IRQ | UART2_IRQ);
125 sc1200wdt_write_data(WDCF, reg); 144 __sc1200wdt_write_data(WDCF, reg);
126 /* set the timeout and get the ball rolling */ 145 /* set the timeout and get the ball rolling */
127 sc1200wdt_write_data(WDTO, timeout); 146 __sc1200wdt_write_data(WDTO, timeout);
128}
129 147
148 spin_unlock(&sc1200wdt_lock);
149}
130 150
131static void sc1200wdt_stop(void) 151static void sc1200wdt_stop(void)
132{ 152{
133 sc1200wdt_write_data(WDTO, 0); 153 sc1200wdt_write_data(WDTO, 0);
134} 154}
135 155
136
137/* This returns the status of the WDO signal, inactive high. */ 156/* This returns the status of the WDO signal, inactive high. */
138static inline int sc1200wdt_status(void) 157static inline int sc1200wdt_status(void)
139{ 158{
@@ -144,14 +163,13 @@ static inline int sc1200wdt_status(void)
144 * KEEPALIVEPING which is a bit of a kludge because there's nothing 163 * KEEPALIVEPING which is a bit of a kludge because there's nothing
145 * else for enabled/disabled status 164 * else for enabled/disabled status
146 */ 165 */
147 return (ret & 0x01) ? 0 : WDIOF_KEEPALIVEPING; /* bits 1 - 7 are undefined */ 166 return (ret & 0x01) ? 0 : WDIOF_KEEPALIVEPING;
148} 167}
149 168
150
151static int sc1200wdt_open(struct inode *inode, struct file *file) 169static int sc1200wdt_open(struct inode *inode, struct file *file)
152{ 170{
153 /* allow one at a time */ 171 /* allow one at a time */
154 if (down_trylock(&open_sem)) 172 if (test_and_set_bit(0, &open_flag))
155 return -EBUSY; 173 return -EBUSY;
156 174
157 if (timeout > MAX_TIMEOUT) 175 if (timeout > MAX_TIMEOUT)
@@ -164,71 +182,71 @@ static int sc1200wdt_open(struct inode *inode, struct file *file)
164} 182}
165 183
166 184
167static int sc1200wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 185static long sc1200wdt_ioctl(struct file *file, unsigned int cmd,
186 unsigned long arg)
168{ 187{
169 int new_timeout; 188 int new_timeout;
170 void __user *argp = (void __user *)arg; 189 void __user *argp = (void __user *)arg;
171 int __user *p = argp; 190 int __user *p = argp;
172 static struct watchdog_info ident = { 191 static const struct watchdog_info ident = {
173 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 192 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
193 WDIOF_MAGICCLOSE,
174 .firmware_version = 0, 194 .firmware_version = 0,
175 .identity = "PC87307/PC97307", 195 .identity = "PC87307/PC97307",
176 }; 196 };
177 197
178 switch (cmd) { 198 switch (cmd) {
179 default:
180 return -ENOTTY;
181
182 case WDIOC_GETSUPPORT:
183 if (copy_to_user(argp, &ident, sizeof ident))
184 return -EFAULT;
185 return 0;
186
187 case WDIOC_GETSTATUS:
188 return put_user(sc1200wdt_status(), p);
189
190 case WDIOC_GETBOOTSTATUS:
191 return put_user(0, p);
192
193 case WDIOC_KEEPALIVE:
194 sc1200wdt_write_data(WDTO, timeout);
195 return 0;
196 199
197 case WDIOC_SETTIMEOUT: 200 case WDIOC_GETSUPPORT:
198 if (get_user(new_timeout, p)) 201 if (copy_to_user(argp, &ident, sizeof ident))
199 return -EFAULT; 202 return -EFAULT;
203 return 0;
200 204
201 /* the API states this is given in secs */ 205 case WDIOC_GETSTATUS:
202 new_timeout /= 60; 206 return put_user(sc1200wdt_status(), p);
203 if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
204 return -EINVAL;
205 207
206 timeout = new_timeout; 208 case WDIOC_GETBOOTSTATUS:
207 sc1200wdt_write_data(WDTO, timeout); 209 return put_user(0, p);
208 /* fall through and return the new timeout */
209 210
210 case WDIOC_GETTIMEOUT: 211 case WDIOC_KEEPALIVE:
211 return put_user(timeout * 60, p); 212 sc1200wdt_write_data(WDTO, timeout);
213 return 0;
214
215 case WDIOC_SETTIMEOUT:
216 if (get_user(new_timeout, p))
217 return -EFAULT;
218 /* the API states this is given in secs */
219 new_timeout /= 60;
220 if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
221 return -EINVAL;
222 timeout = new_timeout;
223 sc1200wdt_write_data(WDTO, timeout);
224 /* fall through and return the new timeout */
212 225
213 case WDIOC_SETOPTIONS: 226 case WDIOC_GETTIMEOUT:
214 { 227 return put_user(timeout * 60, p);
215 int options, retval = -EINVAL;
216 228
217 if (get_user(options, p)) 229 case WDIOC_SETOPTIONS:
218 return -EFAULT; 230 {
231 int options, retval = -EINVAL;
219 232
220 if (options & WDIOS_DISABLECARD) { 233 if (get_user(options, p))
221 sc1200wdt_stop(); 234 return -EFAULT;
222 retval = 0;
223 }
224 235
225 if (options & WDIOS_ENABLECARD) { 236 if (options & WDIOS_DISABLECARD) {
226 sc1200wdt_start(); 237 sc1200wdt_stop();
227 retval = 0; 238 retval = 0;
228 } 239 }
229 240
230 return retval; 241 if (options & WDIOS_ENABLECARD) {
242 sc1200wdt_start();
243 retval = 0;
231 } 244 }
245
246 return retval;
247 }
248 default:
249 return -ENOTTY;
232 } 250 }
233} 251}
234 252
@@ -240,16 +258,18 @@ static int sc1200wdt_release(struct inode *inode, struct file *file)
240 printk(KERN_INFO PFX "Watchdog disabled\n"); 258 printk(KERN_INFO PFX "Watchdog disabled\n");
241 } else { 259 } else {
242 sc1200wdt_write_data(WDTO, timeout); 260 sc1200wdt_write_data(WDTO, timeout);
243 printk(KERN_CRIT PFX "Unexpected close!, timeout = %d min(s)\n", timeout); 261 printk(KERN_CRIT PFX
262 "Unexpected close!, timeout = %d min(s)\n", timeout);
244 } 263 }
245 up(&open_sem); 264 clear_bit(0, &open_flag);
246 expect_close = 0; 265 expect_close = 0;
247 266
248 return 0; 267 return 0;
249} 268}
250 269
251 270
252static ssize_t sc1200wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) 271static ssize_t sc1200wdt_write(struct file *file, const char __user *data,
272 size_t len, loff_t *ppos)
253{ 273{
254 if (len) { 274 if (len) {
255 if (!nowayout) { 275 if (!nowayout) {
@@ -275,7 +295,8 @@ static ssize_t sc1200wdt_write(struct file *file, const char __user *data, size_
275} 295}
276 296
277 297
278static int sc1200wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) 298static int sc1200wdt_notify_sys(struct notifier_block *this,
299 unsigned long code, void *unused)
279{ 300{
280 if (code == SYS_DOWN || code == SYS_HALT) 301 if (code == SYS_DOWN || code == SYS_HALT)
281 sc1200wdt_stop(); 302 sc1200wdt_stop();
@@ -284,23 +305,20 @@ static int sc1200wdt_notify_sys(struct notifier_block *this, unsigned long code,
284} 305}
285 306
286 307
287static struct notifier_block sc1200wdt_notifier = 308static struct notifier_block sc1200wdt_notifier = {
288{
289 .notifier_call = sc1200wdt_notify_sys, 309 .notifier_call = sc1200wdt_notify_sys,
290}; 310};
291 311
292static const struct file_operations sc1200wdt_fops = 312static const struct file_operations sc1200wdt_fops = {
293{
294 .owner = THIS_MODULE, 313 .owner = THIS_MODULE,
295 .llseek = no_llseek, 314 .llseek = no_llseek,
296 .write = sc1200wdt_write, 315 .write = sc1200wdt_write,
297 .ioctl = sc1200wdt_ioctl, 316 .unlocked_ioctl = sc1200wdt_ioctl,
298 .open = sc1200wdt_open, 317 .open = sc1200wdt_open,
299 .release = sc1200wdt_release, 318 .release = sc1200wdt_release,
300}; 319};
301 320
302static struct miscdevice sc1200wdt_miscdev = 321static struct miscdevice sc1200wdt_miscdev = {
303{
304 .minor = WATCHDOG_MINOR, 322 .minor = WATCHDOG_MINOR,
305 .name = "watchdog", 323 .name = "watchdog",
306 .fops = &sc1200wdt_fops, 324 .fops = &sc1200wdt_fops,
@@ -312,14 +330,14 @@ static int __init sc1200wdt_probe(void)
312 /* The probe works by reading the PMC3 register's default value of 0x0e 330 /* The probe works by reading the PMC3 register's default value of 0x0e
313 * there is one caveat, if the device disables the parallel port or any 331 * there is one caveat, if the device disables the parallel port or any
314 * of the UARTs we won't be able to detect it. 332 * of the UARTs we won't be able to detect it.
315 * Nb. This could be done with accuracy by reading the SID registers, but 333 * NB. This could be done with accuracy by reading the SID registers,
316 * we don't have access to those io regions. 334 * but we don't have access to those io regions.
317 */ 335 */
318 336
319 unsigned char reg; 337 unsigned char reg;
320 338
321 sc1200wdt_read_data(PMC3, &reg); 339 sc1200wdt_read_data(PMC3, &reg);
322 reg &= 0x0f; /* we don't want the UART busy bits */ 340 reg &= 0x0f; /* we don't want the UART busy bits */
323 return (reg == 0x0e) ? 0 : -ENODEV; 341 return (reg == 0x0e) ? 0 : -ENODEV;
324} 342}
325 343
@@ -332,7 +350,8 @@ static struct pnp_device_id scl200wdt_pnp_devices[] = {
332 {.id = ""}, 350 {.id = ""},
333}; 351};
334 352
335static int scl200wdt_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) 353static int scl200wdt_pnp_probe(struct pnp_dev *dev,
354 const struct pnp_device_id *dev_id)
336{ 355{
337 /* this driver only supports one card at a time */ 356 /* this driver only supports one card at a time */
338 if (wdt_dev || !isapnp) 357 if (wdt_dev || !isapnp)
@@ -347,13 +366,14 @@ static int scl200wdt_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id
347 return -EBUSY; 366 return -EBUSY;
348 } 367 }
349 368
350 printk(KERN_INFO "scl200wdt: PnP device found at io port %#x/%d\n", io, io_len); 369 printk(KERN_INFO "scl200wdt: PnP device found at io port %#x/%d\n",
370 io, io_len);
351 return 0; 371 return 0;
352} 372}
353 373
354static void scl200wdt_pnp_remove(struct pnp_dev * dev) 374static void scl200wdt_pnp_remove(struct pnp_dev *dev)
355{ 375{
356 if (wdt_dev){ 376 if (wdt_dev) {
357 release_region(io, io_len); 377 release_region(io, io_len);
358 wdt_dev = NULL; 378 wdt_dev = NULL;
359 } 379 }
@@ -375,8 +395,6 @@ static int __init sc1200wdt_init(void)
375 395
376 printk("%s\n", banner); 396 printk("%s\n", banner);
377 397
378 sema_init(&open_sem, 1);
379
380#if defined CONFIG_PNP 398#if defined CONFIG_PNP
381 if (isapnp) { 399 if (isapnp) {
382 ret = pnp_register_driver(&scl200wdt_pnp_driver); 400 ret = pnp_register_driver(&scl200wdt_pnp_driver);
@@ -410,13 +428,16 @@ static int __init sc1200wdt_init(void)
410 428
411 ret = register_reboot_notifier(&sc1200wdt_notifier); 429 ret = register_reboot_notifier(&sc1200wdt_notifier);
412 if (ret) { 430 if (ret) {
413 printk(KERN_ERR PFX "Unable to register reboot notifier err = %d\n", ret); 431 printk(KERN_ERR PFX
432 "Unable to register reboot notifier err = %d\n", ret);
414 goto out_io; 433 goto out_io;
415 } 434 }
416 435
417 ret = misc_register(&sc1200wdt_miscdev); 436 ret = misc_register(&sc1200wdt_miscdev);
418 if (ret) { 437 if (ret) {
419 printk(KERN_ERR PFX "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR); 438 printk(KERN_ERR PFX
439 "Unable to register miscdev on minor %d\n",
440 WATCHDOG_MINOR);
420 goto out_rbt; 441 goto out_rbt;
421 } 442 }
422 443
@@ -446,7 +467,7 @@ static void __exit sc1200wdt_exit(void)
446 unregister_reboot_notifier(&sc1200wdt_notifier); 467 unregister_reboot_notifier(&sc1200wdt_notifier);
447 468
448#if defined CONFIG_PNP 469#if defined CONFIG_PNP
449 if(isapnp) 470 if (isapnp)
450 pnp_unregister_driver(&scl200wdt_pnp_driver); 471 pnp_unregister_driver(&scl200wdt_pnp_driver);
451 else 472 else
452#endif 473#endif
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c
index 756fb15fdce7..53a6b18bcb9a 100644
--- a/drivers/watchdog/wdt.c
+++ b/drivers/watchdog/wdt.c
@@ -24,9 +24,10 @@
24 * Matt Crocker). 24 * Matt Crocker).
25 * Alan Cox : Added wdt= boot option 25 * Alan Cox : Added wdt= boot option
26 * Alan Cox : Cleaned up copy/user stuff 26 * Alan Cox : Cleaned up copy/user stuff
27 * Tim Hockin : Added insmod parameters, comment cleanup 27 * Tim Hockin : Added insmod parameters, comment
28 * Parameterized timeout 28 * cleanup, parameterized timeout
29 * Tigran Aivazian : Restructured wdt_init() to handle failures 29 * Tigran Aivazian : Restructured wdt_init() to handle
30 * failures
30 * Joel Becker : Added WDIOC_GET/SETTIMEOUT 31 * Joel Becker : Added WDIOC_GET/SETTIMEOUT
31 * Matt Domsch : Added nowayout module option 32 * Matt Domsch : Added nowayout module option
32 */ 33 */
@@ -42,9 +43,9 @@
42#include <linux/notifier.h> 43#include <linux/notifier.h>
43#include <linux/reboot.h> 44#include <linux/reboot.h>
44#include <linux/init.h> 45#include <linux/init.h>
46#include <linux/io.h>
47#include <linux/uaccess.h>
45 48
46#include <asm/io.h>
47#include <asm/uaccess.h>
48#include <asm/system.h> 49#include <asm/system.h>
49#include "wd501p.h" 50#include "wd501p.h"
50 51
@@ -60,15 +61,19 @@ static char expect_close;
60static int heartbeat = WD_TIMO; 61static int heartbeat = WD_TIMO;
61static int wd_heartbeat; 62static int wd_heartbeat;
62module_param(heartbeat, int, 0); 63module_param(heartbeat, int, 0);
63MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); 64MODULE_PARM_DESC(heartbeat,
65 "Watchdog heartbeat in seconds. (0 < heartbeat < 65536, default="
66 __MODULE_STRING(WD_TIMO) ")");
64 67
65static int nowayout = WATCHDOG_NOWAYOUT; 68static int nowayout = WATCHDOG_NOWAYOUT;
66module_param(nowayout, int, 0); 69module_param(nowayout, int, 0);
67MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 70MODULE_PARM_DESC(nowayout,
71 "Watchdog cannot be stopped once started (default="
72 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
68 73
69/* You must set these - there is no sane way to probe for this board. */ 74/* You must set these - there is no sane way to probe for this board. */
70static int io=0x240; 75static int io = 0x240;
71static int irq=11; 76static int irq = 11;
72 77
73static DEFINE_SPINLOCK(wdt_lock); 78static DEFINE_SPINLOCK(wdt_lock);
74 79
@@ -82,7 +87,8 @@ MODULE_PARM_DESC(irq, "WDT irq (default=11)");
82static int tachometer; 87static int tachometer;
83 88
84module_param(tachometer, int, 0); 89module_param(tachometer, int, 0);
85MODULE_PARM_DESC(tachometer, "WDT501-P Fan Tachometer support (0=disable, default=0)"); 90MODULE_PARM_DESC(tachometer,
91 "WDT501-P Fan Tachometer support (0=disable, default=0)");
86#endif /* CONFIG_WDT_501 */ 92#endif /* CONFIG_WDT_501 */
87 93
88/* 94/*
@@ -91,9 +97,9 @@ MODULE_PARM_DESC(tachometer, "WDT501-P Fan Tachometer support (0=disable, defaul
91 97
92static void wdt_ctr_mode(int ctr, int mode) 98static void wdt_ctr_mode(int ctr, int mode)
93{ 99{
94 ctr<<=6; 100 ctr <<= 6;
95 ctr|=0x30; 101 ctr |= 0x30;
96 ctr|=(mode<<1); 102 ctr |= (mode << 1);
97 outb_p(ctr, WDT_CR); 103 outb_p(ctr, WDT_CR);
98} 104}
99 105
@@ -114,12 +120,15 @@ static int wdt_start(void)
114 unsigned long flags; 120 unsigned long flags;
115 spin_lock_irqsave(&wdt_lock, flags); 121 spin_lock_irqsave(&wdt_lock, flags);
116 inb_p(WDT_DC); /* Disable watchdog */ 122 inb_p(WDT_DC); /* Disable watchdog */
117 wdt_ctr_mode(0,3); /* Program CTR0 for Mode 3: Square Wave Generator */ 123 wdt_ctr_mode(0, 3); /* Program CTR0 for Mode 3:
118 wdt_ctr_mode(1,2); /* Program CTR1 for Mode 2: Rate Generator */ 124 Square Wave Generator */
119 wdt_ctr_mode(2,0); /* Program CTR2 for Mode 0: Pulse on Terminal Count */ 125 wdt_ctr_mode(1, 2); /* Program CTR1 for Mode 2:
126 Rate Generator */
127 wdt_ctr_mode(2, 0); /* Program CTR2 for Mode 0:
128 Pulse on Terminal Count */
120 wdt_ctr_load(0, 8948); /* Count at 100Hz */ 129 wdt_ctr_load(0, 8948); /* Count at 100Hz */
121 wdt_ctr_load(1,wd_heartbeat); /* Heartbeat */ 130 wdt_ctr_load(1, wd_heartbeat); /* Heartbeat */
122 wdt_ctr_load(2,65535); /* Length of reset pulse */ 131 wdt_ctr_load(2, 65535); /* Length of reset pulse */
123 outb_p(0, WDT_DC); /* Enable watchdog */ 132 outb_p(0, WDT_DC); /* Enable watchdog */
124 spin_unlock_irqrestore(&wdt_lock, flags); 133 spin_unlock_irqrestore(&wdt_lock, flags);
125 return 0; 134 return 0;
@@ -131,13 +140,13 @@ static int wdt_start(void)
131 * Stop the watchdog driver. 140 * Stop the watchdog driver.
132 */ 141 */
133 142
134static int wdt_stop (void) 143static int wdt_stop(void)
135{ 144{
136 unsigned long flags; 145 unsigned long flags;
137 spin_lock_irqsave(&wdt_lock, flags); 146 spin_lock_irqsave(&wdt_lock, flags);
138 /* Turn the card off */ 147 /* Turn the card off */
139 inb_p(WDT_DC); /* Disable watchdog */ 148 inb_p(WDT_DC); /* Disable watchdog */
140 wdt_ctr_load(2,0); /* 0 length reset pulses now */ 149 wdt_ctr_load(2, 0); /* 0 length reset pulses now */
141 spin_unlock_irqrestore(&wdt_lock, flags); 150 spin_unlock_irqrestore(&wdt_lock, flags);
142 return 0; 151 return 0;
143} 152}
@@ -145,8 +154,8 @@ static int wdt_stop (void)
145/** 154/**
146 * wdt_ping: 155 * wdt_ping:
147 * 156 *
148 * Reload counter one with the watchdog heartbeat. We don't bother reloading 157 * Reload counter one with the watchdog heartbeat. We don't bother
149 * the cascade counter. 158 * reloading the cascade counter.
150 */ 159 */
151 160
152static int wdt_ping(void) 161static int wdt_ping(void)
@@ -155,8 +164,9 @@ static int wdt_ping(void)
155 spin_lock_irqsave(&wdt_lock, flags); 164 spin_lock_irqsave(&wdt_lock, flags);
156 /* Write a watchdog value */ 165 /* Write a watchdog value */
157 inb_p(WDT_DC); /* Disable watchdog */ 166 inb_p(WDT_DC); /* Disable watchdog */
158 wdt_ctr_mode(1,2); /* Re-Program CTR1 for Mode 2: Rate Generator */ 167 wdt_ctr_mode(1, 2); /* Re-Program CTR1 for Mode 2:
159 wdt_ctr_load(1,wd_heartbeat); /* Heartbeat */ 168 Rate Generator */
169 wdt_ctr_load(1, wd_heartbeat); /* Heartbeat */
160 outb_p(0, WDT_DC); /* Enable watchdog */ 170 outb_p(0, WDT_DC); /* Enable watchdog */
161 spin_unlock_irqrestore(&wdt_lock, flags); 171 spin_unlock_irqrestore(&wdt_lock, flags);
162 return 0; 172 return 0;
@@ -166,13 +176,14 @@ static int wdt_ping(void)
166 * wdt_set_heartbeat: 176 * wdt_set_heartbeat:
167 * @t: the new heartbeat value that needs to be set. 177 * @t: the new heartbeat value that needs to be set.
168 * 178 *
169 * Set a new heartbeat value for the watchdog device. If the heartbeat value is 179 * Set a new heartbeat value for the watchdog device. If the heartbeat
170 * incorrect we keep the old value and return -EINVAL. If successfull we 180 * value is incorrect we keep the old value and return -EINVAL. If
171 * return 0. 181 * successful we return 0.
172 */ 182 */
183
173static int wdt_set_heartbeat(int t) 184static int wdt_set_heartbeat(int t)
174{ 185{
175 if ((t < 1) || (t > 65535)) 186 if (t < 1 || t > 65535)
176 return -EINVAL; 187 return -EINVAL;
177 188
178 heartbeat = t; 189 heartbeat = t;
@@ -200,7 +211,7 @@ static int wdt_get_status(int *status)
200 new_status = inb_p(WDT_SR); 211 new_status = inb_p(WDT_SR);
201 spin_unlock_irqrestore(&wdt_lock, flags); 212 spin_unlock_irqrestore(&wdt_lock, flags);
202 213
203 *status=0; 214 *status = 0;
204 if (new_status & WDC_SR_ISOI0) 215 if (new_status & WDC_SR_ISOI0)
205 *status |= WDIOF_EXTERN1; 216 *status |= WDIOF_EXTERN1;
206 if (new_status & WDC_SR_ISII1) 217 if (new_status & WDC_SR_ISII1)
@@ -266,7 +277,7 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id)
266 277
267#ifdef CONFIG_WDT_501 278#ifdef CONFIG_WDT_501
268 if (!(status & WDC_SR_TGOOD)) 279 if (!(status & WDC_SR_TGOOD))
269 printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT)); 280 printk(KERN_CRIT "Overheat alarm.(%d)\n", inb_p(WDT_RT));
270 if (!(status & WDC_SR_PSUOVER)) 281 if (!(status & WDC_SR_PSUOVER))
271 printk(KERN_CRIT "PSU over voltage.\n"); 282 printk(KERN_CRIT "PSU over voltage.\n");
272 if (!(status & WDC_SR_PSUUNDR)) 283 if (!(status & WDC_SR_PSUUNDR))
@@ -304,9 +315,10 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id)
304 * write of data will do, as we we don't define content meaning. 315 * write of data will do, as we we don't define content meaning.
305 */ 316 */
306 317
307static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 318static ssize_t wdt_write(struct file *file, const char __user *buf,
319 size_t count, loff_t *ppos)
308{ 320{
309 if(count) { 321 if (count) {
310 if (!nowayout) { 322 if (!nowayout) {
311 size_t i; 323 size_t i;
312 324
@@ -328,7 +340,6 @@ static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count
328 340
329/** 341/**
330 * wdt_ioctl: 342 * wdt_ioctl:
331 * @inode: inode of the device
332 * @file: file handle to the device 343 * @file: file handle to the device
333 * @cmd: watchdog command 344 * @cmd: watchdog command
334 * @arg: argument pointer 345 * @arg: argument pointer
@@ -338,8 +349,7 @@ static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count
338 * querying capabilities and current status. 349 * querying capabilities and current status.
339 */ 350 */
340 351
341static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 352static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
342 unsigned long arg)
343{ 353{
344 void __user *argp = (void __user *)arg; 354 void __user *argp = (void __user *)arg;
345 int __user *p = argp; 355 int __user *p = argp;
@@ -362,32 +372,28 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
362 ident.options |= WDIOF_FANFAULT; 372 ident.options |= WDIOF_FANFAULT;
363#endif /* CONFIG_WDT_501 */ 373#endif /* CONFIG_WDT_501 */
364 374
365 switch(cmd) 375 switch (cmd) {
366 { 376 default:
367 default: 377 return -ENOTTY;
368 return -ENOTTY; 378 case WDIOC_GETSUPPORT:
369 case WDIOC_GETSUPPORT: 379 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
370 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; 380 case WDIOC_GETSTATUS:
371 381 wdt_get_status(&status);
372 case WDIOC_GETSTATUS: 382 return put_user(status, p);
373 wdt_get_status(&status); 383 case WDIOC_GETBOOTSTATUS:
374 return put_user(status, p); 384 return put_user(0, p);
375 case WDIOC_GETBOOTSTATUS: 385 case WDIOC_KEEPALIVE:
376 return put_user(0, p); 386 wdt_ping();
377 case WDIOC_KEEPALIVE: 387 return 0;
378 wdt_ping(); 388 case WDIOC_SETTIMEOUT:
379 return 0; 389 if (get_user(new_heartbeat, p))
380 case WDIOC_SETTIMEOUT: 390 return -EFAULT;
381 if (get_user(new_heartbeat, p)) 391 if (wdt_set_heartbeat(new_heartbeat))
382 return -EFAULT; 392 return -EINVAL;
383 393 wdt_ping();
384 if (wdt_set_heartbeat(new_heartbeat)) 394 /* Fall */
385 return -EINVAL; 395 case WDIOC_GETTIMEOUT:
386 396 return put_user(heartbeat, p);
387 wdt_ping();
388 /* Fall */
389 case WDIOC_GETTIMEOUT:
390 return put_user(heartbeat, p);
391 } 397 }
392} 398}
393 399
@@ -405,7 +411,7 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
405 411
406static int wdt_open(struct inode *inode, struct file *file) 412static int wdt_open(struct inode *inode, struct file *file)
407{ 413{
408 if(test_and_set_bit(0, &wdt_is_open)) 414 if (test_and_set_bit(0, &wdt_is_open))
409 return -EBUSY; 415 return -EBUSY;
410 /* 416 /*
411 * Activate 417 * Activate
@@ -432,7 +438,8 @@ static int wdt_release(struct inode *inode, struct file *file)
432 wdt_stop(); 438 wdt_stop();
433 clear_bit(0, &wdt_is_open); 439 clear_bit(0, &wdt_is_open);
434 } else { 440 } else {
435 printk(KERN_CRIT "wdt: WDT device closed unexpectedly. WDT will not stop!\n"); 441 printk(KERN_CRIT
442 "wdt: WDT device closed unexpectedly. WDT will not stop!\n");
436 wdt_ping(); 443 wdt_ping();
437 } 444 }
438 expect_close = 0; 445 expect_close = 0;
@@ -451,14 +458,15 @@ static int wdt_release(struct inode *inode, struct file *file)
451 * farenheit. It was designed by an imperial measurement luddite. 458 * farenheit. It was designed by an imperial measurement luddite.
452 */ 459 */
453 460
454static ssize_t wdt_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) 461static ssize_t wdt_temp_read(struct file *file, char __user *buf,
462 size_t count, loff_t *ptr)
455{ 463{
456 int temperature; 464 int temperature;
457 465
458 if (wdt_get_temperature(&temperature)) 466 if (wdt_get_temperature(&temperature))
459 return -EFAULT; 467 return -EFAULT;
460 468
461 if (copy_to_user (buf, &temperature, 1)) 469 if (copy_to_user(buf, &temperature, 1))
462 return -EFAULT; 470 return -EFAULT;
463 471
464 return 1; 472 return 1;
@@ -506,10 +514,8 @@ static int wdt_temp_release(struct inode *inode, struct file *file)
506static int wdt_notify_sys(struct notifier_block *this, unsigned long code, 514static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
507 void *unused) 515 void *unused)
508{ 516{
509 if(code==SYS_DOWN || code==SYS_HALT) { 517 if (code == SYS_DOWN || code == SYS_HALT)
510 /* Turn the card off */
511 wdt_stop(); 518 wdt_stop();
512 }
513 return NOTIFY_DONE; 519 return NOTIFY_DONE;
514} 520}
515 521
@@ -522,7 +528,7 @@ static const struct file_operations wdt_fops = {
522 .owner = THIS_MODULE, 528 .owner = THIS_MODULE,
523 .llseek = no_llseek, 529 .llseek = no_llseek,
524 .write = wdt_write, 530 .write = wdt_write,
525 .ioctl = wdt_ioctl, 531 .unlocked_ioctl = wdt_ioctl,
526 .open = wdt_open, 532 .open = wdt_open,
527 .release = wdt_release, 533 .release = wdt_release,
528}; 534};
@@ -576,7 +582,7 @@ static void __exit wdt_exit(void)
576#endif /* CONFIG_WDT_501 */ 582#endif /* CONFIG_WDT_501 */
577 unregister_reboot_notifier(&wdt_notifier); 583 unregister_reboot_notifier(&wdt_notifier);
578 free_irq(irq, NULL); 584 free_irq(irq, NULL);
579 release_region(io,8); 585 release_region(io, 8);
580} 586}
581 587
582/** 588/**
@@ -591,44 +597,49 @@ static int __init wdt_init(void)
591{ 597{
592 int ret; 598 int ret;
593 599
594 /* Check that the heartbeat value is within it's range ; if not reset to the default */ 600 /* Check that the heartbeat value is within it's range;
601 if not reset to the default */
595 if (wdt_set_heartbeat(heartbeat)) { 602 if (wdt_set_heartbeat(heartbeat)) {
596 wdt_set_heartbeat(WD_TIMO); 603 wdt_set_heartbeat(WD_TIMO);
597 printk(KERN_INFO "wdt: heartbeat value must be 0<heartbeat<65536, using %d\n", 604 printk(KERN_INFO "wdt: heartbeat value must be 0 < heartbeat < 65536, using %d\n",
598 WD_TIMO); 605 WD_TIMO);
599 } 606 }
600 607
601 if (!request_region(io, 8, "wdt501p")) { 608 if (!request_region(io, 8, "wdt501p")) {
602 printk(KERN_ERR "wdt: I/O address 0x%04x already in use\n", io); 609 printk(KERN_ERR
610 "wdt: I/O address 0x%04x already in use\n", io);
603 ret = -EBUSY; 611 ret = -EBUSY;
604 goto out; 612 goto out;
605 } 613 }
606 614
607 ret = request_irq(irq, wdt_interrupt, IRQF_DISABLED, "wdt501p", NULL); 615 ret = request_irq(irq, wdt_interrupt, IRQF_DISABLED, "wdt501p", NULL);
608 if(ret) { 616 if (ret) {
609 printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq); 617 printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq);
610 goto outreg; 618 goto outreg;
611 } 619 }
612 620
613 ret = register_reboot_notifier(&wdt_notifier); 621 ret = register_reboot_notifier(&wdt_notifier);
614 if(ret) { 622 if (ret) {
615 printk(KERN_ERR "wdt: cannot register reboot notifier (err=%d)\n", ret); 623 printk(KERN_ERR
624 "wdt: cannot register reboot notifier (err=%d)\n", ret);
616 goto outirq; 625 goto outirq;
617 } 626 }
618 627
619#ifdef CONFIG_WDT_501 628#ifdef CONFIG_WDT_501
620 ret = misc_register(&temp_miscdev); 629 ret = misc_register(&temp_miscdev);
621 if (ret) { 630 if (ret) {
622 printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n", 631 printk(KERN_ERR
623 TEMP_MINOR, ret); 632 "wdt: cannot register miscdev on minor=%d (err=%d)\n",
633 TEMP_MINOR, ret);
624 goto outrbt; 634 goto outrbt;
625 } 635 }
626#endif /* CONFIG_WDT_501 */ 636#endif /* CONFIG_WDT_501 */
627 637
628 ret = misc_register(&wdt_miscdev); 638 ret = misc_register(&wdt_miscdev);
629 if (ret) { 639 if (ret) {
630 printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n", 640 printk(KERN_ERR
631 WATCHDOG_MINOR, ret); 641 "wdt: cannot register miscdev on minor=%d (err=%d)\n",
642 WATCHDOG_MINOR, ret);
632 goto outmisc; 643 goto outmisc;
633 } 644 }
634 645
@@ -636,7 +647,8 @@ static int __init wdt_init(void)
636 printk(KERN_INFO "WDT500/501-P driver 0.10 at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n", 647 printk(KERN_INFO "WDT500/501-P driver 0.10 at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n",
637 io, irq, heartbeat, nowayout); 648 io, irq, heartbeat, nowayout);
638#ifdef CONFIG_WDT_501 649#ifdef CONFIG_WDT_501
639 printk(KERN_INFO "wdt: Fan Tachometer is %s\n", (tachometer ? "Enabled" : "Disabled")); 650 printk(KERN_INFO "wdt: Fan Tachometer is %s\n",
651 (tachometer ? "Enabled" : "Disabled"));
640#endif /* CONFIG_WDT_501 */ 652#endif /* CONFIG_WDT_501 */
641 653
642out: 654out:
@@ -651,7 +663,7 @@ outrbt:
651outirq: 663outirq:
652 free_irq(irq, NULL); 664 free_irq(irq, NULL);
653outreg: 665outreg:
654 release_region(io,8); 666 release_region(io, 8);
655 goto out; 667 goto out;
656} 668}
657 669
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index 1355608683e4..5d922fd6eafc 100644
--- a/drivers/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -29,9 +29,11 @@
29 * JP Nollmann : Added support for PCI wdt501p 29 * JP Nollmann : Added support for PCI wdt501p
30 * Alan Cox : Split ISA and PCI cards into two drivers 30 * Alan Cox : Split ISA and PCI cards into two drivers
31 * Jeff Garzik : PCI cleanups 31 * Jeff Garzik : PCI cleanups
32 * Tigran Aivazian : Restructured wdtpci_init_one() to handle failures 32 * Tigran Aivazian : Restructured wdtpci_init_one() to handle
33 * failures
33 * Joel Becker : Added WDIOC_GET/SETTIMEOUT 34 * Joel Becker : Added WDIOC_GET/SETTIMEOUT
34 * Zwane Mwaikambo : Magic char closing, locking changes, cleanups 35 * Zwane Mwaikambo : Magic char closing, locking changes,
36 * cleanups
35 * Matt Domsch : nowayout module option 37 * Matt Domsch : nowayout module option
36 */ 38 */
37 39
@@ -42,14 +44,15 @@
42#include <linux/miscdevice.h> 44#include <linux/miscdevice.h>
43#include <linux/watchdog.h> 45#include <linux/watchdog.h>
44#include <linux/ioport.h> 46#include <linux/ioport.h>
47#include <linux/delay.h>
45#include <linux/notifier.h> 48#include <linux/notifier.h>
46#include <linux/reboot.h> 49#include <linux/reboot.h>
47#include <linux/init.h> 50#include <linux/init.h>
48#include <linux/fs.h> 51#include <linux/fs.h>
49#include <linux/pci.h> 52#include <linux/pci.h>
53#include <linux/io.h>
54#include <linux/uaccess.h>
50 55
51#include <asm/io.h>
52#include <asm/uaccess.h>
53#include <asm/system.h> 56#include <asm/system.h>
54 57
55#define WDT_IS_PCI 58#define WDT_IS_PCI
@@ -73,7 +76,7 @@
73/* We can only use 1 card due to the /dev/watchdog restriction */ 76/* We can only use 1 card due to the /dev/watchdog restriction */
74static int dev_count; 77static int dev_count;
75 78
76static struct semaphore open_sem; 79static unsigned long open_lock;
77static DEFINE_SPINLOCK(wdtpci_lock); 80static DEFINE_SPINLOCK(wdtpci_lock);
78static char expect_close; 81static char expect_close;
79 82
@@ -86,18 +89,23 @@ static int irq;
86static int heartbeat = WD_TIMO; 89static int heartbeat = WD_TIMO;
87static int wd_heartbeat; 90static int wd_heartbeat;
88module_param(heartbeat, int, 0); 91module_param(heartbeat, int, 0);
89MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); 92MODULE_PARM_DESC(heartbeat,
93 "Watchdog heartbeat in seconds. (0<heartbeat<65536, default="
94 __MODULE_STRING(WD_TIMO) ")");
90 95
91static int nowayout = WATCHDOG_NOWAYOUT; 96static int nowayout = WATCHDOG_NOWAYOUT;
92module_param(nowayout, int, 0); 97module_param(nowayout, int, 0);
93MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 98MODULE_PARM_DESC(nowayout,
99 "Watchdog cannot be stopped once started (default="
100 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
94 101
95#ifdef CONFIG_WDT_501_PCI 102#ifdef CONFIG_WDT_501_PCI
96/* Support for the Fan Tachometer on the PCI-WDT501 */ 103/* Support for the Fan Tachometer on the PCI-WDT501 */
97static int tachometer; 104static int tachometer;
98 105
99module_param(tachometer, int, 0); 106module_param(tachometer, int, 0);
100MODULE_PARM_DESC(tachometer, "PCI-WDT501 Fan Tachometer support (0=disable, default=0)"); 107MODULE_PARM_DESC(tachometer,
108 "PCI-WDT501 Fan Tachometer support (0=disable, default=0)");
101#endif /* CONFIG_WDT_501_PCI */ 109#endif /* CONFIG_WDT_501_PCI */
102 110
103/* 111/*
@@ -106,16 +114,19 @@ MODULE_PARM_DESC(tachometer, "PCI-WDT501 Fan Tachometer support (0=disable, defa
106 114
107static void wdtpci_ctr_mode(int ctr, int mode) 115static void wdtpci_ctr_mode(int ctr, int mode)
108{ 116{
109 ctr<<=6; 117 ctr <<= 6;
110 ctr|=0x30; 118 ctr |= 0x30;
111 ctr|=(mode<<1); 119 ctr |= (mode << 1);
112 outb_p(ctr, WDT_CR); 120 outb(ctr, WDT_CR);
121 udelay(8);
113} 122}
114 123
115static void wdtpci_ctr_load(int ctr, int val) 124static void wdtpci_ctr_load(int ctr, int val)
116{ 125{
117 outb_p(val&0xFF, WDT_COUNT0+ctr); 126 outb(val & 0xFF, WDT_COUNT0 + ctr);
118 outb_p(val>>8, WDT_COUNT0+ctr); 127 udelay(8);
128 outb(val >> 8, WDT_COUNT0 + ctr);
129 udelay(8);
119} 130}
120 131
121/** 132/**
@@ -134,23 +145,35 @@ static int wdtpci_start(void)
134 * "pet" the watchdog, as Access says. 145 * "pet" the watchdog, as Access says.
135 * This resets the clock outputs. 146 * This resets the clock outputs.
136 */ 147 */
137 inb_p(WDT_DC); /* Disable watchdog */ 148 inb(WDT_DC); /* Disable watchdog */
138 wdtpci_ctr_mode(2,0); /* Program CTR2 for Mode 0: Pulse on Terminal Count */ 149 udelay(8);
139 outb_p(0, WDT_DC); /* Enable watchdog */ 150 wdtpci_ctr_mode(2, 0); /* Program CTR2 for Mode 0:
140 151 Pulse on Terminal Count */
141 inb_p(WDT_DC); /* Disable watchdog */ 152 outb(0, WDT_DC); /* Enable watchdog */
142 outb_p(0, WDT_CLOCK); /* 2.0833MHz clock */ 153 udelay(8);
143 inb_p(WDT_BUZZER); /* disable */ 154 inb(WDT_DC); /* Disable watchdog */
144 inb_p(WDT_OPTONOTRST); /* disable */ 155 udelay(8);
145 inb_p(WDT_OPTORST); /* disable */ 156 outb(0, WDT_CLOCK); /* 2.0833MHz clock */
146 inb_p(WDT_PROGOUT); /* disable */ 157 udelay(8);
147 wdtpci_ctr_mode(0,3); /* Program CTR0 for Mode 3: Square Wave Generator */ 158 inb(WDT_BUZZER); /* disable */
148 wdtpci_ctr_mode(1,2); /* Program CTR1 for Mode 2: Rate Generator */ 159 udelay(8);
149 wdtpci_ctr_mode(2,1); /* Program CTR2 for Mode 1: Retriggerable One-Shot */ 160 inb(WDT_OPTONOTRST); /* disable */
150 wdtpci_ctr_load(0,20833); /* count at 100Hz */ 161 udelay(8);
151 wdtpci_ctr_load(1,wd_heartbeat);/* Heartbeat */ 162 inb(WDT_OPTORST); /* disable */
163 udelay(8);
164 inb(WDT_PROGOUT); /* disable */
165 udelay(8);
166 wdtpci_ctr_mode(0, 3); /* Program CTR0 for Mode 3:
167 Square Wave Generator */
168 wdtpci_ctr_mode(1, 2); /* Program CTR1 for Mode 2:
169 Rate Generator */
170 wdtpci_ctr_mode(2, 1); /* Program CTR2 for Mode 1:
171 Retriggerable One-Shot */
172 wdtpci_ctr_load(0, 20833); /* count at 100Hz */
173 wdtpci_ctr_load(1, wd_heartbeat);/* Heartbeat */
152 /* DO NOT LOAD CTR2 on PCI card! -- JPN */ 174 /* DO NOT LOAD CTR2 on PCI card! -- JPN */
153 outb_p(0, WDT_DC); /* Enable watchdog */ 175 outb(0, WDT_DC); /* Enable watchdog */
176 udelay(8);
154 177
155 spin_unlock_irqrestore(&wdtpci_lock, flags); 178 spin_unlock_irqrestore(&wdtpci_lock, flags);
156 return 0; 179 return 0;
@@ -162,14 +185,15 @@ static int wdtpci_start(void)
162 * Stop the watchdog driver. 185 * Stop the watchdog driver.
163 */ 186 */
164 187
165static int wdtpci_stop (void) 188static int wdtpci_stop(void)
166{ 189{
167 unsigned long flags; 190 unsigned long flags;
168 191
169 /* Turn the card off */ 192 /* Turn the card off */
170 spin_lock_irqsave(&wdtpci_lock, flags); 193 spin_lock_irqsave(&wdtpci_lock, flags);
171 inb_p(WDT_DC); /* Disable watchdog */ 194 inb(WDT_DC); /* Disable watchdog */
172 wdtpci_ctr_load(2,0); /* 0 length reset pulses now */ 195 udelay(8);
196 wdtpci_ctr_load(2, 0); /* 0 length reset pulses now */
173 spin_unlock_irqrestore(&wdtpci_lock, flags); 197 spin_unlock_irqrestore(&wdtpci_lock, flags);
174 return 0; 198 return 0;
175} 199}
@@ -177,20 +201,23 @@ static int wdtpci_stop (void)
177/** 201/**
178 * wdtpci_ping: 202 * wdtpci_ping:
179 * 203 *
180 * Reload counter one with the watchdog heartbeat. We don't bother reloading 204 * Reload counter one with the watchdog heartbeat. We don't bother
181 * the cascade counter. 205 * reloading the cascade counter.
182 */ 206 */
183 207
184static int wdtpci_ping(void) 208static int wdtpci_ping(void)
185{ 209{
186 unsigned long flags; 210 unsigned long flags;
187 211
188 /* Write a watchdog value */
189 spin_lock_irqsave(&wdtpci_lock, flags); 212 spin_lock_irqsave(&wdtpci_lock, flags);
190 inb_p(WDT_DC); /* Disable watchdog */ 213 /* Write a watchdog value */
191 wdtpci_ctr_mode(1,2); /* Re-Program CTR1 for Mode 2: Rate Generator */ 214 inb(WDT_DC); /* Disable watchdog */
192 wdtpci_ctr_load(1,wd_heartbeat);/* Heartbeat */ 215 udelay(8);
193 outb_p(0, WDT_DC); /* Enable watchdog */ 216 wdtpci_ctr_mode(1, 2); /* Re-Program CTR1 for Mode 2:
217 Rate Generator */
218 wdtpci_ctr_load(1, wd_heartbeat);/* Heartbeat */
219 outb(0, WDT_DC); /* Enable watchdog */
220 udelay(8);
194 spin_unlock_irqrestore(&wdtpci_lock, flags); 221 spin_unlock_irqrestore(&wdtpci_lock, flags);
195 return 0; 222 return 0;
196} 223}
@@ -199,14 +226,14 @@ static int wdtpci_ping(void)
199 * wdtpci_set_heartbeat: 226 * wdtpci_set_heartbeat:
200 * @t: the new heartbeat value that needs to be set. 227 * @t: the new heartbeat value that needs to be set.
201 * 228 *
202 * Set a new heartbeat value for the watchdog device. If the heartbeat value is 229 * Set a new heartbeat value for the watchdog device. If the heartbeat
203 * incorrect we keep the old value and return -EINVAL. If successfull we 230 * value is incorrect we keep the old value and return -EINVAL.
204 * return 0. 231 * If successful we return 0.
205 */ 232 */
206static int wdtpci_set_heartbeat(int t) 233static int wdtpci_set_heartbeat(int t)
207{ 234{
208 /* Arbitrary, can't find the card's limits */ 235 /* Arbitrary, can't find the card's limits */
209 if ((t < 1) || (t > 65535)) 236 if (t < 1 || t > 65535)
210 return -EINVAL; 237 return -EINVAL;
211 238
212 heartbeat = t; 239 heartbeat = t;
@@ -227,9 +254,14 @@ static int wdtpci_set_heartbeat(int t)
227 254
228static int wdtpci_get_status(int *status) 255static int wdtpci_get_status(int *status)
229{ 256{
230 unsigned char new_status=inb_p(WDT_SR); 257 unsigned char new_status;
258 unsigned long flags;
259
260 spin_lock_irqsave(&wdtpci_lock, flags);
261 new_status = inb(WDT_SR);
262 spin_unlock_irqrestore(&wdtpci_lock, flags);
231 263
232 *status=0; 264 *status = 0;
233 if (new_status & WDC_SR_ISOI0) 265 if (new_status & WDC_SR_ISOI0)
234 *status |= WDIOF_EXTERN1; 266 *status |= WDIOF_EXTERN1;
235 if (new_status & WDC_SR_ISII1) 267 if (new_status & WDC_SR_ISII1)
@@ -259,8 +291,12 @@ static int wdtpci_get_status(int *status)
259 291
260static int wdtpci_get_temperature(int *temperature) 292static int wdtpci_get_temperature(int *temperature)
261{ 293{
262 unsigned short c=inb_p(WDT_RT); 294 unsigned short c;
263 295 unsigned long flags;
296 spin_lock_irqsave(&wdtpci_lock, flags);
297 c = inb(WDT_RT);
298 udelay(8);
299 spin_unlock_irqrestore(&wdtpci_lock, flags);
264 *temperature = (c * 11 / 15) + 7; 300 *temperature = (c * 11 / 15) + 7;
265 return 0; 301 return 0;
266} 302}
@@ -282,17 +318,25 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
282 * Read the status register see what is up and 318 * Read the status register see what is up and
283 * then printk it. 319 * then printk it.
284 */ 320 */
285 unsigned char status=inb_p(WDT_SR); 321 unsigned char status;
322
323 spin_lock(&wdtpci_lock);
324
325 status = inb(WDT_SR);
326 udelay(8);
286 327
287 printk(KERN_CRIT PFX "status %d\n", status); 328 printk(KERN_CRIT PFX "status %d\n", status);
288 329
289#ifdef CONFIG_WDT_501_PCI 330#ifdef CONFIG_WDT_501_PCI
290 if (!(status & WDC_SR_TGOOD)) 331 if (!(status & WDC_SR_TGOOD)) {
291 printk(KERN_CRIT PFX "Overheat alarm.(%d)\n",inb_p(WDT_RT)); 332 u8 alarm = inb(WDT_RT);
333 printk(KERN_CRIT PFX "Overheat alarm.(%d)\n", alarm);
334 udelay(8);
335 }
292 if (!(status & WDC_SR_PSUOVER)) 336 if (!(status & WDC_SR_PSUOVER))
293 printk(KERN_CRIT PFX "PSU over voltage.\n"); 337 printk(KERN_CRIT PFX "PSU over voltage.\n");
294 if (!(status & WDC_SR_PSUUNDR)) 338 if (!(status & WDC_SR_PSUUNDR))
295 printk(KERN_CRIT PFX "PSU under voltage.\n"); 339 printk(KERN_CRIT PFX "PSU under voltage.\n");
296 if (tachometer) { 340 if (tachometer) {
297 if (!(status & WDC_SR_FANGOOD)) 341 if (!(status & WDC_SR_FANGOOD))
298 printk(KERN_CRIT PFX "Possible fan fault.\n"); 342 printk(KERN_CRIT PFX "Possible fan fault.\n");
@@ -310,6 +354,7 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
310 printk(KERN_CRIT PFX "Reset in 5ms.\n"); 354 printk(KERN_CRIT PFX "Reset in 5ms.\n");
311#endif 355#endif
312 } 356 }
357 spin_unlock(&wdtpci_lock);
313 return IRQ_HANDLED; 358 return IRQ_HANDLED;
314} 359}
315 360
@@ -325,7 +370,8 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
325 * write of data will do, as we we don't define content meaning. 370 * write of data will do, as we we don't define content meaning.
326 */ 371 */
327 372
328static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 373static ssize_t wdtpci_write(struct file *file, const char __user *buf,
374 size_t count, loff_t *ppos)
329{ 375{
330 if (count) { 376 if (count) {
331 if (!nowayout) { 377 if (!nowayout) {
@@ -335,7 +381,7 @@ static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t co
335 381
336 for (i = 0; i != count; i++) { 382 for (i = 0; i != count; i++) {
337 char c; 383 char c;
338 if(get_user(c, buf+i)) 384 if (get_user(c, buf+i))
339 return -EFAULT; 385 return -EFAULT;
340 if (c == 'V') 386 if (c == 'V')
341 expect_close = 42; 387 expect_close = 42;
@@ -343,13 +389,11 @@ static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t co
343 } 389 }
344 wdtpci_ping(); 390 wdtpci_ping();
345 } 391 }
346
347 return count; 392 return count;
348} 393}
349 394
350/** 395/**
351 * wdtpci_ioctl: 396 * wdtpci_ioctl:
352 * @inode: inode of the device
353 * @file: file handle to the device 397 * @file: file handle to the device
354 * @cmd: watchdog command 398 * @cmd: watchdog command
355 * @arg: argument pointer 399 * @arg: argument pointer
@@ -359,8 +403,8 @@ static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t co
359 * querying capabilities and current status. 403 * querying capabilities and current status.
360 */ 404 */
361 405
362static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 406static long wdtpci_ioctl(struct file *file, unsigned int cmd,
363 unsigned long arg) 407 unsigned long arg)
364{ 408{
365 int new_heartbeat; 409 int new_heartbeat;
366 int status; 410 int status;
@@ -383,33 +427,29 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd
383 ident.options |= WDIOF_FANFAULT; 427 ident.options |= WDIOF_FANFAULT;
384#endif /* CONFIG_WDT_501_PCI */ 428#endif /* CONFIG_WDT_501_PCI */
385 429
386 switch(cmd) 430 switch (cmd) {
387 { 431 default:
388 default: 432 return -ENOTTY;
389 return -ENOTTY; 433 case WDIOC_GETSUPPORT:
390 case WDIOC_GETSUPPORT: 434 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
391 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; 435 case WDIOC_GETSTATUS:
392 436 wdtpci_get_status(&status);
393 case WDIOC_GETSTATUS: 437 return put_user(status, p);
394 wdtpci_get_status(&status); 438 case WDIOC_GETBOOTSTATUS:
395 return put_user(status, p); 439 return put_user(0, p);
396 case WDIOC_GETBOOTSTATUS: 440 case WDIOC_KEEPALIVE:
397 return put_user(0, p); 441 wdtpci_ping();
398 case WDIOC_KEEPALIVE: 442 return 0;
399 wdtpci_ping(); 443 case WDIOC_SETTIMEOUT:
400 return 0; 444 if (get_user(new_heartbeat, p))
401 case WDIOC_SETTIMEOUT: 445 return -EFAULT;
402 if (get_user(new_heartbeat, p)) 446 if (wdtpci_set_heartbeat(new_heartbeat))
403 return -EFAULT; 447 return -EINVAL;
404 448 wdtpci_ping();
405 if (wdtpci_set_heartbeat(new_heartbeat)) 449 /* Fall */
406 return -EINVAL; 450 case WDIOC_GETTIMEOUT:
407 451 return put_user(heartbeat, p);
408 wdtpci_ping(); 452 }
409 /* Fall */
410 case WDIOC_GETTIMEOUT:
411 return put_user(heartbeat, p);
412 }
413} 453}
414 454
415/** 455/**
@@ -426,12 +466,11 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd
426 466
427static int wdtpci_open(struct inode *inode, struct file *file) 467static int wdtpci_open(struct inode *inode, struct file *file)
428{ 468{
429 if (down_trylock(&open_sem)) 469 if (test_and_set_bit(0, &open_lock))
430 return -EBUSY; 470 return -EBUSY;
431 471
432 if (nowayout) { 472 if (nowayout)
433 __module_get(THIS_MODULE); 473 __module_get(THIS_MODULE);
434 }
435 /* 474 /*
436 * Activate 475 * Activate
437 */ 476 */
@@ -460,7 +499,7 @@ static int wdtpci_release(struct inode *inode, struct file *file)
460 wdtpci_ping(); 499 wdtpci_ping();
461 } 500 }
462 expect_close = 0; 501 expect_close = 0;
463 up(&open_sem); 502 clear_bit(0, &open_lock);
464 return 0; 503 return 0;
465} 504}
466 505
@@ -476,14 +515,15 @@ static int wdtpci_release(struct inode *inode, struct file *file)
476 * fahrenheit. It was designed by an imperial measurement luddite. 515 * fahrenheit. It was designed by an imperial measurement luddite.
477 */ 516 */
478 517
479static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) 518static ssize_t wdtpci_temp_read(struct file *file, char __user *buf,
519 size_t count, loff_t *ptr)
480{ 520{
481 int temperature; 521 int temperature;
482 522
483 if (wdtpci_get_temperature(&temperature)) 523 if (wdtpci_get_temperature(&temperature))
484 return -EFAULT; 524 return -EFAULT;
485 525
486 if (copy_to_user (buf, &temperature, 1)) 526 if (copy_to_user(buf, &temperature, 1))
487 return -EFAULT; 527 return -EFAULT;
488 528
489 return 1; 529 return 1;
@@ -529,12 +569,10 @@ static int wdtpci_temp_release(struct inode *inode, struct file *file)
529 */ 569 */
530 570
531static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, 571static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
532 void *unused) 572 void *unused)
533{ 573{
534 if (code==SYS_DOWN || code==SYS_HALT) { 574 if (code == SYS_DOWN || code == SYS_HALT)
535 /* Turn the card off */
536 wdtpci_stop(); 575 wdtpci_stop();
537 }
538 return NOTIFY_DONE; 576 return NOTIFY_DONE;
539} 577}
540 578
@@ -547,7 +585,7 @@ static const struct file_operations wdtpci_fops = {
547 .owner = THIS_MODULE, 585 .owner = THIS_MODULE,
548 .llseek = no_llseek, 586 .llseek = no_llseek,
549 .write = wdtpci_write, 587 .write = wdtpci_write,
550 .ioctl = wdtpci_ioctl, 588 .unlocked_ioctl = wdtpci_ioctl,
551 .open = wdtpci_open, 589 .open = wdtpci_open,
552 .release = wdtpci_release, 590 .release = wdtpci_release,
553}; 591};
@@ -584,80 +622,85 @@ static struct notifier_block wdtpci_notifier = {
584}; 622};
585 623
586 624
587static int __devinit wdtpci_init_one (struct pci_dev *dev, 625static int __devinit wdtpci_init_one(struct pci_dev *dev,
588 const struct pci_device_id *ent) 626 const struct pci_device_id *ent)
589{ 627{
590 int ret = -EIO; 628 int ret = -EIO;
591 629
592 dev_count++; 630 dev_count++;
593 if (dev_count > 1) { 631 if (dev_count > 1) {
594 printk (KERN_ERR PFX "this driver only supports 1 device\n"); 632 printk(KERN_ERR PFX "This driver only supports one device\n");
595 return -ENODEV; 633 return -ENODEV;
596 } 634 }
597 635
598 if (pci_enable_device (dev)) { 636 if (pci_enable_device(dev)) {
599 printk (KERN_ERR PFX "Not possible to enable PCI Device\n"); 637 printk(KERN_ERR PFX "Not possible to enable PCI Device\n");
600 return -ENODEV; 638 return -ENODEV;
601 } 639 }
602 640
603 if (pci_resource_start (dev, 2) == 0x0000) { 641 if (pci_resource_start(dev, 2) == 0x0000) {
604 printk (KERN_ERR PFX "No I/O-Address for card detected\n"); 642 printk(KERN_ERR PFX "No I/O-Address for card detected\n");
605 ret = -ENODEV; 643 ret = -ENODEV;
606 goto out_pci; 644 goto out_pci;
607 } 645 }
608 646
609 sema_init(&open_sem, 1);
610
611 irq = dev->irq; 647 irq = dev->irq;
612 io = pci_resource_start (dev, 2); 648 io = pci_resource_start(dev, 2);
613 649
614 if (request_region (io, 16, "wdt_pci") == NULL) { 650 if (request_region(io, 16, "wdt_pci") == NULL) {
615 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", io); 651 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", io);
616 goto out_pci; 652 goto out_pci;
617 } 653 }
618 654
619 if (request_irq (irq, wdtpci_interrupt, IRQF_DISABLED | IRQF_SHARED, 655 if (request_irq(irq, wdtpci_interrupt, IRQF_DISABLED | IRQF_SHARED,
620 "wdt_pci", &wdtpci_miscdev)) { 656 "wdt_pci", &wdtpci_miscdev)) {
621 printk (KERN_ERR PFX "IRQ %d is not free\n", irq); 657 printk(KERN_ERR PFX "IRQ %d is not free\n", irq);
622 goto out_reg; 658 goto out_reg;
623 } 659 }
624 660
625 printk ("PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%04x (Interrupt %d)\n", 661 printk(KERN_INFO
626 io, irq); 662 "PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%04x (Interrupt %d)\n",
663 io, irq);
627 664
628 /* Check that the heartbeat value is within it's range ; if not reset to the default */ 665 /* Check that the heartbeat value is within its range;
666 if not reset to the default */
629 if (wdtpci_set_heartbeat(heartbeat)) { 667 if (wdtpci_set_heartbeat(heartbeat)) {
630 wdtpci_set_heartbeat(WD_TIMO); 668 wdtpci_set_heartbeat(WD_TIMO);
631 printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n", 669 printk(KERN_INFO PFX
632 WD_TIMO); 670 "heartbeat value must be 0 < heartbeat < 65536, using %d\n",
671 WD_TIMO);
633 } 672 }
634 673
635 ret = register_reboot_notifier (&wdtpci_notifier); 674 ret = register_reboot_notifier(&wdtpci_notifier);
636 if (ret) { 675 if (ret) {
637 printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); 676 printk(KERN_ERR PFX
677 "cannot register reboot notifier (err=%d)\n", ret);
638 goto out_irq; 678 goto out_irq;
639 } 679 }
640 680
641#ifdef CONFIG_WDT_501_PCI 681#ifdef CONFIG_WDT_501_PCI
642 ret = misc_register (&temp_miscdev); 682 ret = misc_register(&temp_miscdev);
643 if (ret) { 683 if (ret) {
644 printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 684 printk(KERN_ERR PFX
645 TEMP_MINOR, ret); 685 "cannot register miscdev on minor=%d (err=%d)\n",
686 TEMP_MINOR, ret);
646 goto out_rbt; 687 goto out_rbt;
647 } 688 }
648#endif /* CONFIG_WDT_501_PCI */ 689#endif /* CONFIG_WDT_501_PCI */
649 690
650 ret = misc_register (&wdtpci_miscdev); 691 ret = misc_register(&wdtpci_miscdev);
651 if (ret) { 692 if (ret) {
652 printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 693 printk(KERN_ERR PFX
653 WATCHDOG_MINOR, ret); 694 "cannot register miscdev on minor=%d (err=%d)\n",
695 WATCHDOG_MINOR, ret);
654 goto out_misc; 696 goto out_misc;
655 } 697 }
656 698
657 printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", 699 printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
658 heartbeat, nowayout); 700 heartbeat, nowayout);
659#ifdef CONFIG_WDT_501_PCI 701#ifdef CONFIG_WDT_501_PCI
660 printk(KERN_INFO "wdt: Fan Tachometer is %s\n", (tachometer ? "Enabled" : "Disabled")); 702 printk(KERN_INFO "wdt: Fan Tachometer is %s\n",
703 (tachometer ? "Enabled" : "Disabled"));
661#endif /* CONFIG_WDT_501_PCI */ 704#endif /* CONFIG_WDT_501_PCI */
662 705
663 ret = 0; 706 ret = 0;
@@ -673,14 +716,14 @@ out_rbt:
673out_irq: 716out_irq:
674 free_irq(irq, &wdtpci_miscdev); 717 free_irq(irq, &wdtpci_miscdev);
675out_reg: 718out_reg:
676 release_region (io, 16); 719 release_region(io, 16);
677out_pci: 720out_pci:
678 pci_disable_device(dev); 721 pci_disable_device(dev);
679 goto out; 722 goto out;
680} 723}
681 724
682 725
683static void __devexit wdtpci_remove_one (struct pci_dev *pdev) 726static void __devexit wdtpci_remove_one(struct pci_dev *pdev)
684{ 727{
685 /* here we assume only one device will ever have 728 /* here we assume only one device will ever have
686 * been picked up and registered by probe function */ 729 * been picked up and registered by probe function */
@@ -728,7 +771,7 @@ static struct pci_driver wdtpci_driver = {
728 771
729static void __exit wdtpci_cleanup(void) 772static void __exit wdtpci_cleanup(void)
730{ 773{
731 pci_unregister_driver (&wdtpci_driver); 774 pci_unregister_driver(&wdtpci_driver);
732} 775}
733 776
734 777
@@ -742,7 +785,7 @@ static void __exit wdtpci_cleanup(void)
742 785
743static int __init wdtpci_init(void) 786static int __init wdtpci_init(void)
744{ 787{
745 return pci_register_driver (&wdtpci_driver); 788 return pci_register_driver(&wdtpci_driver);
746} 789}
747 790
748 791