aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/con3215.c1
-rw-r--r--drivers/s390/char/con3270.c1
-rw-r--r--drivers/s390/char/fs3270.c10
-rw-r--r--drivers/s390/char/monreader.c8
-rw-r--r--drivers/s390/char/monwriter.c7
-rw-r--r--drivers/s390/char/sclp_cmd.c1
-rw-r--r--drivers/s390/char/tape.h9
-rw-r--r--drivers/s390/char/tape_34xx.c8
-rw-r--r--drivers/s390/char/tape_3590.c2
-rw-r--r--drivers/s390/char/tape_block.c17
-rw-r--r--drivers/s390/char/tape_char.c54
-rw-r--r--drivers/s390/char/tape_core.c65
-rw-r--r--drivers/s390/char/tape_proc.c2
-rw-r--r--drivers/s390/char/tty3270.c20
-rw-r--r--drivers/s390/char/vmlogrdr.c8
-rw-r--r--drivers/s390/char/vmur.c3
-rw-r--r--drivers/s390/char/vmwatchdog.c29
17 files changed, 137 insertions, 108 deletions
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 21639d6c996f..9d61683b5633 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -857,7 +857,6 @@ static struct console con3215 = {
857 857
858/* 858/*
859 * 3215 console initialization code called from console_init(). 859 * 3215 console initialization code called from console_init().
860 * NOTE: This is called before kmalloc is available.
861 */ 860 */
862static int __init con3215_init(void) 861static int __init con3215_init(void)
863{ 862{
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index bb838bdf829d..6bca81aea396 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -572,7 +572,6 @@ static struct console con3270 = {
572 572
573/* 573/*
574 * 3270 console initialization code called from console_init(). 574 * 3270 console initialization code called from console_init().
575 * NOTE: This is called before kmalloc is available.
576 */ 575 */
577static int __init 576static int __init
578con3270_init(void) 577con3270_init(void)
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 097d3846a828..d449063c30fe 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -38,6 +38,8 @@ struct fs3270 {
38 size_t rdbuf_size; /* size of data returned by RDBUF */ 38 size_t rdbuf_size; /* size of data returned by RDBUF */
39}; 39};
40 40
41static DEFINE_MUTEX(fs3270_mutex);
42
41static void 43static void
42fs3270_wake_up(struct raw3270_request *rq, void *data) 44fs3270_wake_up(struct raw3270_request *rq, void *data)
43{ 45{
@@ -328,7 +330,7 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
328 if (!fp) 330 if (!fp)
329 return -ENODEV; 331 return -ENODEV;
330 rc = 0; 332 rc = 0;
331 lock_kernel(); 333 mutex_lock(&fs3270_mutex);
332 switch (cmd) { 334 switch (cmd) {
333 case TUBICMD: 335 case TUBICMD:
334 fp->read_command = arg; 336 fp->read_command = arg;
@@ -354,7 +356,7 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
354 rc = -EFAULT; 356 rc = -EFAULT;
355 break; 357 break;
356 } 358 }
357 unlock_kernel(); 359 mutex_unlock(&fs3270_mutex);
358 return rc; 360 return rc;
359} 361}
360 362
@@ -437,7 +439,7 @@ fs3270_open(struct inode *inode, struct file *filp)
437 minor = tty->index + RAW3270_FIRSTMINOR; 439 minor = tty->index + RAW3270_FIRSTMINOR;
438 tty_kref_put(tty); 440 tty_kref_put(tty);
439 } 441 }
440 lock_kernel(); 442 mutex_lock(&fs3270_mutex);
441 /* Check if some other program is already using fullscreen mode. */ 443 /* Check if some other program is already using fullscreen mode. */
442 fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); 444 fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor);
443 if (!IS_ERR(fp)) { 445 if (!IS_ERR(fp)) {
@@ -478,7 +480,7 @@ fs3270_open(struct inode *inode, struct file *filp)
478 } 480 }
479 filp->private_data = fp; 481 filp->private_data = fp;
480out: 482out:
481 unlock_kernel(); 483 mutex_unlock(&fs3270_mutex);
482 return rc; 484 return rc;
483} 485}
484 486
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 66e21dd23154..60473f86e1f9 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -12,7 +12,6 @@
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/moduleparam.h> 13#include <linux/moduleparam.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/smp_lock.h>
16#include <linux/errno.h> 15#include <linux/errno.h>
17#include <linux/types.h> 16#include <linux/types.h>
18#include <linux/kernel.h> 17#include <linux/kernel.h>
@@ -283,7 +282,6 @@ static int mon_open(struct inode *inode, struct file *filp)
283 /* 282 /*
284 * only one user allowed 283 * only one user allowed
285 */ 284 */
286 lock_kernel();
287 rc = -EBUSY; 285 rc = -EBUSY;
288 if (test_and_set_bit(MON_IN_USE, &mon_in_use)) 286 if (test_and_set_bit(MON_IN_USE, &mon_in_use))
289 goto out; 287 goto out;
@@ -321,7 +319,6 @@ static int mon_open(struct inode *inode, struct file *filp)
321 } 319 }
322 filp->private_data = monpriv; 320 filp->private_data = monpriv;
323 dev_set_drvdata(monreader_device, monpriv); 321 dev_set_drvdata(monreader_device, monpriv);
324 unlock_kernel();
325 return nonseekable_open(inode, filp); 322 return nonseekable_open(inode, filp);
326 323
327out_path: 324out_path:
@@ -331,7 +328,6 @@ out_priv:
331out_use: 328out_use:
332 clear_bit(MON_IN_USE, &mon_in_use); 329 clear_bit(MON_IN_USE, &mon_in_use);
333out: 330out:
334 unlock_kernel();
335 return rc; 331 return rc;
336} 332}
337 333
@@ -607,6 +603,10 @@ static int __init mon_init(void)
607 } 603 }
608 dcss_mkname(mon_dcss_name, &user_data_connect[8]); 604 dcss_mkname(mon_dcss_name, &user_data_connect[8]);
609 605
606 /*
607 * misc_register() has to be the last action in module_init(), because
608 * file operations will be available right after this.
609 */
610 rc = misc_register(&mon_dev); 610 rc = misc_register(&mon_dev);
611 if (rc < 0 ) 611 if (rc < 0 )
612 goto out; 612 goto out;
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 66fb8eba93f4..6532ed8b4afa 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -13,7 +13,6 @@
13#include <linux/moduleparam.h> 13#include <linux/moduleparam.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/smp_lock.h>
17#include <linux/types.h> 16#include <linux/types.h>
18#include <linux/kernel.h> 17#include <linux/kernel.h>
19#include <linux/miscdevice.h> 18#include <linux/miscdevice.h>
@@ -185,13 +184,11 @@ static int monwrite_open(struct inode *inode, struct file *filp)
185 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); 184 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
186 if (!monpriv) 185 if (!monpriv)
187 return -ENOMEM; 186 return -ENOMEM;
188 lock_kernel();
189 INIT_LIST_HEAD(&monpriv->list); 187 INIT_LIST_HEAD(&monpriv->list);
190 monpriv->hdr_to_read = sizeof(monpriv->hdr); 188 monpriv->hdr_to_read = sizeof(monpriv->hdr);
191 mutex_init(&monpriv->thread_mutex); 189 mutex_init(&monpriv->thread_mutex);
192 filp->private_data = monpriv; 190 filp->private_data = monpriv;
193 list_add_tail(&monpriv->priv_list, &mon_priv_list); 191 list_add_tail(&monpriv->priv_list, &mon_priv_list);
194 unlock_kernel();
195 return nonseekable_open(inode, filp); 192 return nonseekable_open(inode, filp);
196} 193}
197 194
@@ -364,6 +361,10 @@ static int __init mon_init(void)
364 goto out_driver; 361 goto out_driver;
365 } 362 }
366 363
364 /*
365 * misc_register() has to be the last action in module_init(), because
366 * file operations will be available right after this.
367 */
367 rc = misc_register(&mon_dev); 368 rc = misc_register(&mon_dev);
368 if (rc) 369 if (rc)
369 goto out_device; 370 goto out_device;
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 5cc11c636d38..28b5afc129c3 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -84,6 +84,7 @@ static void __init sclp_read_info_early(void)
84 do { 84 do {
85 memset(sccb, 0, sizeof(*sccb)); 85 memset(sccb, 0, sizeof(*sccb));
86 sccb->header.length = sizeof(*sccb); 86 sccb->header.length = sizeof(*sccb);
87 sccb->header.function_code = 0x80;
87 sccb->header.control_mask[2] = 0x80; 88 sccb->header.control_mask[2] = 0x80;
88 rc = sclp_cmd_sync_early(commands[i], sccb); 89 rc = sclp_cmd_sync_early(commands[i], sccb);
89 } while (rc == -EBUSY); 90 } while (rc == -EBUSY);
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index a26333774701..7a242f073632 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -212,6 +212,9 @@ struct tape_device {
212 struct tape_class_device * nt; 212 struct tape_class_device * nt;
213 struct tape_class_device * rt; 213 struct tape_class_device * rt;
214 214
215 /* Device mutex to serialize tape commands. */
216 struct mutex mutex;
217
215 /* Device discipline information. */ 218 /* Device discipline information. */
216 struct tape_discipline * discipline; 219 struct tape_discipline * discipline;
217 void * discdata; 220 void * discdata;
@@ -292,9 +295,9 @@ extern int tape_generic_pm_suspend(struct ccw_device *);
292extern int tape_generic_probe(struct ccw_device *); 295extern int tape_generic_probe(struct ccw_device *);
293extern void tape_generic_remove(struct ccw_device *); 296extern void tape_generic_remove(struct ccw_device *);
294 297
295extern struct tape_device *tape_get_device(int devindex); 298extern struct tape_device *tape_find_device(int devindex);
296extern struct tape_device *tape_get_device_reference(struct tape_device *); 299extern struct tape_device *tape_get_device(struct tape_device *);
297extern struct tape_device *tape_put_device(struct tape_device *); 300extern void tape_put_device(struct tape_device *);
298 301
299/* Externals from tape_char.c */ 302/* Externals from tape_char.c */
300extern int tapechar_init(void); 303extern int tapechar_init(void);
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 2fe45ff77b75..3657fe103c27 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -113,16 +113,16 @@ tape_34xx_work_handler(struct work_struct *work)
113{ 113{
114 struct tape_34xx_work *p = 114 struct tape_34xx_work *p =
115 container_of(work, struct tape_34xx_work, work); 115 container_of(work, struct tape_34xx_work, work);
116 struct tape_device *device = p->device;
116 117
117 switch(p->op) { 118 switch(p->op) {
118 case TO_MSEN: 119 case TO_MSEN:
119 tape_34xx_medium_sense(p->device); 120 tape_34xx_medium_sense(device);
120 break; 121 break;
121 default: 122 default:
122 DBF_EVENT(3, "T34XX: internal error: unknown work\n"); 123 DBF_EVENT(3, "T34XX: internal error: unknown work\n");
123 } 124 }
124 125 tape_put_device(device);
125 p->device = tape_put_device(p->device);
126 kfree(p); 126 kfree(p);
127} 127}
128 128
@@ -136,7 +136,7 @@ tape_34xx_schedule_work(struct tape_device *device, enum tape_op op)
136 136
137 INIT_WORK(&p->work, tape_34xx_work_handler); 137 INIT_WORK(&p->work, tape_34xx_work_handler);
138 138
139 p->device = tape_get_device_reference(device); 139 p->device = tape_get_device(device);
140 p->op = op; 140 p->op = op;
141 141
142 schedule_work(&p->work); 142 schedule_work(&p->work);
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index e4cc3aae9162..0c72aadb8391 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -608,7 +608,7 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op)
608 608
609 INIT_WORK(&p->work, tape_3590_work_handler); 609 INIT_WORK(&p->work, tape_3590_work_handler);
610 610
611 p->device = tape_get_device_reference(device); 611 p->device = tape_get_device(device);
612 p->op = op; 612 p->op = op;
613 613
614 schedule_work(&p->work); 614 schedule_work(&p->work);
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 0c0705b91c28..4799cc2f73c3 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -54,7 +54,7 @@ static const struct block_device_operations tapeblock_fops = {
54 .owner = THIS_MODULE, 54 .owner = THIS_MODULE,
55 .open = tapeblock_open, 55 .open = tapeblock_open,
56 .release = tapeblock_release, 56 .release = tapeblock_release,
57 .locked_ioctl = tapeblock_ioctl, 57 .ioctl = tapeblock_ioctl,
58 .media_changed = tapeblock_medium_changed, 58 .media_changed = tapeblock_medium_changed,
59 .revalidate_disk = tapeblock_revalidate_disk, 59 .revalidate_disk = tapeblock_revalidate_disk,
60}; 60};
@@ -239,7 +239,7 @@ tapeblock_setup_device(struct tape_device * device)
239 disk->major = tapeblock_major; 239 disk->major = tapeblock_major;
240 disk->first_minor = device->first_minor; 240 disk->first_minor = device->first_minor;
241 disk->fops = &tapeblock_fops; 241 disk->fops = &tapeblock_fops;
242 disk->private_data = tape_get_device_reference(device); 242 disk->private_data = tape_get_device(device);
243 disk->queue = blkdat->request_queue; 243 disk->queue = blkdat->request_queue;
244 set_capacity(disk, 0); 244 set_capacity(disk, 0);
245 sprintf(disk->disk_name, "btibm%d", 245 sprintf(disk->disk_name, "btibm%d",
@@ -247,11 +247,11 @@ tapeblock_setup_device(struct tape_device * device)
247 247
248 blkdat->disk = disk; 248 blkdat->disk = disk;
249 blkdat->medium_changed = 1; 249 blkdat->medium_changed = 1;
250 blkdat->request_queue->queuedata = tape_get_device_reference(device); 250 blkdat->request_queue->queuedata = tape_get_device(device);
251 251
252 add_disk(disk); 252 add_disk(disk);
253 253
254 tape_get_device_reference(device); 254 tape_get_device(device);
255 INIT_WORK(&blkdat->requeue_task, tapeblock_requeue); 255 INIT_WORK(&blkdat->requeue_task, tapeblock_requeue);
256 256
257 return 0; 257 return 0;
@@ -274,13 +274,14 @@ tapeblock_cleanup_device(struct tape_device *device)
274 } 274 }
275 275
276 del_gendisk(device->blk_data.disk); 276 del_gendisk(device->blk_data.disk);
277 device->blk_data.disk->private_data = 277 device->blk_data.disk->private_data = NULL;
278 tape_put_device(device->blk_data.disk->private_data); 278 tape_put_device(device);
279 put_disk(device->blk_data.disk); 279 put_disk(device->blk_data.disk);
280 280
281 device->blk_data.disk = NULL; 281 device->blk_data.disk = NULL;
282cleanup_queue: 282cleanup_queue:
283 device->blk_data.request_queue->queuedata = tape_put_device(device); 283 device->blk_data.request_queue->queuedata = NULL;
284 tape_put_device(device);
284 285
285 blk_cleanup_queue(device->blk_data.request_queue); 286 blk_cleanup_queue(device->blk_data.request_queue);
286 device->blk_data.request_queue = NULL; 287 device->blk_data.request_queue = NULL;
@@ -363,7 +364,7 @@ tapeblock_open(struct block_device *bdev, fmode_t mode)
363 struct tape_device * device; 364 struct tape_device * device;
364 int rc; 365 int rc;
365 366
366 device = tape_get_device_reference(disk->private_data); 367 device = tape_get_device(disk->private_data);
367 368
368 if (device->required_tapemarks) { 369 if (device->required_tapemarks) {
369 DBF_EVENT(2, "TBLOCK: missing tapemarks\n"); 370 DBF_EVENT(2, "TBLOCK: missing tapemarks\n");
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 31566c55adfe..23d773a0d113 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -33,8 +33,7 @@ static ssize_t tapechar_read(struct file *, char __user *, size_t, loff_t *);
33static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *); 33static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *);
34static int tapechar_open(struct inode *,struct file *); 34static int tapechar_open(struct inode *,struct file *);
35static int tapechar_release(struct inode *,struct file *); 35static int tapechar_release(struct inode *,struct file *);
36static int tapechar_ioctl(struct inode *, struct file *, unsigned int, 36static long tapechar_ioctl(struct file *, unsigned int, unsigned long);
37 unsigned long);
38static long tapechar_compat_ioctl(struct file *, unsigned int, 37static long tapechar_compat_ioctl(struct file *, unsigned int,
39 unsigned long); 38 unsigned long);
40 39
@@ -43,7 +42,7 @@ static const struct file_operations tape_fops =
43 .owner = THIS_MODULE, 42 .owner = THIS_MODULE,
44 .read = tapechar_read, 43 .read = tapechar_read,
45 .write = tapechar_write, 44 .write = tapechar_write,
46 .ioctl = tapechar_ioctl, 45 .unlocked_ioctl = tapechar_ioctl,
47 .compat_ioctl = tapechar_compat_ioctl, 46 .compat_ioctl = tapechar_compat_ioctl,
48 .open = tapechar_open, 47 .open = tapechar_open,
49 .release = tapechar_release, 48 .release = tapechar_release,
@@ -170,7 +169,6 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
170 if (rc == 0) { 169 if (rc == 0) {
171 rc = block_size - request->rescnt; 170 rc = block_size - request->rescnt;
172 DBF_EVENT(6, "TCHAR:rbytes: %x\n", rc); 171 DBF_EVENT(6, "TCHAR:rbytes: %x\n", rc);
173 filp->f_pos += rc;
174 /* Copy data from idal buffer to user space. */ 172 /* Copy data from idal buffer to user space. */
175 if (idal_buffer_to_user(device->char_data.idal_buf, 173 if (idal_buffer_to_user(device->char_data.idal_buf,
176 data, rc) != 0) 174 data, rc) != 0)
@@ -238,7 +236,6 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t
238 break; 236 break;
239 DBF_EVENT(6, "TCHAR:wbytes: %lx\n", 237 DBF_EVENT(6, "TCHAR:wbytes: %lx\n",
240 block_size - request->rescnt); 238 block_size - request->rescnt);
241 filp->f_pos += block_size - request->rescnt;
242 written += block_size - request->rescnt; 239 written += block_size - request->rescnt;
243 if (request->rescnt != 0) 240 if (request->rescnt != 0)
244 break; 241 break;
@@ -286,26 +283,20 @@ tapechar_open (struct inode *inode, struct file *filp)
286 if (imajor(filp->f_path.dentry->d_inode) != tapechar_major) 283 if (imajor(filp->f_path.dentry->d_inode) != tapechar_major)
287 return -ENODEV; 284 return -ENODEV;
288 285
289 lock_kernel();
290 minor = iminor(filp->f_path.dentry->d_inode); 286 minor = iminor(filp->f_path.dentry->d_inode);
291 device = tape_get_device(minor / TAPE_MINORS_PER_DEV); 287 device = tape_find_device(minor / TAPE_MINORS_PER_DEV);
292 if (IS_ERR(device)) { 288 if (IS_ERR(device)) {
293 DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n"); 289 DBF_EVENT(3, "TCHAR:open: tape_find_device() failed\n");
294 rc = PTR_ERR(device); 290 return PTR_ERR(device);
295 goto out;
296 } 291 }
297 292
298
299 rc = tape_open(device); 293 rc = tape_open(device);
300 if (rc == 0) { 294 if (rc == 0) {
301 filp->private_data = device; 295 filp->private_data = device;
302 rc = nonseekable_open(inode, filp); 296 nonseekable_open(inode, filp);
303 } 297 } else
304 else
305 tape_put_device(device); 298 tape_put_device(device);
306 299
307out:
308 unlock_kernel();
309 return rc; 300 return rc;
310} 301}
311 302
@@ -342,7 +333,8 @@ tapechar_release(struct inode *inode, struct file *filp)
342 device->char_data.idal_buf = NULL; 333 device->char_data.idal_buf = NULL;
343 } 334 }
344 tape_release(device); 335 tape_release(device);
345 filp->private_data = tape_put_device(device); 336 filp->private_data = NULL;
337 tape_put_device(device);
346 338
347 return 0; 339 return 0;
348} 340}
@@ -351,16 +343,11 @@ tapechar_release(struct inode *inode, struct file *filp)
351 * Tape device io controls. 343 * Tape device io controls.
352 */ 344 */
353static int 345static int
354tapechar_ioctl(struct inode *inp, struct file *filp, 346__tapechar_ioctl(struct tape_device *device,
355 unsigned int no, unsigned long data) 347 unsigned int no, unsigned long data)
356{ 348{
357 struct tape_device *device;
358 int rc; 349 int rc;
359 350
360 DBF_EVENT(6, "TCHAR:ioct\n");
361
362 device = (struct tape_device *) filp->private_data;
363
364 if (no == MTIOCTOP) { 351 if (no == MTIOCTOP) {
365 struct mtop op; 352 struct mtop op;
366 353
@@ -453,15 +440,30 @@ tapechar_ioctl(struct inode *inp, struct file *filp,
453} 440}
454 441
455static long 442static long
443tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data)
444{
445 struct tape_device *device;
446 long rc;
447
448 DBF_EVENT(6, "TCHAR:ioct\n");
449
450 device = (struct tape_device *) filp->private_data;
451 mutex_lock(&device->mutex);
452 rc = __tapechar_ioctl(device, no, data);
453 mutex_unlock(&device->mutex);
454 return rc;
455}
456
457static long
456tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) 458tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
457{ 459{
458 struct tape_device *device = filp->private_data; 460 struct tape_device *device = filp->private_data;
459 int rval = -ENOIOCTLCMD; 461 int rval = -ENOIOCTLCMD;
460 462
461 if (device->discipline->ioctl_fn) { 463 if (device->discipline->ioctl_fn) {
462 lock_kernel(); 464 mutex_lock(&device->mutex);
463 rval = device->discipline->ioctl_fn(device, no, data); 465 rval = device->discipline->ioctl_fn(device, no, data);
464 unlock_kernel(); 466 mutex_unlock(&device->mutex);
465 if (rval == -EINVAL) 467 if (rval == -EINVAL)
466 rval = -ENOIOCTLCMD; 468 rval = -ENOIOCTLCMD;
467 } 469 }
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 5cd31e071647..f5d6802dc5da 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -492,6 +492,7 @@ tape_alloc_device(void)
492 kfree(device); 492 kfree(device);
493 return ERR_PTR(-ENOMEM); 493 return ERR_PTR(-ENOMEM);
494 } 494 }
495 mutex_init(&device->mutex);
495 INIT_LIST_HEAD(&device->req_queue); 496 INIT_LIST_HEAD(&device->req_queue);
496 INIT_LIST_HEAD(&device->node); 497 INIT_LIST_HEAD(&device->node);
497 init_waitqueue_head(&device->state_change_wq); 498 init_waitqueue_head(&device->state_change_wq);
@@ -511,11 +512,12 @@ tape_alloc_device(void)
511 * increment the reference count. 512 * increment the reference count.
512 */ 513 */
513struct tape_device * 514struct tape_device *
514tape_get_device_reference(struct tape_device *device) 515tape_get_device(struct tape_device *device)
515{ 516{
516 DBF_EVENT(4, "tape_get_device_reference(%p) = %i\n", device, 517 int count;
517 atomic_inc_return(&device->ref_count));
518 518
519 count = atomic_inc_return(&device->ref_count);
520 DBF_EVENT(4, "tape_get_device(%p) = %i\n", device, count);
519 return device; 521 return device;
520} 522}
521 523
@@ -525,32 +527,25 @@ tape_get_device_reference(struct tape_device *device)
525 * The function returns a NULL pointer to be used by the caller 527 * The function returns a NULL pointer to be used by the caller
526 * for clearing reference pointers. 528 * for clearing reference pointers.
527 */ 529 */
528struct tape_device * 530void
529tape_put_device(struct tape_device *device) 531tape_put_device(struct tape_device *device)
530{ 532{
531 int remain; 533 int count;
532 534
533 remain = atomic_dec_return(&device->ref_count); 535 count = atomic_dec_return(&device->ref_count);
534 if (remain > 0) { 536 DBF_EVENT(4, "tape_put_device(%p) -> %i\n", device, count);
535 DBF_EVENT(4, "tape_put_device(%p) -> %i\n", device, remain); 537 BUG_ON(count < 0);
536 } else { 538 if (count == 0) {
537 if (remain < 0) { 539 kfree(device->modeset_byte);
538 DBF_EVENT(4, "put device without reference\n"); 540 kfree(device);
539 } else {
540 DBF_EVENT(4, "tape_free_device(%p)\n", device);
541 kfree(device->modeset_byte);
542 kfree(device);
543 }
544 } 541 }
545
546 return NULL;
547} 542}
548 543
549/* 544/*
550 * Find tape device by a device index. 545 * Find tape device by a device index.
551 */ 546 */
552struct tape_device * 547struct tape_device *
553tape_get_device(int devindex) 548tape_find_device(int devindex)
554{ 549{
555 struct tape_device *device, *tmp; 550 struct tape_device *device, *tmp;
556 551
@@ -558,7 +553,7 @@ tape_get_device(int devindex)
558 read_lock(&tape_device_lock); 553 read_lock(&tape_device_lock);
559 list_for_each_entry(tmp, &tape_device_list, node) { 554 list_for_each_entry(tmp, &tape_device_list, node) {
560 if (tmp->first_minor / TAPE_MINORS_PER_DEV == devindex) { 555 if (tmp->first_minor / TAPE_MINORS_PER_DEV == devindex) {
561 device = tape_get_device_reference(tmp); 556 device = tape_get_device(tmp);
562 break; 557 break;
563 } 558 }
564 } 559 }
@@ -579,7 +574,8 @@ tape_generic_probe(struct ccw_device *cdev)
579 device = tape_alloc_device(); 574 device = tape_alloc_device();
580 if (IS_ERR(device)) 575 if (IS_ERR(device))
581 return -ENODEV; 576 return -ENODEV;
582 ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); 577 ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP |
578 CCWDEV_DO_MULTIPATH);
583 ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group); 579 ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group);
584 if (ret) { 580 if (ret) {
585 tape_put_device(device); 581 tape_put_device(device);
@@ -606,7 +602,8 @@ __tape_discard_requests(struct tape_device *device)
606 list_del(&request->list); 602 list_del(&request->list);
607 603
608 /* Decrease ref_count for removed request. */ 604 /* Decrease ref_count for removed request. */
609 request->device = tape_put_device(device); 605 request->device = NULL;
606 tape_put_device(device);
610 request->rc = -EIO; 607 request->rc = -EIO;
611 if (request->callback != NULL) 608 if (request->callback != NULL)
612 request->callback(request, request->callback_data); 609 request->callback(request, request->callback_data);
@@ -664,9 +661,11 @@ tape_generic_remove(struct ccw_device *cdev)
664 tape_cleanup_device(device); 661 tape_cleanup_device(device);
665 } 662 }
666 663
667 if (!dev_get_drvdata(&cdev->dev)) { 664 device = dev_get_drvdata(&cdev->dev);
665 if (device) {
668 sysfs_remove_group(&cdev->dev.kobj, &tape_attr_group); 666 sysfs_remove_group(&cdev->dev.kobj, &tape_attr_group);
669 dev_set_drvdata(&cdev->dev, tape_put_device(dev_get_drvdata(&cdev->dev))); 667 dev_set_drvdata(&cdev->dev, NULL);
668 tape_put_device(device);
670 } 669 }
671} 670}
672 671
@@ -721,9 +720,8 @@ tape_free_request (struct tape_request * request)
721{ 720{
722 DBF_LH(6, "Free request %p\n", request); 721 DBF_LH(6, "Free request %p\n", request);
723 722
724 if (request->device != NULL) { 723 if (request->device)
725 request->device = tape_put_device(request->device); 724 tape_put_device(request->device);
726 }
727 kfree(request->cpdata); 725 kfree(request->cpdata);
728 kfree(request->cpaddr); 726 kfree(request->cpaddr);
729 kfree(request); 727 kfree(request);
@@ -838,7 +836,8 @@ static void tape_long_busy_timeout(unsigned long data)
838 BUG_ON(request->status != TAPE_REQUEST_LONG_BUSY); 836 BUG_ON(request->status != TAPE_REQUEST_LONG_BUSY);
839 DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id); 837 DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id);
840 __tape_start_next_request(device); 838 __tape_start_next_request(device);
841 device->lb_timeout.data = (unsigned long) tape_put_device(device); 839 device->lb_timeout.data = 0UL;
840 tape_put_device(device);
842 spin_unlock_irq(get_ccwdev_lock(device->cdev)); 841 spin_unlock_irq(get_ccwdev_lock(device->cdev));
843} 842}
844 843
@@ -918,7 +917,7 @@ __tape_start_request(struct tape_device *device, struct tape_request *request)
918 } 917 }
919 918
920 /* Increase use count of device for the added request. */ 919 /* Increase use count of device for the added request. */
921 request->device = tape_get_device_reference(device); 920 request->device = tape_get_device(device);
922 921
923 if (list_empty(&device->req_queue)) { 922 if (list_empty(&device->req_queue)) {
924 /* No other requests are on the queue. Start this one. */ 923 /* No other requests are on the queue. Start this one. */
@@ -1117,8 +1116,8 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
1117 if (req->status == TAPE_REQUEST_LONG_BUSY) { 1116 if (req->status == TAPE_REQUEST_LONG_BUSY) {
1118 DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id); 1117 DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id);
1119 if (del_timer(&device->lb_timeout)) { 1118 if (del_timer(&device->lb_timeout)) {
1120 device->lb_timeout.data = (unsigned long) 1119 device->lb_timeout.data = 0UL;
1121 tape_put_device(device); 1120 tape_put_device(device);
1122 __tape_start_next_request(device); 1121 __tape_start_next_request(device);
1123 } 1122 }
1124 return; 1123 return;
@@ -1173,7 +1172,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
1173 break; 1172 break;
1174 case TAPE_IO_LONG_BUSY: 1173 case TAPE_IO_LONG_BUSY:
1175 device->lb_timeout.data = 1174 device->lb_timeout.data =
1176 (unsigned long)tape_get_device_reference(device); 1175 (unsigned long) tape_get_device(device);
1177 device->lb_timeout.expires = jiffies + 1176 device->lb_timeout.expires = jiffies +
1178 LONG_BUSY_TIMEOUT * HZ; 1177 LONG_BUSY_TIMEOUT * HZ;
1179 DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id); 1178 DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id);
@@ -1326,7 +1325,7 @@ EXPORT_SYMBOL(tape_generic_online);
1326EXPORT_SYMBOL(tape_generic_offline); 1325EXPORT_SYMBOL(tape_generic_offline);
1327EXPORT_SYMBOL(tape_generic_pm_suspend); 1326EXPORT_SYMBOL(tape_generic_pm_suspend);
1328EXPORT_SYMBOL(tape_put_device); 1327EXPORT_SYMBOL(tape_put_device);
1329EXPORT_SYMBOL(tape_get_device_reference); 1328EXPORT_SYMBOL(tape_get_device);
1330EXPORT_SYMBOL(tape_state_verbose); 1329EXPORT_SYMBOL(tape_state_verbose);
1331EXPORT_SYMBOL(tape_op_verbose); 1330EXPORT_SYMBOL(tape_op_verbose);
1332EXPORT_SYMBOL(tape_state_set); 1331EXPORT_SYMBOL(tape_state_set);
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index 202f42132939..ebd820ccfb24 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -45,7 +45,7 @@ static int tape_proc_show(struct seq_file *m, void *v)
45 seq_printf(m, "TapeNo\tBusID CuType/Model\t" 45 seq_printf(m, "TapeNo\tBusID CuType/Model\t"
46 "DevType/Model\tBlkSize\tState\tOp\tMedState\n"); 46 "DevType/Model\tBlkSize\tState\tOp\tMedState\n");
47 } 47 }
48 device = tape_get_device(n); 48 device = tape_find_device(n);
49 if (IS_ERR(device)) 49 if (IS_ERR(device))
50 return 0; 50 return 0;
51 spin_lock_irq(get_ccwdev_lock(device->cdev)); 51 spin_lock_irq(get_ccwdev_lock(device->cdev));
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 38385677c653..911822db614d 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -19,6 +19,7 @@
19 19
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/bootmem.h> 21#include <linux/bootmem.h>
22#include <linux/compat.h>
22 23
23#include <asm/ccwdev.h> 24#include <asm/ccwdev.h>
24#include <asm/cio.h> 25#include <asm/cio.h>
@@ -1731,6 +1732,22 @@ tty3270_ioctl(struct tty_struct *tty, struct file *file,
1731 return kbd_ioctl(tp->kbd, file, cmd, arg); 1732 return kbd_ioctl(tp->kbd, file, cmd, arg);
1732} 1733}
1733 1734
1735#ifdef CONFIG_COMPAT
1736static long
1737tty3270_compat_ioctl(struct tty_struct *tty, struct file *file,
1738 unsigned int cmd, unsigned long arg)
1739{
1740 struct tty3270 *tp;
1741
1742 tp = tty->driver_data;
1743 if (!tp)
1744 return -ENODEV;
1745 if (tty->flags & (1 << TTY_IO_ERROR))
1746 return -EIO;
1747 return kbd_ioctl(tp->kbd, file, cmd, (unsigned long)compat_ptr(arg));
1748}
1749#endif
1750
1734static const struct tty_operations tty3270_ops = { 1751static const struct tty_operations tty3270_ops = {
1735 .open = tty3270_open, 1752 .open = tty3270_open,
1736 .close = tty3270_close, 1753 .close = tty3270_close,
@@ -1745,6 +1762,9 @@ static const struct tty_operations tty3270_ops = {
1745 .hangup = tty3270_hangup, 1762 .hangup = tty3270_hangup,
1746 .wait_until_sent = tty3270_wait_until_sent, 1763 .wait_until_sent = tty3270_wait_until_sent,
1747 .ioctl = tty3270_ioctl, 1764 .ioctl = tty3270_ioctl,
1765#ifdef CONFIG_COMPAT
1766 .compat_ioctl = tty3270_compat_ioctl,
1767#endif
1748 .set_termios = tty3270_set_termios 1768 .set_termios = tty3270_set_termios
1749}; 1769};
1750 1770
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index d1a142fa3eb4..899aa795bf38 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -312,11 +312,9 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp)
312 return -ENOSYS; 312 return -ENOSYS;
313 313
314 /* Besure this device hasn't already been opened */ 314 /* Besure this device hasn't already been opened */
315 lock_kernel();
316 spin_lock_bh(&logptr->priv_lock); 315 spin_lock_bh(&logptr->priv_lock);
317 if (logptr->dev_in_use) { 316 if (logptr->dev_in_use) {
318 spin_unlock_bh(&logptr->priv_lock); 317 spin_unlock_bh(&logptr->priv_lock);
319 unlock_kernel();
320 return -EBUSY; 318 return -EBUSY;
321 } 319 }
322 logptr->dev_in_use = 1; 320 logptr->dev_in_use = 1;
@@ -360,9 +358,8 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp)
360 || (logptr->iucv_path_severed)); 358 || (logptr->iucv_path_severed));
361 if (logptr->iucv_path_severed) 359 if (logptr->iucv_path_severed)
362 goto out_record; 360 goto out_record;
363 ret = nonseekable_open(inode, filp); 361 nonseekable_open(inode, filp);
364 unlock_kernel(); 362 return 0;
365 return ret;
366 363
367out_record: 364out_record:
368 if (logptr->autorecording) 365 if (logptr->autorecording)
@@ -372,7 +369,6 @@ out_path:
372 logptr->path = NULL; 369 logptr->path = NULL;
373out_dev: 370out_dev:
374 logptr->dev_in_use = 0; 371 logptr->dev_in_use = 0;
375 unlock_kernel();
376 return -EIO; 372 return -EIO;
377} 373}
378 374
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 77571b68539a..cc56fc708bae 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -695,7 +695,6 @@ static int ur_open(struct inode *inode, struct file *file)
695 695
696 if (accmode == O_RDWR) 696 if (accmode == O_RDWR)
697 return -EACCES; 697 return -EACCES;
698 lock_kernel();
699 /* 698 /*
700 * We treat the minor number as the devno of the ur device 699 * We treat the minor number as the devno of the ur device
701 * to find in the driver tree. 700 * to find in the driver tree.
@@ -749,7 +748,6 @@ static int ur_open(struct inode *inode, struct file *file)
749 goto fail_urfile_free; 748 goto fail_urfile_free;
750 urf->file_reclen = rc; 749 urf->file_reclen = rc;
751 file->private_data = urf; 750 file->private_data = urf;
752 unlock_kernel();
753 return 0; 751 return 0;
754 752
755fail_urfile_free: 753fail_urfile_free:
@@ -761,7 +759,6 @@ fail_unlock:
761fail_put: 759fail_put:
762 urdev_put(urd); 760 urdev_put(urd);
763out: 761out:
764 unlock_kernel();
765 return rc; 762 return rc;
766} 763}
767 764
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index f2bc287b69e4..c974058e48d2 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -19,7 +19,6 @@
19#include <linux/moduleparam.h> 19#include <linux/moduleparam.h>
20#include <linux/suspend.h> 20#include <linux/suspend.h>
21#include <linux/watchdog.h> 21#include <linux/watchdog.h>
22#include <linux/smp_lock.h>
23 22
24#include <asm/ebcdic.h> 23#include <asm/ebcdic.h>
25#include <asm/io.h> 24#include <asm/io.h>
@@ -49,6 +48,8 @@ static unsigned int vmwdt_interval = 60;
49static unsigned long vmwdt_is_open; 48static unsigned long vmwdt_is_open;
50static int vmwdt_expect_close; 49static int vmwdt_expect_close;
51 50
51static DEFINE_MUTEX(vmwdt_mutex);
52
52#define VMWDT_OPEN 0 /* devnode is open or suspend in progress */ 53#define VMWDT_OPEN 0 /* devnode is open or suspend in progress */
53#define VMWDT_RUNNING 1 /* The watchdog is armed */ 54#define VMWDT_RUNNING 1 /* The watchdog is armed */
54 55
@@ -133,15 +134,11 @@ static int __init vmwdt_probe(void)
133static int vmwdt_open(struct inode *i, struct file *f) 134static int vmwdt_open(struct inode *i, struct file *f)
134{ 135{
135 int ret; 136 int ret;
136 lock_kernel(); 137 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; 138 return -EBUSY;
140 }
141 ret = vmwdt_keepalive(); 139 ret = vmwdt_keepalive();
142 if (ret) 140 if (ret)
143 clear_bit(VMWDT_OPEN, &vmwdt_is_open); 141 clear_bit(VMWDT_OPEN, &vmwdt_is_open);
144 unlock_kernel();
145 return ret ? ret : nonseekable_open(i, f); 142 return ret ? ret : nonseekable_open(i, f);
146} 143}
147 144
@@ -160,8 +157,7 @@ static struct watchdog_info vmwdt_info = {
160 .identity = "z/VM Watchdog Timer", 157 .identity = "z/VM Watchdog Timer",
161}; 158};
162 159
163static int vmwdt_ioctl(struct inode *i, struct file *f, 160static int __vmwdt_ioctl(unsigned int cmd, unsigned long arg)
164 unsigned int cmd, unsigned long arg)
165{ 161{
166 switch (cmd) { 162 switch (cmd) {
167 case WDIOC_GETSUPPORT: 163 case WDIOC_GETSUPPORT:
@@ -205,10 +201,19 @@ static int vmwdt_ioctl(struct inode *i, struct file *f,
205 case WDIOC_KEEPALIVE: 201 case WDIOC_KEEPALIVE:
206 return vmwdt_keepalive(); 202 return vmwdt_keepalive();
207 } 203 }
208
209 return -EINVAL; 204 return -EINVAL;
210} 205}
211 206
207static long vmwdt_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
208{
209 int rc;
210
211 mutex_lock(&vmwdt_mutex);
212 rc = __vmwdt_ioctl(cmd, arg);
213 mutex_unlock(&vmwdt_mutex);
214 return (long) rc;
215}
216
212static ssize_t vmwdt_write(struct file *f, const char __user *buf, 217static ssize_t vmwdt_write(struct file *f, const char __user *buf,
213 size_t count, loff_t *ppos) 218 size_t count, loff_t *ppos)
214{ 219{
@@ -288,7 +293,7 @@ static struct notifier_block vmwdt_power_notifier = {
288static const struct file_operations vmwdt_fops = { 293static const struct file_operations vmwdt_fops = {
289 .open = &vmwdt_open, 294 .open = &vmwdt_open,
290 .release = &vmwdt_close, 295 .release = &vmwdt_close,
291 .ioctl = &vmwdt_ioctl, 296 .unlocked_ioctl = &vmwdt_ioctl,
292 .write = &vmwdt_write, 297 .write = &vmwdt_write,
293 .owner = THIS_MODULE, 298 .owner = THIS_MODULE,
294}; 299};
@@ -309,6 +314,10 @@ static int __init vmwdt_init(void)
309 ret = register_pm_notifier(&vmwdt_power_notifier); 314 ret = register_pm_notifier(&vmwdt_power_notifier);
310 if (ret) 315 if (ret)
311 return ret; 316 return ret;
317 /*
318 * misc_register() has to be the last action in module_init(), because
319 * file operations will be available right after this.
320 */
312 ret = misc_register(&vmwdt_dev); 321 ret = misc_register(&vmwdt_dev);
313 if (ret) { 322 if (ret) {
314 unregister_pm_notifier(&vmwdt_power_notifier); 323 unregister_pm_notifier(&vmwdt_power_notifier);