diff options
Diffstat (limited to 'drivers/s390/char/vmwatchdog.c')
-rw-r--r-- | drivers/s390/char/vmwatchdog.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c index f2bc287b69e4..e13508c98b1a 100644 --- a/drivers/s390/char/vmwatchdog.c +++ b/drivers/s390/char/vmwatchdog.c | |||
@@ -17,9 +17,9 @@ | |||
17 | #include <linux/miscdevice.h> | 17 | #include <linux/miscdevice.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/moduleparam.h> | 19 | #include <linux/moduleparam.h> |
20 | #include <linux/slab.h> | ||
20 | #include <linux/suspend.h> | 21 | #include <linux/suspend.h> |
21 | #include <linux/watchdog.h> | 22 | #include <linux/watchdog.h> |
22 | #include <linux/smp_lock.h> | ||
23 | 23 | ||
24 | #include <asm/ebcdic.h> | 24 | #include <asm/ebcdic.h> |
25 | #include <asm/io.h> | 25 | #include <asm/io.h> |
@@ -49,6 +49,8 @@ static unsigned int vmwdt_interval = 60; | |||
49 | static unsigned long vmwdt_is_open; | 49 | static unsigned long vmwdt_is_open; |
50 | static int vmwdt_expect_close; | 50 | static int vmwdt_expect_close; |
51 | 51 | ||
52 | static DEFINE_MUTEX(vmwdt_mutex); | ||
53 | |||
52 | #define VMWDT_OPEN 0 /* devnode is open or suspend in progress */ | 54 | #define VMWDT_OPEN 0 /* devnode is open or suspend in progress */ |
53 | #define VMWDT_RUNNING 1 /* The watchdog is armed */ | 55 | #define VMWDT_RUNNING 1 /* The watchdog is armed */ |
54 | 56 | ||
@@ -133,15 +135,11 @@ static int __init vmwdt_probe(void) | |||
133 | static int vmwdt_open(struct inode *i, struct file *f) | 135 | static int vmwdt_open(struct inode *i, struct file *f) |
134 | { | 136 | { |
135 | int ret; | 137 | int ret; |
136 | lock_kernel(); | 138 | if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) |
137 | if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) { | ||
138 | unlock_kernel(); | ||
139 | return -EBUSY; | 139 | return -EBUSY; |
140 | } | ||
141 | ret = vmwdt_keepalive(); | 140 | ret = vmwdt_keepalive(); |
142 | if (ret) | 141 | if (ret) |
143 | clear_bit(VMWDT_OPEN, &vmwdt_is_open); | 142 | clear_bit(VMWDT_OPEN, &vmwdt_is_open); |
144 | unlock_kernel(); | ||
145 | return ret ? ret : nonseekable_open(i, f); | 143 | return ret ? ret : nonseekable_open(i, f); |
146 | } | 144 | } |
147 | 145 | ||
@@ -160,8 +158,7 @@ static struct watchdog_info vmwdt_info = { | |||
160 | .identity = "z/VM Watchdog Timer", | 158 | .identity = "z/VM Watchdog Timer", |
161 | }; | 159 | }; |
162 | 160 | ||
163 | static int vmwdt_ioctl(struct inode *i, struct file *f, | 161 | static int __vmwdt_ioctl(unsigned int cmd, unsigned long arg) |
164 | unsigned int cmd, unsigned long arg) | ||
165 | { | 162 | { |
166 | switch (cmd) { | 163 | switch (cmd) { |
167 | case WDIOC_GETSUPPORT: | 164 | case WDIOC_GETSUPPORT: |
@@ -205,10 +202,19 @@ static int vmwdt_ioctl(struct inode *i, struct file *f, | |||
205 | case WDIOC_KEEPALIVE: | 202 | case WDIOC_KEEPALIVE: |
206 | return vmwdt_keepalive(); | 203 | return vmwdt_keepalive(); |
207 | } | 204 | } |
208 | |||
209 | return -EINVAL; | 205 | return -EINVAL; |
210 | } | 206 | } |
211 | 207 | ||
208 | static long vmwdt_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | ||
209 | { | ||
210 | int rc; | ||
211 | |||
212 | mutex_lock(&vmwdt_mutex); | ||
213 | rc = __vmwdt_ioctl(cmd, arg); | ||
214 | mutex_unlock(&vmwdt_mutex); | ||
215 | return (long) rc; | ||
216 | } | ||
217 | |||
212 | static ssize_t vmwdt_write(struct file *f, const char __user *buf, | 218 | static ssize_t vmwdt_write(struct file *f, const char __user *buf, |
213 | size_t count, loff_t *ppos) | 219 | size_t count, loff_t *ppos) |
214 | { | 220 | { |
@@ -288,7 +294,7 @@ static struct notifier_block vmwdt_power_notifier = { | |||
288 | static const struct file_operations vmwdt_fops = { | 294 | static const struct file_operations vmwdt_fops = { |
289 | .open = &vmwdt_open, | 295 | .open = &vmwdt_open, |
290 | .release = &vmwdt_close, | 296 | .release = &vmwdt_close, |
291 | .ioctl = &vmwdt_ioctl, | 297 | .unlocked_ioctl = &vmwdt_ioctl, |
292 | .write = &vmwdt_write, | 298 | .write = &vmwdt_write, |
293 | .owner = THIS_MODULE, | 299 | .owner = THIS_MODULE, |
294 | }; | 300 | }; |
@@ -309,6 +315,10 @@ static int __init vmwdt_init(void) | |||
309 | ret = register_pm_notifier(&vmwdt_power_notifier); | 315 | ret = register_pm_notifier(&vmwdt_power_notifier); |
310 | if (ret) | 316 | if (ret) |
311 | return ret; | 317 | return ret; |
318 | /* | ||
319 | * misc_register() has to be the last action in module_init(), because | ||
320 | * file operations will be available right after this. | ||
321 | */ | ||
312 | ret = misc_register(&vmwdt_dev); | 322 | ret = misc_register(&vmwdt_dev); |
313 | if (ret) { | 323 | if (ret) { |
314 | unregister_pm_notifier(&vmwdt_power_notifier); | 324 | unregister_pm_notifier(&vmwdt_power_notifier); |