diff options
author | Alan Cox <alan@redhat.com> | 2008-05-19 09:07:15 -0400 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2008-06-13 15:51:55 -0400 |
commit | 83ab1a53f219c8139199633f60ab0ef88ef18c54 (patch) | |
tree | 30e16a3eb8ffb1d497f5af373cbc2735779466cb /drivers/watchdog | |
parent | f26ef3dc69467e135e2b9555e44a088aee5c7d8f (diff) |
[WATCHDOG 27/57] mpcore watchdog: unlocked_ioctl and BKl work
Review and switch to unlocked_ioctl
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/mpcore_wdt.c | 53 |
1 files changed, 32 insertions, 21 deletions
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 009573b81496..5e58f8b73d00 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c | |||
@@ -29,9 +29,9 @@ | |||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
32 | #include <linux/uaccess.h> | ||
32 | 33 | ||
33 | #include <asm/hardware/arm_twd.h> | 34 | #include <asm/hardware/arm_twd.h> |
34 | #include <asm/uaccess.h> | ||
35 | 35 | ||
36 | struct mpcore_wdt { | 36 | struct mpcore_wdt { |
37 | unsigned long timer_alive; | 37 | unsigned long timer_alive; |
@@ -43,17 +43,20 @@ struct mpcore_wdt { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | static struct platform_device *mpcore_wdt_dev; | 45 | static struct platform_device *mpcore_wdt_dev; |
46 | |||
47 | extern unsigned int mpcore_timer_rate; | 46 | extern unsigned int mpcore_timer_rate; |
48 | 47 | ||
49 | #define TIMER_MARGIN 60 | 48 | #define TIMER_MARGIN 60 |
50 | static int mpcore_margin = TIMER_MARGIN; | 49 | static int mpcore_margin = TIMER_MARGIN; |
51 | module_param(mpcore_margin, int, 0); | 50 | module_param(mpcore_margin, int, 0); |
52 | MODULE_PARM_DESC(mpcore_margin, "MPcore timer margin in seconds. (0<mpcore_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")"); | 51 | MODULE_PARM_DESC(mpcore_margin, |
52 | "MPcore timer margin in seconds. (0 < mpcore_margin < 65536, default=" | ||
53 | __MODULE_STRING(TIMER_MARGIN) ")"); | ||
53 | 54 | ||
54 | static int nowayout = WATCHDOG_NOWAYOUT; | 55 | static int nowayout = WATCHDOG_NOWAYOUT; |
55 | module_param(nowayout, int, 0); | 56 | module_param(nowayout, int, 0); |
56 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 57 | MODULE_PARM_DESC(nowayout, |
58 | "Watchdog cannot be stopped once started (default=" | ||
59 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
57 | 60 | ||
58 | #define ONLY_TESTING 0 | 61 | #define ONLY_TESTING 0 |
59 | static int mpcore_noboot = ONLY_TESTING; | 62 | static int mpcore_noboot = ONLY_TESTING; |
@@ -70,14 +73,12 @@ static irqreturn_t mpcore_wdt_fire(int irq, void *arg) | |||
70 | 73 | ||
71 | /* Check it really was our interrupt */ | 74 | /* Check it really was our interrupt */ |
72 | if (readl(wdt->base + TWD_WDOG_INTSTAT)) { | 75 | if (readl(wdt->base + TWD_WDOG_INTSTAT)) { |
73 | dev_printk(KERN_CRIT, wdt->dev, "Triggered - Reboot ignored.\n"); | 76 | dev_printk(KERN_CRIT, wdt->dev, |
74 | 77 | "Triggered - Reboot ignored.\n"); | |
75 | /* Clear the interrupt on the watchdog */ | 78 | /* Clear the interrupt on the watchdog */ |
76 | writel(1, wdt->base + TWD_WDOG_INTSTAT); | 79 | writel(1, wdt->base + TWD_WDOG_INTSTAT); |
77 | |||
78 | return IRQ_HANDLED; | 80 | return IRQ_HANDLED; |
79 | } | 81 | } |
80 | |||
81 | return IRQ_NONE; | 82 | return IRQ_NONE; |
82 | } | 83 | } |
83 | 84 | ||
@@ -96,22 +97,26 @@ static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt) | |||
96 | count = (mpcore_timer_rate / 256) * mpcore_margin; | 97 | count = (mpcore_timer_rate / 256) * mpcore_margin; |
97 | 98 | ||
98 | /* Reload the counter */ | 99 | /* Reload the counter */ |
100 | spin_lock(&wdt_lock); | ||
99 | writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); | 101 | writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); |
100 | |||
101 | wdt->perturb = wdt->perturb ? 0 : 1; | 102 | wdt->perturb = wdt->perturb ? 0 : 1; |
103 | spin_unlock(&wdt_lock); | ||
102 | } | 104 | } |
103 | 105 | ||
104 | static void mpcore_wdt_stop(struct mpcore_wdt *wdt) | 106 | static void mpcore_wdt_stop(struct mpcore_wdt *wdt) |
105 | { | 107 | { |
108 | spin_lock(&wdt_lock); | ||
106 | writel(0x12345678, wdt->base + TWD_WDOG_DISABLE); | 109 | writel(0x12345678, wdt->base + TWD_WDOG_DISABLE); |
107 | writel(0x87654321, wdt->base + TWD_WDOG_DISABLE); | 110 | writel(0x87654321, wdt->base + TWD_WDOG_DISABLE); |
108 | writel(0x0, wdt->base + TWD_WDOG_CONTROL); | 111 | writel(0x0, wdt->base + TWD_WDOG_CONTROL); |
112 | spin_unlock(&wdt_lock); | ||
109 | } | 113 | } |
110 | 114 | ||
111 | static void mpcore_wdt_start(struct mpcore_wdt *wdt) | 115 | static void mpcore_wdt_start(struct mpcore_wdt *wdt) |
112 | { | 116 | { |
113 | dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); | 117 | dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); |
114 | 118 | ||
119 | spin_lock(&wdt_lock); | ||
115 | /* This loads the count register but does NOT start the count yet */ | 120 | /* This loads the count register but does NOT start the count yet */ |
116 | mpcore_wdt_keepalive(wdt); | 121 | mpcore_wdt_keepalive(wdt); |
117 | 122 | ||
@@ -122,6 +127,7 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt) | |||
122 | /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */ | 127 | /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */ |
123 | writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL); | 128 | writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL); |
124 | } | 129 | } |
130 | spin_unlock(&wdt_lock); | ||
125 | } | 131 | } |
126 | 132 | ||
127 | static int mpcore_wdt_set_heartbeat(int t) | 133 | static int mpcore_wdt_set_heartbeat(int t) |
@@ -164,10 +170,11 @@ static int mpcore_wdt_release(struct inode *inode, struct file *file) | |||
164 | * Shut off the timer. | 170 | * Shut off the timer. |
165 | * Lock it in if it's a module and we set nowayout | 171 | * Lock it in if it's a module and we set nowayout |
166 | */ | 172 | */ |
167 | if (wdt->expect_close == 42) { | 173 | if (wdt->expect_close == 42) |
168 | mpcore_wdt_stop(wdt); | 174 | mpcore_wdt_stop(wdt); |
169 | } else { | 175 | else { |
170 | dev_printk(KERN_CRIT, wdt->dev, "unexpected close, not stopping watchdog!\n"); | 176 | dev_printk(KERN_CRIT, wdt->dev, |
177 | "unexpected close, not stopping watchdog!\n"); | ||
171 | mpcore_wdt_keepalive(wdt); | 178 | mpcore_wdt_keepalive(wdt); |
172 | } | 179 | } |
173 | clear_bit(0, &wdt->timer_alive); | 180 | clear_bit(0, &wdt->timer_alive); |
@@ -175,7 +182,8 @@ static int mpcore_wdt_release(struct inode *inode, struct file *file) | |||
175 | return 0; | 182 | return 0; |
176 | } | 183 | } |
177 | 184 | ||
178 | static ssize_t mpcore_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) | 185 | static ssize_t mpcore_wdt_write(struct file *file, const char *data, |
186 | size_t len, loff_t *ppos) | ||
179 | { | 187 | { |
180 | struct mpcore_wdt *wdt = file->private_data; | 188 | struct mpcore_wdt *wdt = file->private_data; |
181 | 189 | ||
@@ -210,8 +218,8 @@ static struct watchdog_info ident = { | |||
210 | .identity = "MPcore Watchdog", | 218 | .identity = "MPcore Watchdog", |
211 | }; | 219 | }; |
212 | 220 | ||
213 | static int mpcore_wdt_ioctl(struct inode *inode, struct file *file, | 221 | static long mpcore_wdt_ioctl(struct file *file, unsigned int cmd, |
214 | unsigned int cmd, unsigned long arg) | 222 | unsigned long arg) |
215 | { | 223 | { |
216 | struct mpcore_wdt *wdt = file->private_data; | 224 | struct mpcore_wdt *wdt = file->private_data; |
217 | int ret; | 225 | int ret; |
@@ -301,7 +309,7 @@ static const struct file_operations mpcore_wdt_fops = { | |||
301 | .owner = THIS_MODULE, | 309 | .owner = THIS_MODULE, |
302 | .llseek = no_llseek, | 310 | .llseek = no_llseek, |
303 | .write = mpcore_wdt_write, | 311 | .write = mpcore_wdt_write, |
304 | .ioctl = mpcore_wdt_ioctl, | 312 | .unlocked_ioctl = mpcore_wdt_ioctl, |
305 | .open = mpcore_wdt_open, | 313 | .open = mpcore_wdt_open, |
306 | .release = mpcore_wdt_release, | 314 | .release = mpcore_wdt_release, |
307 | }; | 315 | }; |
@@ -349,14 +357,17 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) | |||
349 | mpcore_wdt_miscdev.parent = &dev->dev; | 357 | mpcore_wdt_miscdev.parent = &dev->dev; |
350 | ret = misc_register(&mpcore_wdt_miscdev); | 358 | ret = misc_register(&mpcore_wdt_miscdev); |
351 | if (ret) { | 359 | if (ret) { |
352 | dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n", | 360 | dev_printk(KERN_ERR, _dev, |
353 | WATCHDOG_MINOR, ret); | 361 | "cannot register miscdev on minor=%d (err=%d)\n", |
362 | WATCHDOG_MINOR, ret); | ||
354 | goto err_misc; | 363 | goto err_misc; |
355 | } | 364 | } |
356 | 365 | ||
357 | ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, "mpcore_wdt", wdt); | 366 | ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, |
367 | "mpcore_wdt", wdt); | ||
358 | if (ret) { | 368 | if (ret) { |
359 | dev_printk(KERN_ERR, _dev, "cannot register IRQ%d for watchdog\n", wdt->irq); | 369 | dev_printk(KERN_ERR, _dev, |
370 | "cannot register IRQ%d for watchdog\n", wdt->irq); | ||
360 | goto err_irq; | 371 | goto err_irq; |
361 | } | 372 | } |
362 | 373 | ||
@@ -415,7 +426,7 @@ static int __init mpcore_wdt_init(void) | |||
415 | */ | 426 | */ |
416 | if (mpcore_wdt_set_heartbeat(mpcore_margin)) { | 427 | if (mpcore_wdt_set_heartbeat(mpcore_margin)) { |
417 | mpcore_wdt_set_heartbeat(TIMER_MARGIN); | 428 | mpcore_wdt_set_heartbeat(TIMER_MARGIN); |
418 | printk(KERN_INFO "mpcore_margin value must be 0<mpcore_margin<65536, using %d\n", | 429 | printk(KERN_INFO "mpcore_margin value must be 0 < mpcore_margin < 65536, using %d\n", |
419 | TIMER_MARGIN); | 430 | TIMER_MARGIN); |
420 | } | 431 | } |
421 | 432 | ||