diff options
author | Alan Cox <alan@redhat.com> | 2008-08-04 12:55:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-04 20:12:07 -0400 |
commit | 9f2d1f0da766f84fdb96c9bd79ed0f97036635cb (patch) | |
tree | 398d413ab236da55522fe091be55d9e4ba798660 /drivers/watchdog/wdt_pci.c | |
parent | 41dc8b72e37c514f7332cbc3f3dd864910c2a1fa (diff) |
wdt: Cleanup and sort out locking and inb_p
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/watchdog/wdt_pci.c')
-rw-r--r-- | drivers/watchdog/wdt_pci.c | 300 |
1 files changed, 171 insertions, 129 deletions
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 1355608683e4..078f37f80383 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 | ||
@@ -47,9 +49,9 @@ | |||
47 | #include <linux/init.h> | 49 | #include <linux/init.h> |
48 | #include <linux/fs.h> | 50 | #include <linux/fs.h> |
49 | #include <linux/pci.h> | 51 | #include <linux/pci.h> |
52 | #include <linux/io.h> | ||
53 | #include <linux/uaccess.h> | ||
50 | 54 | ||
51 | #include <asm/io.h> | ||
52 | #include <asm/uaccess.h> | ||
53 | #include <asm/system.h> | 55 | #include <asm/system.h> |
54 | 56 | ||
55 | #define WDT_IS_PCI | 57 | #define WDT_IS_PCI |
@@ -73,7 +75,7 @@ | |||
73 | /* We can only use 1 card due to the /dev/watchdog restriction */ | 75 | /* We can only use 1 card due to the /dev/watchdog restriction */ |
74 | static int dev_count; | 76 | static int dev_count; |
75 | 77 | ||
76 | static struct semaphore open_sem; | 78 | static unsigned long open_lock; |
77 | static DEFINE_SPINLOCK(wdtpci_lock); | 79 | static DEFINE_SPINLOCK(wdtpci_lock); |
78 | static char expect_close; | 80 | static char expect_close; |
79 | 81 | ||
@@ -86,18 +88,23 @@ static int irq; | |||
86 | static int heartbeat = WD_TIMO; | 88 | static int heartbeat = WD_TIMO; |
87 | static int wd_heartbeat; | 89 | static int wd_heartbeat; |
88 | module_param(heartbeat, int, 0); | 90 | module_param(heartbeat, int, 0); |
89 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); | 91 | MODULE_PARM_DESC(heartbeat, |
92 | "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" | ||
93 | __MODULE_STRING(WD_TIMO) ")"); | ||
90 | 94 | ||
91 | static int nowayout = WATCHDOG_NOWAYOUT; | 95 | static int nowayout = WATCHDOG_NOWAYOUT; |
92 | module_param(nowayout, int, 0); | 96 | module_param(nowayout, int, 0); |
93 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 97 | MODULE_PARM_DESC(nowayout, |
98 | "Watchdog cannot be stopped once started (default=" | ||
99 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
94 | 100 | ||
95 | #ifdef CONFIG_WDT_501_PCI | 101 | #ifdef CONFIG_WDT_501_PCI |
96 | /* Support for the Fan Tachometer on the PCI-WDT501 */ | 102 | /* Support for the Fan Tachometer on the PCI-WDT501 */ |
97 | static int tachometer; | 103 | static int tachometer; |
98 | 104 | ||
99 | module_param(tachometer, int, 0); | 105 | module_param(tachometer, int, 0); |
100 | MODULE_PARM_DESC(tachometer, "PCI-WDT501 Fan Tachometer support (0=disable, default=0)"); | 106 | MODULE_PARM_DESC(tachometer, |
107 | "PCI-WDT501 Fan Tachometer support (0=disable, default=0)"); | ||
101 | #endif /* CONFIG_WDT_501_PCI */ | 108 | #endif /* CONFIG_WDT_501_PCI */ |
102 | 109 | ||
103 | /* | 110 | /* |
@@ -106,16 +113,19 @@ MODULE_PARM_DESC(tachometer, "PCI-WDT501 Fan Tachometer support (0=disable, defa | |||
106 | 113 | ||
107 | static void wdtpci_ctr_mode(int ctr, int mode) | 114 | static void wdtpci_ctr_mode(int ctr, int mode) |
108 | { | 115 | { |
109 | ctr<<=6; | 116 | ctr <<= 6; |
110 | ctr|=0x30; | 117 | ctr |= 0x30; |
111 | ctr|=(mode<<1); | 118 | ctr |= (mode << 1); |
112 | outb_p(ctr, WDT_CR); | 119 | outb(ctr, WDT_CR); |
120 | udelay(8); | ||
113 | } | 121 | } |
114 | 122 | ||
115 | static void wdtpci_ctr_load(int ctr, int val) | 123 | static void wdtpci_ctr_load(int ctr, int val) |
116 | { | 124 | { |
117 | outb_p(val&0xFF, WDT_COUNT0+ctr); | 125 | outb(val & 0xFF, WDT_COUNT0 + ctr); |
118 | outb_p(val>>8, WDT_COUNT0+ctr); | 126 | udelay(8); |
127 | outb(val >> 8, WDT_COUNT0 + ctr); | ||
128 | udelay(8); | ||
119 | } | 129 | } |
120 | 130 | ||
121 | /** | 131 | /** |
@@ -134,23 +144,35 @@ static int wdtpci_start(void) | |||
134 | * "pet" the watchdog, as Access says. | 144 | * "pet" the watchdog, as Access says. |
135 | * This resets the clock outputs. | 145 | * This resets the clock outputs. |
136 | */ | 146 | */ |
137 | inb_p(WDT_DC); /* Disable watchdog */ | 147 | inb(WDT_DC); /* Disable watchdog */ |
138 | wdtpci_ctr_mode(2,0); /* Program CTR2 for Mode 0: Pulse on Terminal Count */ | 148 | udelay(8); |
139 | outb_p(0, WDT_DC); /* Enable watchdog */ | 149 | wdtpci_ctr_mode(2, 0); /* Program CTR2 for Mode 0: |
140 | 150 | Pulse on Terminal Count */ | |
141 | inb_p(WDT_DC); /* Disable watchdog */ | 151 | outb(0, WDT_DC); /* Enable watchdog */ |
142 | outb_p(0, WDT_CLOCK); /* 2.0833MHz clock */ | 152 | udelay(8); |
143 | inb_p(WDT_BUZZER); /* disable */ | 153 | inb(WDT_DC); /* Disable watchdog */ |
144 | inb_p(WDT_OPTONOTRST); /* disable */ | 154 | udelay(8); |
145 | inb_p(WDT_OPTORST); /* disable */ | 155 | outb(0, WDT_CLOCK); /* 2.0833MHz clock */ |
146 | inb_p(WDT_PROGOUT); /* disable */ | 156 | udelay(8); |
147 | wdtpci_ctr_mode(0,3); /* Program CTR0 for Mode 3: Square Wave Generator */ | 157 | inb(WDT_BUZZER); /* disable */ |
148 | wdtpci_ctr_mode(1,2); /* Program CTR1 for Mode 2: Rate Generator */ | 158 | udelay(8); |
149 | wdtpci_ctr_mode(2,1); /* Program CTR2 for Mode 1: Retriggerable One-Shot */ | 159 | inb(WDT_OPTONOTRST); /* disable */ |
150 | wdtpci_ctr_load(0,20833); /* count at 100Hz */ | 160 | udelay(8); |
151 | wdtpci_ctr_load(1,wd_heartbeat);/* Heartbeat */ | 161 | inb(WDT_OPTORST); /* disable */ |
162 | udelay(8); | ||
163 | inb(WDT_PROGOUT); /* disable */ | ||
164 | udelay(8); | ||
165 | wdtpci_ctr_mode(0, 3); /* Program CTR0 for Mode 3: | ||
166 | Square Wave Generator */ | ||
167 | wdtpci_ctr_mode(1, 2); /* Program CTR1 for Mode 2: | ||
168 | Rate Generator */ | ||
169 | wdtpci_ctr_mode(2, 1); /* Program CTR2 for Mode 1: | ||
170 | Retriggerable One-Shot */ | ||
171 | wdtpci_ctr_load(0, 20833); /* count at 100Hz */ | ||
172 | wdtpci_ctr_load(1, wd_heartbeat);/* Heartbeat */ | ||
152 | /* DO NOT LOAD CTR2 on PCI card! -- JPN */ | 173 | /* DO NOT LOAD CTR2 on PCI card! -- JPN */ |
153 | outb_p(0, WDT_DC); /* Enable watchdog */ | 174 | outb(0, WDT_DC); /* Enable watchdog */ |
175 | udelay(8); | ||
154 | 176 | ||
155 | spin_unlock_irqrestore(&wdtpci_lock, flags); | 177 | spin_unlock_irqrestore(&wdtpci_lock, flags); |
156 | return 0; | 178 | return 0; |
@@ -162,14 +184,15 @@ static int wdtpci_start(void) | |||
162 | * Stop the watchdog driver. | 184 | * Stop the watchdog driver. |
163 | */ | 185 | */ |
164 | 186 | ||
165 | static int wdtpci_stop (void) | 187 | static int wdtpci_stop(void) |
166 | { | 188 | { |
167 | unsigned long flags; | 189 | unsigned long flags; |
168 | 190 | ||
169 | /* Turn the card off */ | 191 | /* Turn the card off */ |
170 | spin_lock_irqsave(&wdtpci_lock, flags); | 192 | spin_lock_irqsave(&wdtpci_lock, flags); |
171 | inb_p(WDT_DC); /* Disable watchdog */ | 193 | inb(WDT_DC); /* Disable watchdog */ |
172 | wdtpci_ctr_load(2,0); /* 0 length reset pulses now */ | 194 | udelay(8); |
195 | wdtpci_ctr_load(2, 0); /* 0 length reset pulses now */ | ||
173 | spin_unlock_irqrestore(&wdtpci_lock, flags); | 196 | spin_unlock_irqrestore(&wdtpci_lock, flags); |
174 | return 0; | 197 | return 0; |
175 | } | 198 | } |
@@ -177,20 +200,23 @@ static int wdtpci_stop (void) | |||
177 | /** | 200 | /** |
178 | * wdtpci_ping: | 201 | * wdtpci_ping: |
179 | * | 202 | * |
180 | * Reload counter one with the watchdog heartbeat. We don't bother reloading | 203 | * Reload counter one with the watchdog heartbeat. We don't bother |
181 | * the cascade counter. | 204 | * reloading the cascade counter. |
182 | */ | 205 | */ |
183 | 206 | ||
184 | static int wdtpci_ping(void) | 207 | static int wdtpci_ping(void) |
185 | { | 208 | { |
186 | unsigned long flags; | 209 | unsigned long flags; |
187 | 210 | ||
188 | /* Write a watchdog value */ | ||
189 | spin_lock_irqsave(&wdtpci_lock, flags); | 211 | spin_lock_irqsave(&wdtpci_lock, flags); |
190 | inb_p(WDT_DC); /* Disable watchdog */ | 212 | /* Write a watchdog value */ |
191 | wdtpci_ctr_mode(1,2); /* Re-Program CTR1 for Mode 2: Rate Generator */ | 213 | inb(WDT_DC); /* Disable watchdog */ |
192 | wdtpci_ctr_load(1,wd_heartbeat);/* Heartbeat */ | 214 | udelay(8); |
193 | outb_p(0, WDT_DC); /* Enable watchdog */ | 215 | wdtpci_ctr_mode(1, 2); /* Re-Program CTR1 for Mode 2: |
216 | Rate Generator */ | ||
217 | wdtpci_ctr_load(1, wd_heartbeat);/* Heartbeat */ | ||
218 | outb(0, WDT_DC); /* Enable watchdog */ | ||
219 | udelay(8); | ||
194 | spin_unlock_irqrestore(&wdtpci_lock, flags); | 220 | spin_unlock_irqrestore(&wdtpci_lock, flags); |
195 | return 0; | 221 | return 0; |
196 | } | 222 | } |
@@ -199,14 +225,14 @@ static int wdtpci_ping(void) | |||
199 | * wdtpci_set_heartbeat: | 225 | * wdtpci_set_heartbeat: |
200 | * @t: the new heartbeat value that needs to be set. | 226 | * @t: the new heartbeat value that needs to be set. |
201 | * | 227 | * |
202 | * Set a new heartbeat value for the watchdog device. If the heartbeat value is | 228 | * 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 | 229 | * value is incorrect we keep the old value and return -EINVAL. |
204 | * return 0. | 230 | * If successful we return 0. |
205 | */ | 231 | */ |
206 | static int wdtpci_set_heartbeat(int t) | 232 | static int wdtpci_set_heartbeat(int t) |
207 | { | 233 | { |
208 | /* Arbitrary, can't find the card's limits */ | 234 | /* Arbitrary, can't find the card's limits */ |
209 | if ((t < 1) || (t > 65535)) | 235 | if (t < 1 || t > 65535) |
210 | return -EINVAL; | 236 | return -EINVAL; |
211 | 237 | ||
212 | heartbeat = t; | 238 | heartbeat = t; |
@@ -227,9 +253,14 @@ static int wdtpci_set_heartbeat(int t) | |||
227 | 253 | ||
228 | static int wdtpci_get_status(int *status) | 254 | static int wdtpci_get_status(int *status) |
229 | { | 255 | { |
230 | unsigned char new_status=inb_p(WDT_SR); | 256 | unsigned char new_status; |
257 | unsigned long flags; | ||
258 | |||
259 | spin_lock_irqsave(&wdtpci_lock, flags); | ||
260 | new_status = inb(WDT_SR); | ||
261 | spin_unlock_irqrestore(&wdtpci_lock, flags); | ||
231 | 262 | ||
232 | *status=0; | 263 | *status = 0; |
233 | if (new_status & WDC_SR_ISOI0) | 264 | if (new_status & WDC_SR_ISOI0) |
234 | *status |= WDIOF_EXTERN1; | 265 | *status |= WDIOF_EXTERN1; |
235 | if (new_status & WDC_SR_ISII1) | 266 | if (new_status & WDC_SR_ISII1) |
@@ -259,8 +290,12 @@ static int wdtpci_get_status(int *status) | |||
259 | 290 | ||
260 | static int wdtpci_get_temperature(int *temperature) | 291 | static int wdtpci_get_temperature(int *temperature) |
261 | { | 292 | { |
262 | unsigned short c=inb_p(WDT_RT); | 293 | unsigned short c; |
263 | 294 | unsigned long flags; | |
295 | spin_lock_irqsave(&wdtpci_lock, flags); | ||
296 | c = inb(WDT_RT); | ||
297 | udelay(8); | ||
298 | spin_unlock_irqrestore(&wdtpci_lock, flags); | ||
264 | *temperature = (c * 11 / 15) + 7; | 299 | *temperature = (c * 11 / 15) + 7; |
265 | return 0; | 300 | return 0; |
266 | } | 301 | } |
@@ -282,17 +317,25 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id) | |||
282 | * Read the status register see what is up and | 317 | * Read the status register see what is up and |
283 | * then printk it. | 318 | * then printk it. |
284 | */ | 319 | */ |
285 | unsigned char status=inb_p(WDT_SR); | 320 | unsigned char status; |
321 | |||
322 | spin_lock(&wdtpci_lock); | ||
323 | |||
324 | status = inb(WDT_SR); | ||
325 | udelay(8); | ||
286 | 326 | ||
287 | printk(KERN_CRIT PFX "status %d\n", status); | 327 | printk(KERN_CRIT PFX "status %d\n", status); |
288 | 328 | ||
289 | #ifdef CONFIG_WDT_501_PCI | 329 | #ifdef CONFIG_WDT_501_PCI |
290 | if (!(status & WDC_SR_TGOOD)) | 330 | if (!(status & WDC_SR_TGOOD)) { |
291 | printk(KERN_CRIT PFX "Overheat alarm.(%d)\n",inb_p(WDT_RT)); | 331 | u8 alarm = inb(WDT_RT); |
332 | printk(KERN_CRIT PFX "Overheat alarm.(%d)\n", alarm); | ||
333 | udelay(8); | ||
334 | } | ||
292 | if (!(status & WDC_SR_PSUOVER)) | 335 | if (!(status & WDC_SR_PSUOVER)) |
293 | printk(KERN_CRIT PFX "PSU over voltage.\n"); | 336 | printk(KERN_CRIT PFX "PSU over voltage.\n"); |
294 | if (!(status & WDC_SR_PSUUNDR)) | 337 | if (!(status & WDC_SR_PSUUNDR)) |
295 | printk(KERN_CRIT PFX "PSU under voltage.\n"); | 338 | printk(KERN_CRIT PFX "PSU under voltage.\n"); |
296 | if (tachometer) { | 339 | if (tachometer) { |
297 | if (!(status & WDC_SR_FANGOOD)) | 340 | if (!(status & WDC_SR_FANGOOD)) |
298 | printk(KERN_CRIT PFX "Possible fan fault.\n"); | 341 | printk(KERN_CRIT PFX "Possible fan fault.\n"); |
@@ -310,6 +353,7 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id) | |||
310 | printk(KERN_CRIT PFX "Reset in 5ms.\n"); | 353 | printk(KERN_CRIT PFX "Reset in 5ms.\n"); |
311 | #endif | 354 | #endif |
312 | } | 355 | } |
356 | spin_unlock(&wdtpci_lock); | ||
313 | return IRQ_HANDLED; | 357 | return IRQ_HANDLED; |
314 | } | 358 | } |
315 | 359 | ||
@@ -325,7 +369,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. | 369 | * write of data will do, as we we don't define content meaning. |
326 | */ | 370 | */ |
327 | 371 | ||
328 | static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 372 | static ssize_t wdtpci_write(struct file *file, const char __user *buf, |
373 | size_t count, loff_t *ppos) | ||
329 | { | 374 | { |
330 | if (count) { | 375 | if (count) { |
331 | if (!nowayout) { | 376 | if (!nowayout) { |
@@ -335,7 +380,7 @@ static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t co | |||
335 | 380 | ||
336 | for (i = 0; i != count; i++) { | 381 | for (i = 0; i != count; i++) { |
337 | char c; | 382 | char c; |
338 | if(get_user(c, buf+i)) | 383 | if (get_user(c, buf+i)) |
339 | return -EFAULT; | 384 | return -EFAULT; |
340 | if (c == 'V') | 385 | if (c == 'V') |
341 | expect_close = 42; | 386 | expect_close = 42; |
@@ -343,13 +388,11 @@ static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t co | |||
343 | } | 388 | } |
344 | wdtpci_ping(); | 389 | wdtpci_ping(); |
345 | } | 390 | } |
346 | |||
347 | return count; | 391 | return count; |
348 | } | 392 | } |
349 | 393 | ||
350 | /** | 394 | /** |
351 | * wdtpci_ioctl: | 395 | * wdtpci_ioctl: |
352 | * @inode: inode of the device | ||
353 | * @file: file handle to the device | 396 | * @file: file handle to the device |
354 | * @cmd: watchdog command | 397 | * @cmd: watchdog command |
355 | * @arg: argument pointer | 398 | * @arg: argument pointer |
@@ -359,8 +402,8 @@ static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t co | |||
359 | * querying capabilities and current status. | 402 | * querying capabilities and current status. |
360 | */ | 403 | */ |
361 | 404 | ||
362 | static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 405 | static long wdtpci_ioctl(struct file *file, unsigned int cmd, |
363 | unsigned long arg) | 406 | unsigned long arg) |
364 | { | 407 | { |
365 | int new_heartbeat; | 408 | int new_heartbeat; |
366 | int status; | 409 | int status; |
@@ -383,33 +426,29 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
383 | ident.options |= WDIOF_FANFAULT; | 426 | ident.options |= WDIOF_FANFAULT; |
384 | #endif /* CONFIG_WDT_501_PCI */ | 427 | #endif /* CONFIG_WDT_501_PCI */ |
385 | 428 | ||
386 | switch(cmd) | 429 | switch (cmd) { |
387 | { | 430 | default: |
388 | default: | 431 | return -ENOTTY; |
389 | return -ENOTTY; | 432 | case WDIOC_GETSUPPORT: |
390 | case WDIOC_GETSUPPORT: | 433 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
391 | return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; | 434 | case WDIOC_GETSTATUS: |
392 | 435 | wdtpci_get_status(&status); | |
393 | case WDIOC_GETSTATUS: | 436 | return put_user(status, p); |
394 | wdtpci_get_status(&status); | 437 | case WDIOC_GETBOOTSTATUS: |
395 | return put_user(status, p); | 438 | return put_user(0, p); |
396 | case WDIOC_GETBOOTSTATUS: | 439 | case WDIOC_KEEPALIVE: |
397 | return put_user(0, p); | 440 | wdtpci_ping(); |
398 | case WDIOC_KEEPALIVE: | 441 | return 0; |
399 | wdtpci_ping(); | 442 | case WDIOC_SETTIMEOUT: |
400 | return 0; | 443 | if (get_user(new_heartbeat, p)) |
401 | case WDIOC_SETTIMEOUT: | 444 | return -EFAULT; |
402 | if (get_user(new_heartbeat, p)) | 445 | if (wdtpci_set_heartbeat(new_heartbeat)) |
403 | return -EFAULT; | 446 | return -EINVAL; |
404 | 447 | wdtpci_ping(); | |
405 | if (wdtpci_set_heartbeat(new_heartbeat)) | 448 | /* Fall */ |
406 | return -EINVAL; | 449 | case WDIOC_GETTIMEOUT: |
407 | 450 | return put_user(heartbeat, p); | |
408 | wdtpci_ping(); | 451 | } |
409 | /* Fall */ | ||
410 | case WDIOC_GETTIMEOUT: | ||
411 | return put_user(heartbeat, p); | ||
412 | } | ||
413 | } | 452 | } |
414 | 453 | ||
415 | /** | 454 | /** |
@@ -426,12 +465,11 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
426 | 465 | ||
427 | static int wdtpci_open(struct inode *inode, struct file *file) | 466 | static int wdtpci_open(struct inode *inode, struct file *file) |
428 | { | 467 | { |
429 | if (down_trylock(&open_sem)) | 468 | if (test_and_set_bit(0, &open_lock)) |
430 | return -EBUSY; | 469 | return -EBUSY; |
431 | 470 | ||
432 | if (nowayout) { | 471 | if (nowayout) |
433 | __module_get(THIS_MODULE); | 472 | __module_get(THIS_MODULE); |
434 | } | ||
435 | /* | 473 | /* |
436 | * Activate | 474 | * Activate |
437 | */ | 475 | */ |
@@ -460,7 +498,7 @@ static int wdtpci_release(struct inode *inode, struct file *file) | |||
460 | wdtpci_ping(); | 498 | wdtpci_ping(); |
461 | } | 499 | } |
462 | expect_close = 0; | 500 | expect_close = 0; |
463 | up(&open_sem); | 501 | clear_bit(0, &open_lock); |
464 | return 0; | 502 | return 0; |
465 | } | 503 | } |
466 | 504 | ||
@@ -476,14 +514,15 @@ static int wdtpci_release(struct inode *inode, struct file *file) | |||
476 | * fahrenheit. It was designed by an imperial measurement luddite. | 514 | * fahrenheit. It was designed by an imperial measurement luddite. |
477 | */ | 515 | */ |
478 | 516 | ||
479 | static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) | 517 | static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, |
518 | size_t count, loff_t *ptr) | ||
480 | { | 519 | { |
481 | int temperature; | 520 | int temperature; |
482 | 521 | ||
483 | if (wdtpci_get_temperature(&temperature)) | 522 | if (wdtpci_get_temperature(&temperature)) |
484 | return -EFAULT; | 523 | return -EFAULT; |
485 | 524 | ||
486 | if (copy_to_user (buf, &temperature, 1)) | 525 | if (copy_to_user(buf, &temperature, 1)) |
487 | return -EFAULT; | 526 | return -EFAULT; |
488 | 527 | ||
489 | return 1; | 528 | return 1; |
@@ -529,12 +568,10 @@ static int wdtpci_temp_release(struct inode *inode, struct file *file) | |||
529 | */ | 568 | */ |
530 | 569 | ||
531 | static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, | 570 | static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, |
532 | void *unused) | 571 | void *unused) |
533 | { | 572 | { |
534 | if (code==SYS_DOWN || code==SYS_HALT) { | 573 | if (code == SYS_DOWN || code == SYS_HALT) |
535 | /* Turn the card off */ | ||
536 | wdtpci_stop(); | 574 | wdtpci_stop(); |
537 | } | ||
538 | return NOTIFY_DONE; | 575 | return NOTIFY_DONE; |
539 | } | 576 | } |
540 | 577 | ||
@@ -547,7 +584,7 @@ static const struct file_operations wdtpci_fops = { | |||
547 | .owner = THIS_MODULE, | 584 | .owner = THIS_MODULE, |
548 | .llseek = no_llseek, | 585 | .llseek = no_llseek, |
549 | .write = wdtpci_write, | 586 | .write = wdtpci_write, |
550 | .ioctl = wdtpci_ioctl, | 587 | .unlocked_ioctl = wdtpci_ioctl, |
551 | .open = wdtpci_open, | 588 | .open = wdtpci_open, |
552 | .release = wdtpci_release, | 589 | .release = wdtpci_release, |
553 | }; | 590 | }; |
@@ -584,80 +621,85 @@ static struct notifier_block wdtpci_notifier = { | |||
584 | }; | 621 | }; |
585 | 622 | ||
586 | 623 | ||
587 | static int __devinit wdtpci_init_one (struct pci_dev *dev, | 624 | static int __devinit wdtpci_init_one(struct pci_dev *dev, |
588 | const struct pci_device_id *ent) | 625 | const struct pci_device_id *ent) |
589 | { | 626 | { |
590 | int ret = -EIO; | 627 | int ret = -EIO; |
591 | 628 | ||
592 | dev_count++; | 629 | dev_count++; |
593 | if (dev_count > 1) { | 630 | if (dev_count > 1) { |
594 | printk (KERN_ERR PFX "this driver only supports 1 device\n"); | 631 | printk(KERN_ERR PFX "This driver only supports one device\n"); |
595 | return -ENODEV; | 632 | return -ENODEV; |
596 | } | 633 | } |
597 | 634 | ||
598 | if (pci_enable_device (dev)) { | 635 | if (pci_enable_device(dev)) { |
599 | printk (KERN_ERR PFX "Not possible to enable PCI Device\n"); | 636 | printk(KERN_ERR PFX "Not possible to enable PCI Device\n"); |
600 | return -ENODEV; | 637 | return -ENODEV; |
601 | } | 638 | } |
602 | 639 | ||
603 | if (pci_resource_start (dev, 2) == 0x0000) { | 640 | if (pci_resource_start(dev, 2) == 0x0000) { |
604 | printk (KERN_ERR PFX "No I/O-Address for card detected\n"); | 641 | printk(KERN_ERR PFX "No I/O-Address for card detected\n"); |
605 | ret = -ENODEV; | 642 | ret = -ENODEV; |
606 | goto out_pci; | 643 | goto out_pci; |
607 | } | 644 | } |
608 | 645 | ||
609 | sema_init(&open_sem, 1); | ||
610 | |||
611 | irq = dev->irq; | 646 | irq = dev->irq; |
612 | io = pci_resource_start (dev, 2); | 647 | io = pci_resource_start(dev, 2); |
613 | 648 | ||
614 | if (request_region (io, 16, "wdt_pci") == NULL) { | 649 | if (request_region(io, 16, "wdt_pci") == NULL) { |
615 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", io); | 650 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", io); |
616 | goto out_pci; | 651 | goto out_pci; |
617 | } | 652 | } |
618 | 653 | ||
619 | if (request_irq (irq, wdtpci_interrupt, IRQF_DISABLED | IRQF_SHARED, | 654 | if (request_irq(irq, wdtpci_interrupt, IRQF_DISABLED | IRQF_SHARED, |
620 | "wdt_pci", &wdtpci_miscdev)) { | 655 | "wdt_pci", &wdtpci_miscdev)) { |
621 | printk (KERN_ERR PFX "IRQ %d is not free\n", irq); | 656 | printk(KERN_ERR PFX "IRQ %d is not free\n", irq); |
622 | goto out_reg; | 657 | goto out_reg; |
623 | } | 658 | } |
624 | 659 | ||
625 | printk ("PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%04x (Interrupt %d)\n", | 660 | printk(KERN_INFO |
626 | io, irq); | 661 | "PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%04x (Interrupt %d)\n", |
662 | io, irq); | ||
627 | 663 | ||
628 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ | 664 | /* Check that the heartbeat value is within its range; |
665 | if not reset to the default */ | ||
629 | if (wdtpci_set_heartbeat(heartbeat)) { | 666 | if (wdtpci_set_heartbeat(heartbeat)) { |
630 | wdtpci_set_heartbeat(WD_TIMO); | 667 | wdtpci_set_heartbeat(WD_TIMO); |
631 | printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n", | 668 | printk(KERN_INFO PFX |
632 | WD_TIMO); | 669 | "heartbeat value must be 0 < heartbeat < 65536, using %d\n", |
670 | WD_TIMO); | ||
633 | } | 671 | } |
634 | 672 | ||
635 | ret = register_reboot_notifier (&wdtpci_notifier); | 673 | ret = register_reboot_notifier(&wdtpci_notifier); |
636 | if (ret) { | 674 | if (ret) { |
637 | printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); | 675 | printk(KERN_ERR PFX |
676 | "cannot register reboot notifier (err=%d)\n", ret); | ||
638 | goto out_irq; | 677 | goto out_irq; |
639 | } | 678 | } |
640 | 679 | ||
641 | #ifdef CONFIG_WDT_501_PCI | 680 | #ifdef CONFIG_WDT_501_PCI |
642 | ret = misc_register (&temp_miscdev); | 681 | ret = misc_register(&temp_miscdev); |
643 | if (ret) { | 682 | if (ret) { |
644 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 683 | printk(KERN_ERR PFX |
645 | TEMP_MINOR, ret); | 684 | "cannot register miscdev on minor=%d (err=%d)\n", |
685 | TEMP_MINOR, ret); | ||
646 | goto out_rbt; | 686 | goto out_rbt; |
647 | } | 687 | } |
648 | #endif /* CONFIG_WDT_501_PCI */ | 688 | #endif /* CONFIG_WDT_501_PCI */ |
649 | 689 | ||
650 | ret = misc_register (&wdtpci_miscdev); | 690 | ret = misc_register(&wdtpci_miscdev); |
651 | if (ret) { | 691 | if (ret) { |
652 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 692 | printk(KERN_ERR PFX |
653 | WATCHDOG_MINOR, ret); | 693 | "cannot register miscdev on minor=%d (err=%d)\n", |
694 | WATCHDOG_MINOR, ret); | ||
654 | goto out_misc; | 695 | goto out_misc; |
655 | } | 696 | } |
656 | 697 | ||
657 | printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", | 698 | printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", |
658 | heartbeat, nowayout); | 699 | heartbeat, nowayout); |
659 | #ifdef CONFIG_WDT_501_PCI | 700 | #ifdef CONFIG_WDT_501_PCI |
660 | printk(KERN_INFO "wdt: Fan Tachometer is %s\n", (tachometer ? "Enabled" : "Disabled")); | 701 | printk(KERN_INFO "wdt: Fan Tachometer is %s\n", |
702 | (tachometer ? "Enabled" : "Disabled")); | ||
661 | #endif /* CONFIG_WDT_501_PCI */ | 703 | #endif /* CONFIG_WDT_501_PCI */ |
662 | 704 | ||
663 | ret = 0; | 705 | ret = 0; |
@@ -673,14 +715,14 @@ out_rbt: | |||
673 | out_irq: | 715 | out_irq: |
674 | free_irq(irq, &wdtpci_miscdev); | 716 | free_irq(irq, &wdtpci_miscdev); |
675 | out_reg: | 717 | out_reg: |
676 | release_region (io, 16); | 718 | release_region(io, 16); |
677 | out_pci: | 719 | out_pci: |
678 | pci_disable_device(dev); | 720 | pci_disable_device(dev); |
679 | goto out; | 721 | goto out; |
680 | } | 722 | } |
681 | 723 | ||
682 | 724 | ||
683 | static void __devexit wdtpci_remove_one (struct pci_dev *pdev) | 725 | static void __devexit wdtpci_remove_one(struct pci_dev *pdev) |
684 | { | 726 | { |
685 | /* here we assume only one device will ever have | 727 | /* here we assume only one device will ever have |
686 | * been picked up and registered by probe function */ | 728 | * been picked up and registered by probe function */ |
@@ -728,7 +770,7 @@ static struct pci_driver wdtpci_driver = { | |||
728 | 770 | ||
729 | static void __exit wdtpci_cleanup(void) | 771 | static void __exit wdtpci_cleanup(void) |
730 | { | 772 | { |
731 | pci_unregister_driver (&wdtpci_driver); | 773 | pci_unregister_driver(&wdtpci_driver); |
732 | } | 774 | } |
733 | 775 | ||
734 | 776 | ||
@@ -742,7 +784,7 @@ static void __exit wdtpci_cleanup(void) | |||
742 | 784 | ||
743 | static int __init wdtpci_init(void) | 785 | static int __init wdtpci_init(void) |
744 | { | 786 | { |
745 | return pci_register_driver (&wdtpci_driver); | 787 | return pci_register_driver(&wdtpci_driver); |
746 | } | 788 | } |
747 | 789 | ||
748 | 790 | ||