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 | { | 
