diff options
| -rw-r--r-- | drivers/watchdog/ar7_wdt.c | 29 |
1 files changed, 17 insertions, 12 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 |
