diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-08-07 04:55:03 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-08-07 04:55:03 -0400 |
commit | 4fb8af10d0fd09372d52966b76922b9e82bbc950 (patch) | |
tree | d240e4d40357583e3f3eb228dccf20122a5b31ed /drivers/watchdog | |
parent | f44f82e8a20b98558486eb14497b2f71c78fa325 (diff) | |
parent | 64a99d2a8c3ed5c4e39f3ae1cc682aa8fd3977fc (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.c | 29 | ||||
-rw-r--r-- | drivers/watchdog/hpwdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/it8712f_wdt.c | 77 | ||||
-rw-r--r-- | drivers/watchdog/s3c2410_wdt.c | 148 | ||||
-rw-r--r-- | drivers/watchdog/sc1200wdt.c | 205 | ||||
-rw-r--r-- | drivers/watchdog/wdt.c | 176 | ||||
-rw-r--r-- | drivers/watchdog/wdt_pci.c | 301 |
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 | ||
72 | static struct semaphore open_semaphore; | 72 | static unsigned long wdt_is_open; |
73 | static spinlock_t wdt_lock; | ||
73 | static unsigned expect_close; | 74 | static 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) | |||
179 | static int ar7_wdt_open(struct inode *inode, struct file *file) | 182 | static 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 | ||
240 | static int ar7_wdt_ioctl(struct inode *inode, struct file *file, | 243 | static 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, | |||
282 | static const struct file_operations ar7_wdt_fops = { | 287 | static 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) | |||
420 | static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, | 420 | static 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; | |||
50 | module_param(nowayout, int, 0); | 49 | module_param(nowayout, int, 0); |
51 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); | 50 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); |
52 | 51 | ||
53 | static struct semaphore it8712f_wdt_sem; | 52 | static unsigned long wdt_open; |
54 | static unsigned expect_close; | 53 | static unsigned expect_close; |
55 | static spinlock_t io_lock; | 54 | static spinlock_t io_lock; |
56 | static unsigned char revision; | 55 | static 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 | ||
89 | static int | 88 | static int superio_inb(int reg) |
90 | superio_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 | ||
96 | static void | 94 | static void superio_outb(int val, int reg) |
97 | superio_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 | ||
103 | static int | 100 | static int superio_inw(int reg) |
104 | superio_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 | ||
114 | static inline void | 110 | static inline void superio_select(int ldn) |
115 | superio_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 | ||
121 | static inline void | 116 | static inline void superio_enter(void) |
122 | superio_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 | ||
131 | static inline void | 125 | static inline void superio_exit(void) |
132 | superio_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 | ||
139 | static inline void | 132 | static inline void it8712f_wdt_ping(void) |
140 | it8712f_wdt_ping(void) | ||
141 | { | 133 | { |
142 | inb(address); | 134 | inb(address); |
143 | } | 135 | } |
144 | 136 | ||
145 | static void | 137 | static void it8712f_wdt_update_margin(void) |
146 | it8712f_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 | ||
168 | static int | 159 | static int it8712f_wdt_get_status(void) |
169 | it8712f_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 | ||
177 | static void | 167 | static void it8712f_wdt_enable(void) |
178 | it8712f_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 | ||
193 | static void | 182 | static void it8712f_wdt_disable(void) |
194 | it8712f_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 | ||
210 | static int | 198 | static int it8712f_wdt_notify(struct notifier_block *this, |
211 | it8712f_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 | ||
225 | static ssize_t | 212 | static ssize_t it8712f_wdt_write(struct file *file, const char __user *data, |
226 | it8712f_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 | ||
248 | static int | 234 | static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, |
249 | it8712f_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 | ||
305 | static int | 290 | static int it8712f_wdt_open(struct inode *inode, struct file *file) |
306 | it8712f_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 | ||
316 | static int | 299 | static int it8712f_wdt_release(struct inode *inode, struct file *file) |
317 | it8712f_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 | ||
347 | static int __init | 329 | static int __init it8712f_wdt_find(unsigned short *address) |
348 | it8712f_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 | ||
390 | static int __init | 371 | static int __init it8712f_wdt_init(void) |
391 | it8712f_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 | ||
433 | static void __exit | 411 | static void __exit it8712f_wdt_exit(void) |
434 | it8712f_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 @@ | |||
65 | static int nowayout = WATCHDOG_NOWAYOUT; | 64 | static int nowayout = WATCHDOG_NOWAYOUT; |
66 | static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME; | 65 | static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME; |
67 | static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT; | 66 | static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT; |
68 | static int soft_noboot = 0; | 67 | static int soft_noboot; |
69 | static int debug = 0; | 68 | static int debug; |
70 | 69 | ||
71 | module_param(tmr_margin, int, 0); | 70 | module_param(tmr_margin, int, 0); |
72 | module_param(tmr_atboot, int, 0); | 71 | module_param(tmr_atboot, int, 0); |
@@ -74,24 +73,23 @@ module_param(nowayout, int, 0); | |||
74 | module_param(soft_noboot, int, 0); | 73 | module_param(soft_noboot, int, 0); |
75 | module_param(debug, int, 0); | 74 | module_param(debug, int, 0); |
76 | 75 | ||
77 | MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME) ")"); | 76 | MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. default=" |
78 | 77 | __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME) ")"); | |
79 | MODULE_PARM_DESC(tmr_atboot, "Watchdog is started at boot time if set to 1, default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT)); | 78 | MODULE_PARM_DESC(tmr_atboot, |
80 | 79 | "Watchdog is started at boot time if set to 1, default=" | |
81 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 80 | __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT)); |
82 | 81 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | |
82 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
83 | MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)"); | 83 | MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)"); |
84 | |||
85 | MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug, (default 0)"); | 84 | MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug, (default 0)"); |
86 | 85 | ||
87 | 86 | ||
88 | typedef enum close_state { | 87 | typedef 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 | ||
93 | static DECLARE_MUTEX(open_lock); | 92 | static unsigned long open_lock; |
94 | |||
95 | static struct device *wdt_dev; /* platform device attached to */ | 93 | static struct device *wdt_dev; /* platform device attached to */ |
96 | static struct resource *wdt_mem; | 94 | static struct resource *wdt_mem; |
97 | static struct resource *wdt_irq; | 95 | static struct resource *wdt_irq; |
@@ -99,38 +97,58 @@ static struct clk *wdt_clock; | |||
99 | static void __iomem *wdt_base; | 97 | static void __iomem *wdt_base; |
100 | static unsigned int wdt_count; | 98 | static unsigned int wdt_count; |
101 | static close_state_t allow_close; | 99 | static close_state_t allow_close; |
100 | static 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 | ||
112 | static int s3c2410wdt_keepalive(void) | 111 | static 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 | ||
118 | static int s3c2410wdt_stop(void) | 118 | static 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; | 129 | static 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 | |||
138 | static void s3c2410wdt_stop(void) | ||
139 | { | ||
140 | spin_lock(&wdt_lock); | ||
141 | __s3c2410wdt_stop(); | ||
142 | spin_unlock(&wdt_lock); | ||
127 | } | 143 | } |
128 | 144 | ||
129 | static int s3c2410wdt_start(void) | 145 | static 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 | ||
212 | static int s3c2410wdt_open(struct inode *inode, struct file *file) | 231 | static 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 | ||
276 | static struct watchdog_info s3c2410_wdt_ident = { | 293 | static 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 | ||
283 | static int s3c2410wdt_ioctl(struct inode *inode, struct file *file, | 300 | static 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 | ||
488 | static void s3c2410wdt_shutdown(struct platform_device *dev) | 499 | static 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 | ||
543 | static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"; | 554 | static char banner[] __initdata = |
555 | KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"; | ||
544 | 556 | ||
545 | static int __init watchdog_init(void) | 557 | static 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; | |||
72 | static int timeout = 1; | 75 | static int timeout = 1; |
73 | static int io = -1; | 76 | static int io = -1; |
74 | static int io_len = 2; /* for non plug and play */ | 77 | static int io_len = 2; /* for non plug and play */ |
75 | static struct semaphore open_sem; | 78 | static unsigned long open_flag; |
76 | static char expect_close; | 79 | static char expect_close; |
77 | static DEFINE_SPINLOCK(sc1200wdt_lock); /* io port access serialisation */ | 80 | static DEFINE_SPINLOCK(sc1200wdt_lock); /* io port access serialisation */ |
78 | 81 | ||
@@ -81,7 +84,8 @@ static int isapnp = 1; | |||
81 | static struct pnp_dev *wdt_dev; | 84 | static struct pnp_dev *wdt_dev; |
82 | 85 | ||
83 | module_param(isapnp, int, 0); | 86 | module_param(isapnp, int, 0); |
84 | MODULE_PARM_DESC(isapnp, "When set to 0 driver ISA PnP support will be disabled"); | 87 | MODULE_PARM_DESC(isapnp, |
88 | "When set to 0 driver ISA PnP support will be disabled"); | ||
85 | #endif | 89 | #endif |
86 | 90 | ||
87 | module_param(io, int, 0); | 91 | module_param(io, int, 0); |
@@ -91,26 +95,40 @@ MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1"); | |||
91 | 95 | ||
92 | static int nowayout = WATCHDOG_NOWAYOUT; | 96 | static int nowayout = WATCHDOG_NOWAYOUT; |
93 | module_param(nowayout, int, 0); | 97 | module_param(nowayout, int, 0); |
94 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 98 | MODULE_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 */ |
99 | static inline void sc1200wdt_read_data(unsigned char index, unsigned char *data) | 105 | static 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 | ||
112 | static 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 */ |
109 | static inline void sc1200wdt_write_data(unsigned char index, unsigned char data) | 120 | static 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 | |||
127 | static 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) | |||
118 | static void sc1200wdt_start(void) | 136 | static 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, ®); | 141 | __sc1200wdt_read_data(WDCF, ®); |
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 | ||
131 | static void sc1200wdt_stop(void) | 151 | static 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. */ |
138 | static inline int sc1200wdt_status(void) | 157 | static 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 | |||
151 | static int sc1200wdt_open(struct inode *inode, struct file *file) | 169 | static 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 | ||
167 | static int sc1200wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 185 | static 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 | ||
252 | static ssize_t sc1200wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) | 271 | static 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 | ||
278 | static int sc1200wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) | 298 | static 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 | ||
287 | static struct notifier_block sc1200wdt_notifier = | 308 | static struct notifier_block sc1200wdt_notifier = { |
288 | { | ||
289 | .notifier_call = sc1200wdt_notify_sys, | 309 | .notifier_call = sc1200wdt_notify_sys, |
290 | }; | 310 | }; |
291 | 311 | ||
292 | static const struct file_operations sc1200wdt_fops = | 312 | static 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 | ||
302 | static struct miscdevice sc1200wdt_miscdev = | 321 | static 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, ®); | 339 | sc1200wdt_read_data(PMC3, ®); |
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 | ||
335 | static int scl200wdt_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) | 353 | static 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 | ||
354 | static void scl200wdt_pnp_remove(struct pnp_dev * dev) | 374 | static 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; | |||
60 | static int heartbeat = WD_TIMO; | 61 | static int heartbeat = WD_TIMO; |
61 | static int wd_heartbeat; | 62 | static int wd_heartbeat; |
62 | module_param(heartbeat, int, 0); | 63 | module_param(heartbeat, int, 0); |
63 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); | 64 | MODULE_PARM_DESC(heartbeat, |
65 | "Watchdog heartbeat in seconds. (0 < heartbeat < 65536, default=" | ||
66 | __MODULE_STRING(WD_TIMO) ")"); | ||
64 | 67 | ||
65 | static int nowayout = WATCHDOG_NOWAYOUT; | 68 | static int nowayout = WATCHDOG_NOWAYOUT; |
66 | module_param(nowayout, int, 0); | 69 | module_param(nowayout, int, 0); |
67 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 70 | MODULE_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. */ |
70 | static int io=0x240; | 75 | static int io = 0x240; |
71 | static int irq=11; | 76 | static int irq = 11; |
72 | 77 | ||
73 | static DEFINE_SPINLOCK(wdt_lock); | 78 | static DEFINE_SPINLOCK(wdt_lock); |
74 | 79 | ||
@@ -82,7 +87,8 @@ MODULE_PARM_DESC(irq, "WDT irq (default=11)"); | |||
82 | static int tachometer; | 87 | static int tachometer; |
83 | 88 | ||
84 | module_param(tachometer, int, 0); | 89 | module_param(tachometer, int, 0); |
85 | MODULE_PARM_DESC(tachometer, "WDT501-P Fan Tachometer support (0=disable, default=0)"); | 90 | MODULE_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 | ||
92 | static void wdt_ctr_mode(int ctr, int mode) | 98 | static 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 | ||
134 | static int wdt_stop (void) | 143 | static 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 | ||
152 | static int wdt_ping(void) | 161 | static 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 | |||
173 | static int wdt_set_heartbeat(int t) | 184 | static 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 | ||
307 | static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 318 | static 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 | ||
341 | static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 352 | static 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 | ||
406 | static int wdt_open(struct inode *inode, struct file *file) | 412 | static 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 | ||
454 | static ssize_t wdt_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) | 461 | static 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) | |||
506 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | 514 | static 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 | ||
642 | out: | 654 | out: |
@@ -651,7 +663,7 @@ outrbt: | |||
651 | outirq: | 663 | outirq: |
652 | free_irq(irq, NULL); | 664 | free_irq(irq, NULL); |
653 | outreg: | 665 | outreg: |
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 */ |
74 | static int dev_count; | 77 | static int dev_count; |
75 | 78 | ||
76 | static struct semaphore open_sem; | 79 | static unsigned long open_lock; |
77 | static DEFINE_SPINLOCK(wdtpci_lock); | 80 | static DEFINE_SPINLOCK(wdtpci_lock); |
78 | static char expect_close; | 81 | static char expect_close; |
79 | 82 | ||
@@ -86,18 +89,23 @@ static int irq; | |||
86 | static int heartbeat = WD_TIMO; | 89 | static int heartbeat = WD_TIMO; |
87 | static int wd_heartbeat; | 90 | static int wd_heartbeat; |
88 | module_param(heartbeat, int, 0); | 91 | module_param(heartbeat, int, 0); |
89 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); | 92 | MODULE_PARM_DESC(heartbeat, |
93 | "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" | ||
94 | __MODULE_STRING(WD_TIMO) ")"); | ||
90 | 95 | ||
91 | static int nowayout = WATCHDOG_NOWAYOUT; | 96 | static int nowayout = WATCHDOG_NOWAYOUT; |
92 | module_param(nowayout, int, 0); | 97 | module_param(nowayout, int, 0); |
93 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 98 | MODULE_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 */ |
97 | static int tachometer; | 104 | static int tachometer; |
98 | 105 | ||
99 | module_param(tachometer, int, 0); | 106 | module_param(tachometer, int, 0); |
100 | MODULE_PARM_DESC(tachometer, "PCI-WDT501 Fan Tachometer support (0=disable, default=0)"); | 107 | MODULE_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 | ||
107 | static void wdtpci_ctr_mode(int ctr, int mode) | 115 | static 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 | ||
115 | static void wdtpci_ctr_load(int ctr, int val) | 124 | static 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 | ||
165 | static int wdtpci_stop (void) | 188 | static 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 | ||
184 | static int wdtpci_ping(void) | 208 | static 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 | */ |
206 | static int wdtpci_set_heartbeat(int t) | 233 | static 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 | ||
228 | static int wdtpci_get_status(int *status) | 255 | static 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 | ||
260 | static int wdtpci_get_temperature(int *temperature) | 292 | static 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 | ||
328 | static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 373 | static 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 | ||
362 | static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 406 | static 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 | ||
427 | static int wdtpci_open(struct inode *inode, struct file *file) | 467 | static 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 | ||
479 | static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) | 518 | static 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 | ||
531 | static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, | 571 | static 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 | ||
587 | static int __devinit wdtpci_init_one (struct pci_dev *dev, | 625 | static 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: | |||
673 | out_irq: | 716 | out_irq: |
674 | free_irq(irq, &wdtpci_miscdev); | 717 | free_irq(irq, &wdtpci_miscdev); |
675 | out_reg: | 718 | out_reg: |
676 | release_region (io, 16); | 719 | release_region(io, 16); |
677 | out_pci: | 720 | out_pci: |
678 | pci_disable_device(dev); | 721 | pci_disable_device(dev); |
679 | goto out; | 722 | goto out; |
680 | } | 723 | } |
681 | 724 | ||
682 | 725 | ||
683 | static void __devexit wdtpci_remove_one (struct pci_dev *pdev) | 726 | static 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 | ||
729 | static void __exit wdtpci_cleanup(void) | 772 | static 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 | ||
743 | static int __init wdtpci_init(void) | 786 | static 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 | ||