diff options
-rw-r--r-- | drivers/char/watchdog/rm9k_wdt.c | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index 22aab8703eda..ec3909371c21 100644 --- a/drivers/char/watchdog/rm9k_wdt.c +++ b/drivers/char/watchdog/rm9k_wdt.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | #include <linux/reboot.h> | 28 | #include <linux/reboot.h> |
29 | #include <linux/notifier.h> | ||
29 | #include <linux/miscdevice.h> | 30 | #include <linux/miscdevice.h> |
30 | #include <linux/watchdog.h> | 31 | #include <linux/watchdog.h> |
31 | #include <asm/io.h> | 32 | #include <asm/io.h> |
@@ -47,13 +48,15 @@ | |||
47 | 48 | ||
48 | /* Function prototypes */ | 49 | /* Function prototypes */ |
49 | static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *); | 50 | static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *); |
51 | static void wdt_gpi_start(void); | ||
52 | static void wdt_gpi_stop(void); | ||
50 | static void wdt_gpi_set_timeout(unsigned int); | 53 | static void wdt_gpi_set_timeout(unsigned int); |
51 | static int wdt_gpi_open(struct inode *, struct file *); | 54 | static int wdt_gpi_open(struct inode *, struct file *); |
52 | static int wdt_gpi_release(struct inode *, struct file *); | 55 | static int wdt_gpi_release(struct inode *, struct file *); |
53 | static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, loff_t *); | 56 | static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, loff_t *); |
54 | static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); | 57 | static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); |
55 | static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); | ||
56 | static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); | 58 | static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); |
59 | static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); | ||
57 | static int __init wdt_gpi_probe(struct device *); | 60 | static int __init wdt_gpi_probe(struct device *); |
58 | static int __exit wdt_gpi_remove(struct device *); | 61 | static int __exit wdt_gpi_remove(struct device *); |
59 | 62 | ||
@@ -61,7 +64,7 @@ static int __exit wdt_gpi_remove(struct device *); | |||
61 | static const char wdt_gpi_name[] = "wdt_gpi"; | 64 | static const char wdt_gpi_name[] = "wdt_gpi"; |
62 | static atomic_t opencnt; | 65 | static atomic_t opencnt; |
63 | static int expect_close; | 66 | static int expect_close; |
64 | static int locked = 0; | 67 | static int locked; |
65 | 68 | ||
66 | 69 | ||
67 | /* These are set from device resources */ | 70 | /* These are set from device resources */ |
@@ -82,7 +85,7 @@ static unsigned long flagaddr = 0xbffdc104; | |||
82 | module_param(flagaddr, ulong, 0444); | 85 | module_param(flagaddr, ulong, 0444); |
83 | MODULE_PARM_DESC(flagaddr, "Address to write to boot flags to"); | 86 | MODULE_PARM_DESC(flagaddr, "Address to write to boot flags to"); |
84 | 87 | ||
85 | static int powercycle = 0; | 88 | static int powercycle; |
86 | module_param(powercycle, bool, 0444); | 89 | module_param(powercycle, bool, 0444); |
87 | MODULE_PARM_DESC(powercycle, "Cycle power if watchdog expires"); | 90 | MODULE_PARM_DESC(powercycle, "Cycle power if watchdog expires"); |
88 | 91 | ||
@@ -99,7 +102,7 @@ static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt, struct pt_regs *regs) | |||
99 | __raw_writel(0x1, wd_regs + 0x0008); | 102 | __raw_writel(0x1, wd_regs + 0x0008); |
100 | 103 | ||
101 | 104 | ||
102 | printk(KERN_WARNING "%s: watchdog expired - resetting system\n", | 105 | printk(KERN_CRIT "%s: watchdog expired - resetting system\n", |
103 | wdt_gpi_name); | 106 | wdt_gpi_name); |
104 | 107 | ||
105 | *(volatile char *) flagaddr |= 0x01; | 108 | *(volatile char *) flagaddr |= 0x01; |
@@ -155,11 +158,11 @@ static void wdt_gpi_set_timeout(unsigned int to) | |||
155 | 158 | ||
156 | 159 | ||
157 | /* /dev/watchdog operations */ | 160 | /* /dev/watchdog operations */ |
158 | static int wdt_gpi_open(struct inode *i, struct file *f) | 161 | static int wdt_gpi_open(struct inode *inode, struct file *file) |
159 | { | 162 | { |
160 | int res; | 163 | int res; |
161 | 164 | ||
162 | if (unlikely(0 > atomic_dec_if_positive(&opencnt))) | 165 | if (unlikely(atomic_dec_if_positive(&opencnt) < 0)) |
163 | return -EBUSY; | 166 | return -EBUSY; |
164 | 167 | ||
165 | expect_close = 0; | 168 | expect_close = 0; |
@@ -179,13 +182,13 @@ static int wdt_gpi_open(struct inode *i, struct file *f) | |||
179 | 182 | ||
180 | printk(KERN_INFO "%s: watchdog started, timeout = %u seconds\n", | 183 | printk(KERN_INFO "%s: watchdog started, timeout = %u seconds\n", |
181 | wdt_gpi_name, timeout); | 184 | wdt_gpi_name, timeout); |
182 | return 0; | 185 | return nonseekable_open(inode, file); |
183 | } | 186 | } |
184 | 187 | ||
185 | static int wdt_gpi_release(struct inode *i, struct file *f) | 188 | static int wdt_gpi_release(struct inode *inode, struct file *file) |
186 | { | 189 | { |
187 | if (nowayout) { | 190 | if (nowayout) { |
188 | printk(KERN_NOTICE "%s: no way out - watchdog left running\n", | 191 | printk(KERN_INFO "%s: no way out - watchdog left running\n", |
189 | wdt_gpi_name); | 192 | wdt_gpi_name); |
190 | __module_get(THIS_MODULE); | 193 | __module_get(THIS_MODULE); |
191 | locked = 1; | 194 | locked = 1; |
@@ -195,7 +198,7 @@ static int wdt_gpi_release(struct inode *i, struct file *f) | |||
195 | free_irq(wd_irq, &miscdev); | 198 | free_irq(wd_irq, &miscdev); |
196 | printk(KERN_INFO "%s: watchdog stopped\n", wdt_gpi_name); | 199 | printk(KERN_INFO "%s: watchdog stopped\n", wdt_gpi_name); |
197 | } else { | 200 | } else { |
198 | printk(KERN_NOTICE "%s: unexpected close() -" | 201 | printk(KERN_CRIT "%s: unexpected close() -" |
199 | " watchdog left running\n", | 202 | " watchdog left running\n", |
200 | wdt_gpi_name); | 203 | wdt_gpi_name); |
201 | wdt_gpi_set_timeout(timeout); | 204 | wdt_gpi_set_timeout(timeout); |
@@ -224,6 +227,7 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
224 | long res = -ENOTTY; | 227 | long res = -ENOTTY; |
225 | const long size = _IOC_SIZE(cmd); | 228 | const long size = _IOC_SIZE(cmd); |
226 | int stat; | 229 | int stat; |
230 | void __user *argp = (void __user *)arg; | ||
227 | static struct watchdog_info wdinfo = { | 231 | static struct watchdog_info wdinfo = { |
228 | .identity = "RM9xxx/GPI watchdog", | 232 | .identity = "RM9xxx/GPI watchdog", |
229 | .firmware_version = 0, | 233 | .firmware_version = 0, |
@@ -248,8 +252,7 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
248 | wdinfo.options = nowayout ? | 252 | wdinfo.options = nowayout ? |
249 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING : | 253 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING : |
250 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE; | 254 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE; |
251 | res = __copy_to_user((void __user *)arg, &wdinfo, size) ? | 255 | res = __copy_to_user(argp, &wdinfo, size) ? -EFAULT : size; |
252 | -EFAULT : size; | ||
253 | break; | 256 | break; |
254 | 257 | ||
255 | case WDIOC_GETSTATUS: | 258 | case WDIOC_GETSTATUS: |
@@ -258,7 +261,7 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
258 | case WDIOC_GETBOOTSTATUS: | 261 | case WDIOC_GETBOOTSTATUS: |
259 | stat = (*(volatile char *) flagaddr & 0x01) | 262 | stat = (*(volatile char *) flagaddr & 0x01) |
260 | ? WDIOF_CARDRESET : 0; | 263 | ? WDIOF_CARDRESET : 0; |
261 | res = __copy_to_user((void __user *)arg, &stat, size) ? | 264 | res = __copy_to_user(argp, &stat, size) ? |
262 | -EFAULT : size; | 265 | -EFAULT : size; |
263 | break; | 266 | break; |
264 | 267 | ||
@@ -273,24 +276,23 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
273 | case WDIOC_SETTIMEOUT: | 276 | case WDIOC_SETTIMEOUT: |
274 | { | 277 | { |
275 | int val; | 278 | int val; |
276 | if (unlikely(__copy_from_user(&val, (const void __user *) arg, | 279 | if (unlikely(__copy_from_user(&val, argp, size))) { |
277 | size))) { | ||
278 | res = -EFAULT; | 280 | res = -EFAULT; |
279 | break; | 281 | break; |
280 | } | 282 | } |
281 | 283 | ||
282 | if (val > 32) | 284 | if (val > MAX_TIMEOUT_SECONDS) |
283 | val = 32; | 285 | val = MAX_TIMEOUT_SECONDS; |
284 | timeout = val; | 286 | timeout = val; |
285 | wdt_gpi_set_timeout(val); | 287 | wdt_gpi_set_timeout(val); |
286 | res = size; | 288 | res = size; |
287 | printk("%s: timeout set to %u seconds\n", | 289 | printk(KERN_INFO "%s: timeout set to %u seconds\n", |
288 | wdt_gpi_name, timeout); | 290 | wdt_gpi_name, timeout); |
289 | } | 291 | } |
290 | break; | 292 | break; |
291 | 293 | ||
292 | case WDIOC_GETTIMEOUT: | 294 | case WDIOC_GETTIMEOUT: |
293 | res = __copy_to_user((void __user *) arg, &timeout, size) ? | 295 | res = __copy_to_user(argp, &timeout, size) ? |
294 | -EFAULT : size; | 296 | -EFAULT : size; |
295 | break; | 297 | break; |
296 | } | 298 | } |
@@ -299,7 +301,7 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
299 | } | 301 | } |
300 | 302 | ||
301 | 303 | ||
302 | /* Shutdown notifier*/ | 304 | /* Shutdown notifier */ |
303 | static int | 305 | static int |
304 | wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) | 306 | wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) |
305 | { | 307 | { |