diff options
| -rw-r--r-- | drivers/char/watchdog/mv64x60_wdt.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c index 009b9a2c6efa..e07007543d09 100644 --- a/drivers/char/watchdog/mv64x60_wdt.c +++ b/drivers/char/watchdog/mv64x60_wdt.c | |||
| @@ -44,6 +44,7 @@ static int wdt_status; | |||
| 44 | static void __iomem *mv64x60_wdt_regs; | 44 | static void __iomem *mv64x60_wdt_regs; |
| 45 | static int mv64x60_wdt_timeout; | 45 | static int mv64x60_wdt_timeout; |
| 46 | static unsigned int bus_clk; | 46 | static unsigned int bus_clk; |
| 47 | static char expect_close; | ||
| 47 | 48 | ||
| 48 | static int nowayout = WATCHDOG_NOWAYOUT; | 49 | static int nowayout = WATCHDOG_NOWAYOUT; |
| 49 | module_param(nowayout, int, 0); | 50 | module_param(nowayout, int, 0); |
| @@ -115,10 +116,14 @@ static int mv64x60_wdt_open(struct inode *inode, struct file *file) | |||
| 115 | 116 | ||
| 116 | static int mv64x60_wdt_release(struct inode *inode, struct file *file) | 117 | static int mv64x60_wdt_release(struct inode *inode, struct file *file) |
| 117 | { | 118 | { |
| 118 | mv64x60_wdt_service(); | 119 | if (expect_close == 42) |
| 119 | |||
| 120 | if (!nowayout) | ||
| 121 | mv64x60_wdt_handler_disable(); | 120 | mv64x60_wdt_handler_disable(); |
| 121 | else { | ||
| 122 | printk(KERN_CRIT | ||
| 123 | "mv64x60_wdt: unexpected close, not stopping timer!\n"); | ||
| 124 | mv64x60_wdt_service(); | ||
| 125 | } | ||
| 126 | expect_close = 0; | ||
| 122 | 127 | ||
| 123 | clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags); | 128 | clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags); |
| 124 | 129 | ||
| @@ -128,8 +133,22 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file) | |||
| 128 | static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, | 133 | static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, |
| 129 | size_t len, loff_t * ppos) | 134 | size_t len, loff_t * ppos) |
| 130 | { | 135 | { |
| 131 | if (len) | 136 | if (len) { |
| 137 | if (!nowayout) { | ||
| 138 | size_t i; | ||
| 139 | |||
| 140 | expect_close = 0; | ||
| 141 | |||
| 142 | for (i = 0; i != len; i++) { | ||
| 143 | char c; | ||
| 144 | if(get_user(c, data + i)) | ||
| 145 | return -EFAULT; | ||
| 146 | if (c == 'V') | ||
| 147 | expect_close = 42; | ||
| 148 | } | ||
| 149 | } | ||
| 132 | mv64x60_wdt_service(); | 150 | mv64x60_wdt_service(); |
| 151 | } | ||
| 133 | 152 | ||
| 134 | return len; | 153 | return len; |
| 135 | } | 154 | } |
| @@ -142,6 +161,7 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, | |||
| 142 | void __user *argp = (void __user *)arg; | 161 | void __user *argp = (void __user *)arg; |
| 143 | static struct watchdog_info info = { | 162 | static struct watchdog_info info = { |
| 144 | .options = WDIOF_SETTIMEOUT | | 163 | .options = WDIOF_SETTIMEOUT | |
| 164 | WDIOF_MAGICCLOSE | | ||
| 145 | WDIOF_KEEPALIVEPING, | 165 | WDIOF_KEEPALIVEPING, |
| 146 | .firmware_version = 0, | 166 | .firmware_version = 0, |
| 147 | .identity = "MV64x60 watchdog", | 167 | .identity = "MV64x60 watchdog", |
