diff options
| -rw-r--r-- | drivers/watchdog/it8712f_wdt.c | 77 |
1 files changed, 27 insertions, 50 deletions
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); |
