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", |