diff options
Diffstat (limited to 'drivers/s390/char')
-rw-r--r-- | drivers/s390/char/con3215.c | 18 | ||||
-rw-r--r-- | drivers/s390/char/con3270.c | 1 | ||||
-rw-r--r-- | drivers/s390/char/fs3270.c | 31 | ||||
-rw-r--r-- | drivers/s390/char/monreader.c | 10 | ||||
-rw-r--r-- | drivers/s390/char/monwriter.c | 9 | ||||
-rw-r--r-- | drivers/s390/char/sclp.c | 2 | ||||
-rw-r--r-- | drivers/s390/char/sclp_cmd.c | 3 | ||||
-rw-r--r-- | drivers/s390/char/tape.h | 9 | ||||
-rw-r--r-- | drivers/s390/char/tape_34xx.c | 9 | ||||
-rw-r--r-- | drivers/s390/char/tape_3590.c | 5 | ||||
-rw-r--r-- | drivers/s390/char/tape_block.c | 55 | ||||
-rw-r--r-- | drivers/s390/char/tape_char.c | 75 | ||||
-rw-r--r-- | drivers/s390/char/tape_class.c | 4 | ||||
-rw-r--r-- | drivers/s390/char/tape_core.c | 67 | ||||
-rw-r--r-- | drivers/s390/char/tape_proc.c | 5 | ||||
-rw-r--r-- | drivers/s390/char/tape_std.c | 3 | ||||
-rw-r--r-- | drivers/s390/char/tty3270.c | 20 | ||||
-rw-r--r-- | drivers/s390/char/vmcp.c | 12 | ||||
-rw-r--r-- | drivers/s390/char/vmlogrdr.c | 10 | ||||
-rw-r--r-- | drivers/s390/char/vmur.c | 3 | ||||
-rw-r--r-- | drivers/s390/char/vmwatchdog.c | 29 |
21 files changed, 197 insertions, 183 deletions
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 21639d6c996f..59ec073724bf 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -857,7 +857,6 @@ static struct console con3215 = { /* * 3215 console initialization code called from console_init(). - * NOTE: This is called before kmalloc is available. */ static int __init con3215_init(void) { @@ -1038,22 +1037,6 @@ static void tty3215_flush_buffer(struct tty_struct *tty) } /* - * Currently we don't have any io controls for 3215 ttys - */ -static int tty3215_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - switch (cmd) { - default: - return -ENOIOCTLCMD; - } - return 0; -} - -/* * Disable reading from a 3215 tty */ static void tty3215_throttle(struct tty_struct * tty) @@ -1118,7 +1101,6 @@ static const struct tty_operations tty3215_ops = { .write_room = tty3215_write_room, .chars_in_buffer = tty3215_chars_in_buffer, .flush_buffer = tty3215_flush_buffer, - .ioctl = tty3215_ioctl, .throttle = tty3215_throttle, .unthrottle = tty3215_unthrottle, .stop = tty3215_stop, 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 = { /* * 3270 console initialization code called from console_init(). - * NOTE: This is called before kmalloc is available. */ static int __init con3270_init(void) diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 097d3846a828..31c59b0d6df0 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c @@ -15,6 +15,7 @@ #include <linux/types.h> #include <linux/smp_lock.h> +#include <asm/compat.h> #include <asm/ccwdev.h> #include <asm/cio.h> #include <asm/ebcdic.h> @@ -38,6 +39,8 @@ struct fs3270 { size_t rdbuf_size; /* size of data returned by RDBUF */ }; +static DEFINE_MUTEX(fs3270_mutex); + static void fs3270_wake_up(struct raw3270_request *rq, void *data) { @@ -74,7 +77,7 @@ fs3270_do_io(struct raw3270_view *view, struct raw3270_request *rq) } rc = raw3270_start(view, rq); if (rc == 0) { - /* Started sucessfully. Now wait for completion. */ + /* Started successfully. Now wait for completion. */ wait_event(fp->wait, raw3270_request_final(rq)); } } while (rc == -EACCES); @@ -320,6 +323,7 @@ fs3270_write(struct file *filp, const char __user *data, size_t count, loff_t *o static long fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { + char __user *argp; struct fs3270 *fp; struct raw3270_iocb iocb; int rc; @@ -327,8 +331,12 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) fp = filp->private_data; if (!fp) return -ENODEV; + if (is_compat_task()) + argp = compat_ptr(arg); + else + argp = (char __user *)arg; rc = 0; - lock_kernel(); + mutex_lock(&fs3270_mutex); switch (cmd) { case TUBICMD: fp->read_command = arg; @@ -337,10 +345,10 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) fp->write_command = arg; break; case TUBGETI: - rc = put_user(fp->read_command, (char __user *) arg); + rc = put_user(fp->read_command, argp); break; case TUBGETO: - rc = put_user(fp->write_command,(char __user *) arg); + rc = put_user(fp->write_command, argp); break; case TUBGETMOD: iocb.model = fp->view.model; @@ -349,12 +357,11 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) iocb.pf_cnt = 24; iocb.re_cnt = 20; iocb.map = 0; - if (copy_to_user((char __user *) arg, &iocb, - sizeof(struct raw3270_iocb))) + if (copy_to_user(argp, &iocb, sizeof(struct raw3270_iocb))) rc = -EFAULT; break; } - unlock_kernel(); + mutex_unlock(&fs3270_mutex); return rc; } @@ -437,7 +444,7 @@ fs3270_open(struct inode *inode, struct file *filp) minor = tty->index + RAW3270_FIRSTMINOR; tty_kref_put(tty); } - lock_kernel(); + mutex_lock(&fs3270_mutex); /* Check if some other program is already using fullscreen mode. */ fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); if (!IS_ERR(fp)) { @@ -465,7 +472,7 @@ fs3270_open(struct inode *inode, struct file *filp) if (IS_ERR(ib)) { raw3270_put_view(&fp->view); raw3270_del_view(&fp->view); - rc = PTR_ERR(fp); + rc = PTR_ERR(ib); goto out; } fp->rdbuf = ib; @@ -478,7 +485,7 @@ fs3270_open(struct inode *inode, struct file *filp) } filp->private_data = fp; out: - unlock_kernel(); + mutex_unlock(&fs3270_mutex); return rc; } @@ -509,8 +516,8 @@ static const struct file_operations fs3270_fops = { .write = fs3270_write, /* write */ .unlocked_ioctl = fs3270_ioctl, /* ioctl */ .compat_ioctl = fs3270_ioctl, /* ioctl */ - .open = fs3270_open, /* open */ - .release = fs3270_close, /* release */ + .open = fs3270_open, /* open */ + .release = fs3270_close, /* release */ }; /* diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 66e21dd23154..33e96484d54f 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> -#include <linux/smp_lock.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/kernel.h> @@ -283,7 +282,6 @@ static int mon_open(struct inode *inode, struct file *filp) /* * only one user allowed */ - lock_kernel(); rc = -EBUSY; if (test_and_set_bit(MON_IN_USE, &mon_in_use)) goto out; @@ -321,7 +319,6 @@ static int mon_open(struct inode *inode, struct file *filp) } filp->private_data = monpriv; dev_set_drvdata(monreader_device, monpriv); - unlock_kernel(); return nonseekable_open(inode, filp); out_path: @@ -331,7 +328,6 @@ out_priv: out_use: clear_bit(MON_IN_USE, &mon_in_use); out: - unlock_kernel(); return rc; } @@ -533,7 +529,7 @@ static int monreader_restore(struct device *dev) return monreader_thaw(dev); } -static struct dev_pm_ops monreader_pm_ops = { +static const struct dev_pm_ops monreader_pm_ops = { .freeze = monreader_freeze, .thaw = monreader_thaw, .restore = monreader_restore, @@ -607,6 +603,10 @@ static int __init mon_init(void) } dcss_mkname(mon_dcss_name, &user_data_connect[8]); + /* + * misc_register() has to be the last action in module_init(), because + * file operations will be available right after this. + */ rc = misc_register(&mon_dev); if (rc < 0 ) goto out; diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index 66fb8eba93f4..668a0579b26b 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c @@ -13,7 +13,6 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/errno.h> -#include <linux/smp_lock.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/miscdevice.h> @@ -185,13 +184,11 @@ static int monwrite_open(struct inode *inode, struct file *filp) monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); if (!monpriv) return -ENOMEM; - lock_kernel(); INIT_LIST_HEAD(&monpriv->list); monpriv->hdr_to_read = sizeof(monpriv->hdr); mutex_init(&monpriv->thread_mutex); filp->private_data = monpriv; list_add_tail(&monpriv->priv_list, &mon_priv_list); - unlock_kernel(); return nonseekable_open(inode, filp); } @@ -326,7 +323,7 @@ static int monwriter_thaw(struct device *dev) return monwriter_restore(dev); } -static struct dev_pm_ops monwriter_pm_ops = { +static const struct dev_pm_ops monwriter_pm_ops = { .freeze = monwriter_freeze, .thaw = monwriter_thaw, .restore = monwriter_restore, @@ -364,6 +361,10 @@ static int __init mon_init(void) goto out_driver; } + /* + * misc_register() has to be the last action in module_init(), because + * file operations will be available right after this. + */ rc = misc_register(&mon_dev); if (rc) goto out_device; diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index a983f5086788..ec88c59842e3 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -1019,7 +1019,7 @@ static int sclp_restore(struct device *dev) return sclp_undo_suspend(SCLP_PM_EVENT_RESTORE); } -static struct dev_pm_ops sclp_pm_ops = { +static const struct dev_pm_ops sclp_pm_ops = { .freeze = sclp_freeze, .thaw = sclp_thaw, .restore = sclp_restore, diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 5cc11c636d38..b3beab610da4 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) do { memset(sccb, 0, sizeof(*sccb)); sccb->header.length = sizeof(*sccb); + sccb->header.function_code = 0x80; sccb->header.control_mask[2] = 0x80; rc = sclp_cmd_sync_early(commands[i], sccb); } while (rc == -EBUSY); @@ -546,7 +547,7 @@ struct read_storage_sccb { u32 entries[0]; } __packed; -static struct dev_pm_ops sclp_mem_pm_ops = { +static const struct dev_pm_ops sclp_mem_pm_ops = { .freeze = sclp_mem_freeze, }; 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 { struct tape_class_device * nt; struct tape_class_device * rt; + /* Device mutex to serialize tape commands. */ + struct mutex mutex; + /* Device discipline information. */ struct tape_discipline * discipline; void * discdata; @@ -292,9 +295,9 @@ extern int tape_generic_pm_suspend(struct ccw_device *); extern int tape_generic_probe(struct ccw_device *); extern void tape_generic_remove(struct ccw_device *); -extern struct tape_device *tape_get_device(int devindex); -extern struct tape_device *tape_get_device_reference(struct tape_device *); -extern struct tape_device *tape_put_device(struct tape_device *); +extern struct tape_device *tape_find_device(int devindex); +extern struct tape_device *tape_get_device(struct tape_device *); +extern void tape_put_device(struct tape_device *); /* Externals from tape_char.c */ extern int tapechar_init(void); diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 2fe45ff77b75..cb70fa1cf539 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -9,6 +9,7 @@ */ #define KMSG_COMPONENT "tape_34xx" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include <linux/module.h> #include <linux/init.h> @@ -113,16 +114,16 @@ tape_34xx_work_handler(struct work_struct *work) { struct tape_34xx_work *p = container_of(work, struct tape_34xx_work, work); + struct tape_device *device = p->device; switch(p->op) { case TO_MSEN: - tape_34xx_medium_sense(p->device); + tape_34xx_medium_sense(device); break; default: DBF_EVENT(3, "T34XX: internal error: unknown work\n"); } - - p->device = tape_put_device(p->device); + tape_put_device(device); kfree(p); } @@ -136,7 +137,7 @@ tape_34xx_schedule_work(struct tape_device *device, enum tape_op op) INIT_WORK(&p->work, tape_34xx_work_handler); - p->device = tape_get_device_reference(device); + p->device = tape_get_device(device); p->op = op; schedule_work(&p->work); diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index e4cc3aae9162..9821c5886613 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -9,6 +9,7 @@ */ #define KMSG_COMPONENT "tape_3590" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include <linux/module.h> #include <linux/init.h> @@ -136,7 +137,7 @@ static void int_to_ext_kekl(struct tape3592_kekl *in, out->type_on_tape = TAPE390_KEKL_TYPE_LABEL; memcpy(out->label, in->label, sizeof(in->label)); EBCASC(out->label, sizeof(in->label)); - strstrip(out->label); + strim(out->label); } static void int_to_ext_kekl_pair(struct tape3592_kekl_pair *in, @@ -608,7 +609,7 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op) INIT_WORK(&p->work, tape_3590_work_handler); - p->device = tape_get_device_reference(device); + p->device = tape_get_device(device); p->op = op; schedule_work(&p->work); diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 0c0705b91c28..8d3d720737da 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -11,6 +11,7 @@ */ #define KMSG_COMPONENT "tape" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include <linux/fs.h> #include <linux/module.h> @@ -45,8 +46,6 @@ */ static int tapeblock_open(struct block_device *, fmode_t); static int tapeblock_release(struct gendisk *, fmode_t); -static int tapeblock_ioctl(struct block_device *, fmode_t, unsigned int, - unsigned long); static int tapeblock_medium_changed(struct gendisk *); static int tapeblock_revalidate_disk(struct gendisk *); @@ -54,7 +53,6 @@ static const struct block_device_operations tapeblock_fops = { .owner = THIS_MODULE, .open = tapeblock_open, .release = tapeblock_release, - .locked_ioctl = tapeblock_ioctl, .media_changed = tapeblock_medium_changed, .revalidate_disk = tapeblock_revalidate_disk, }; @@ -239,7 +237,7 @@ tapeblock_setup_device(struct tape_device * device) disk->major = tapeblock_major; disk->first_minor = device->first_minor; disk->fops = &tapeblock_fops; - disk->private_data = tape_get_device_reference(device); + disk->private_data = tape_get_device(device); disk->queue = blkdat->request_queue; set_capacity(disk, 0); sprintf(disk->disk_name, "btibm%d", @@ -247,11 +245,11 @@ tapeblock_setup_device(struct tape_device * device) blkdat->disk = disk; blkdat->medium_changed = 1; - blkdat->request_queue->queuedata = tape_get_device_reference(device); + blkdat->request_queue->queuedata = tape_get_device(device); add_disk(disk); - tape_get_device_reference(device); + tape_get_device(device); INIT_WORK(&blkdat->requeue_task, tapeblock_requeue); return 0; @@ -274,13 +272,14 @@ tapeblock_cleanup_device(struct tape_device *device) } del_gendisk(device->blk_data.disk); - device->blk_data.disk->private_data = - tape_put_device(device->blk_data.disk->private_data); + device->blk_data.disk->private_data = NULL; + tape_put_device(device); put_disk(device->blk_data.disk); device->blk_data.disk = NULL; cleanup_queue: - device->blk_data.request_queue->queuedata = tape_put_device(device); + device->blk_data.request_queue->queuedata = NULL; + tape_put_device(device); blk_cleanup_queue(device->blk_data.request_queue); device->blk_data.request_queue = NULL; @@ -363,7 +362,7 @@ tapeblock_open(struct block_device *bdev, fmode_t mode) struct tape_device * device; int rc; - device = tape_get_device_reference(disk->private_data); + device = tape_get_device(disk->private_data); if (device->required_tapemarks) { DBF_EVENT(2, "TBLOCK: missing tapemarks\n"); @@ -414,42 +413,6 @@ tapeblock_release(struct gendisk *disk, fmode_t mode) } /* - * Support of some generic block device IOCTLs. - */ -static int -tapeblock_ioctl( - struct block_device * bdev, - fmode_t mode, - unsigned int command, - unsigned long arg -) { - int rc; - int minor; - struct gendisk *disk = bdev->bd_disk; - struct tape_device *device; - - rc = 0; - BUG_ON(!disk); - device = disk->private_data; - BUG_ON(!device); - minor = MINOR(bdev->bd_dev); - - DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command); - DBF_LH(6, "device = %d:%d\n", tapeblock_major, minor); - - switch (command) { - /* Refuse some IOCTL calls without complaining (mount). */ - case 0x5310: /* CDROMMULTISESSION */ - rc = -EINVAL; - break; - default: - rc = -EINVAL; - } - - return rc; -} - -/* * Initialize block device frontend. */ int diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index 31566c55adfe..539045acaad4 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c @@ -10,11 +10,15 @@ * Martin Schwidefsky <schwidefsky@de.ibm.com> */ +#define KMSG_COMPONENT "tape" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + #include <linux/module.h> #include <linux/types.h> #include <linux/proc_fs.h> #include <linux/mtio.h> #include <linux/smp_lock.h> +#include <linux/compat.h> #include <asm/uaccess.h> @@ -33,18 +37,20 @@ static ssize_t tapechar_read(struct file *, char __user *, size_t, loff_t *); static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *); static int tapechar_open(struct inode *,struct file *); static int tapechar_release(struct inode *,struct file *); -static int tapechar_ioctl(struct inode *, struct file *, unsigned int, - unsigned long); -static long tapechar_compat_ioctl(struct file *, unsigned int, - unsigned long); +static long tapechar_ioctl(struct file *, unsigned int, unsigned long); +#ifdef CONFIG_COMPAT +static long tapechar_compat_ioctl(struct file *, unsigned int, unsigned long); +#endif static const struct file_operations tape_fops = { .owner = THIS_MODULE, .read = tapechar_read, .write = tapechar_write, - .ioctl = tapechar_ioctl, + .unlocked_ioctl = tapechar_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = tapechar_compat_ioctl, +#endif .open = tapechar_open, .release = tapechar_release, }; @@ -170,7 +176,6 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) if (rc == 0) { rc = block_size - request->rescnt; DBF_EVENT(6, "TCHAR:rbytes: %x\n", rc); - filp->f_pos += rc; /* Copy data from idal buffer to user space. */ if (idal_buffer_to_user(device->char_data.idal_buf, data, rc) != 0) @@ -238,7 +243,6 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t break; DBF_EVENT(6, "TCHAR:wbytes: %lx\n", block_size - request->rescnt); - filp->f_pos += block_size - request->rescnt; written += block_size - request->rescnt; if (request->rescnt != 0) break; @@ -286,26 +290,20 @@ tapechar_open (struct inode *inode, struct file *filp) if (imajor(filp->f_path.dentry->d_inode) != tapechar_major) return -ENODEV; - lock_kernel(); minor = iminor(filp->f_path.dentry->d_inode); - device = tape_get_device(minor / TAPE_MINORS_PER_DEV); + device = tape_find_device(minor / TAPE_MINORS_PER_DEV); if (IS_ERR(device)) { - DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n"); - rc = PTR_ERR(device); - goto out; + DBF_EVENT(3, "TCHAR:open: tape_find_device() failed\n"); + return PTR_ERR(device); } - rc = tape_open(device); if (rc == 0) { filp->private_data = device; - rc = nonseekable_open(inode, filp); - } - else + nonseekable_open(inode, filp); + } else tape_put_device(device); -out: - unlock_kernel(); return rc; } @@ -342,7 +340,8 @@ tapechar_release(struct inode *inode, struct file *filp) device->char_data.idal_buf = NULL; } tape_release(device); - filp->private_data = tape_put_device(device); + filp->private_data = NULL; + tape_put_device(device); return 0; } @@ -351,16 +350,11 @@ tapechar_release(struct inode *inode, struct file *filp) * Tape device io controls. */ static int -tapechar_ioctl(struct inode *inp, struct file *filp, - unsigned int no, unsigned long data) +__tapechar_ioctl(struct tape_device *device, + unsigned int no, unsigned long data) { - struct tape_device *device; int rc; - DBF_EVENT(6, "TCHAR:ioct\n"); - - device = (struct tape_device *) filp->private_data; - if (no == MTIOCTOP) { struct mtop op; @@ -453,21 +447,44 @@ tapechar_ioctl(struct inode *inp, struct file *filp, } static long +tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data) +{ + struct tape_device *device; + long rc; + + DBF_EVENT(6, "TCHAR:ioct\n"); + + device = (struct tape_device *) filp->private_data; + mutex_lock(&device->mutex); + rc = __tapechar_ioctl(device, no, data); + mutex_unlock(&device->mutex); + return rc; +} + +#ifdef CONFIG_COMPAT +static long tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) { struct tape_device *device = filp->private_data; int rval = -ENOIOCTLCMD; + unsigned long argp; + /* The 'arg' argument of any ioctl function may only be used for + * pointers because of the compat pointer conversion. + * Consider this when adding new ioctls. + */ + argp = (unsigned long) compat_ptr(data); if (device->discipline->ioctl_fn) { - lock_kernel(); - rval = device->discipline->ioctl_fn(device, no, data); - unlock_kernel(); + mutex_lock(&device->mutex); + rval = device->discipline->ioctl_fn(device, no, argp); + mutex_unlock(&device->mutex); if (rval == -EINVAL) rval = -ENOIOCTLCMD; } return rval; } +#endif /* CONFIG_COMPAT */ /* * Initialize character device frontend. diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c index ddc914ccea8f..b2864e3edb6d 100644 --- a/drivers/s390/char/tape_class.c +++ b/drivers/s390/char/tape_class.c @@ -7,6 +7,10 @@ * Author: Stefan Bader <shbader@de.ibm.com> * Based on simple class device code by Greg K-H */ + +#define KMSG_COMPONENT "tape" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + #include "tape_class.h" MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>"); diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 5cd31e071647..81b094e480e6 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -12,6 +12,8 @@ */ #define KMSG_COMPONENT "tape" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + #include <linux/module.h> #include <linux/init.h> // for kernel parameters #include <linux/kmod.h> // for requesting modules @@ -492,6 +494,7 @@ tape_alloc_device(void) kfree(device); return ERR_PTR(-ENOMEM); } + mutex_init(&device->mutex); INIT_LIST_HEAD(&device->req_queue); INIT_LIST_HEAD(&device->node); init_waitqueue_head(&device->state_change_wq); @@ -511,11 +514,12 @@ tape_alloc_device(void) * increment the reference count. */ struct tape_device * -tape_get_device_reference(struct tape_device *device) +tape_get_device(struct tape_device *device) { - DBF_EVENT(4, "tape_get_device_reference(%p) = %i\n", device, - atomic_inc_return(&device->ref_count)); + int count; + count = atomic_inc_return(&device->ref_count); + DBF_EVENT(4, "tape_get_device(%p) = %i\n", device, count); return device; } @@ -525,32 +529,25 @@ tape_get_device_reference(struct tape_device *device) * The function returns a NULL pointer to be used by the caller * for clearing reference pointers. */ -struct tape_device * +void tape_put_device(struct tape_device *device) { - int remain; + int count; - remain = atomic_dec_return(&device->ref_count); - if (remain > 0) { - DBF_EVENT(4, "tape_put_device(%p) -> %i\n", device, remain); - } else { - if (remain < 0) { - DBF_EVENT(4, "put device without reference\n"); - } else { - DBF_EVENT(4, "tape_free_device(%p)\n", device); - kfree(device->modeset_byte); - kfree(device); - } + count = atomic_dec_return(&device->ref_count); + DBF_EVENT(4, "tape_put_device(%p) -> %i\n", device, count); + BUG_ON(count < 0); + if (count == 0) { + kfree(device->modeset_byte); + kfree(device); } - - return NULL; } /* * Find tape device by a device index. */ struct tape_device * -tape_get_device(int devindex) +tape_find_device(int devindex) { struct tape_device *device, *tmp; @@ -558,7 +555,7 @@ tape_get_device(int devindex) read_lock(&tape_device_lock); list_for_each_entry(tmp, &tape_device_list, node) { if (tmp->first_minor / TAPE_MINORS_PER_DEV == devindex) { - device = tape_get_device_reference(tmp); + device = tape_get_device(tmp); break; } } @@ -579,7 +576,8 @@ tape_generic_probe(struct ccw_device *cdev) device = tape_alloc_device(); if (IS_ERR(device)) return -ENODEV; - ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); + ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP | + CCWDEV_DO_MULTIPATH); ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group); if (ret) { tape_put_device(device); @@ -606,7 +604,8 @@ __tape_discard_requests(struct tape_device *device) list_del(&request->list); /* Decrease ref_count for removed request. */ - request->device = tape_put_device(device); + request->device = NULL; + tape_put_device(device); request->rc = -EIO; if (request->callback != NULL) request->callback(request, request->callback_data); @@ -664,9 +663,11 @@ tape_generic_remove(struct ccw_device *cdev) tape_cleanup_device(device); } - if (!dev_get_drvdata(&cdev->dev)) { + device = dev_get_drvdata(&cdev->dev); + if (device) { sysfs_remove_group(&cdev->dev.kobj, &tape_attr_group); - dev_set_drvdata(&cdev->dev, tape_put_device(dev_get_drvdata(&cdev->dev))); + dev_set_drvdata(&cdev->dev, NULL); + tape_put_device(device); } } @@ -721,9 +722,8 @@ tape_free_request (struct tape_request * request) { DBF_LH(6, "Free request %p\n", request); - if (request->device != NULL) { - request->device = tape_put_device(request->device); - } + if (request->device) + tape_put_device(request->device); kfree(request->cpdata); kfree(request->cpaddr); kfree(request); @@ -838,7 +838,8 @@ static void tape_long_busy_timeout(unsigned long data) BUG_ON(request->status != TAPE_REQUEST_LONG_BUSY); DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id); __tape_start_next_request(device); - device->lb_timeout.data = (unsigned long) tape_put_device(device); + device->lb_timeout.data = 0UL; + tape_put_device(device); spin_unlock_irq(get_ccwdev_lock(device->cdev)); } @@ -918,7 +919,7 @@ __tape_start_request(struct tape_device *device, struct tape_request *request) } /* Increase use count of device for the added request. */ - request->device = tape_get_device_reference(device); + request->device = tape_get_device(device); if (list_empty(&device->req_queue)) { /* No other requests are on the queue. Start this one. */ @@ -1117,8 +1118,8 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) if (req->status == TAPE_REQUEST_LONG_BUSY) { DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id); if (del_timer(&device->lb_timeout)) { - device->lb_timeout.data = (unsigned long) - tape_put_device(device); + device->lb_timeout.data = 0UL; + tape_put_device(device); __tape_start_next_request(device); } return; @@ -1173,7 +1174,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) break; case TAPE_IO_LONG_BUSY: device->lb_timeout.data = - (unsigned long)tape_get_device_reference(device); + (unsigned long) tape_get_device(device); device->lb_timeout.expires = jiffies + LONG_BUSY_TIMEOUT * HZ; DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id); @@ -1326,7 +1327,7 @@ EXPORT_SYMBOL(tape_generic_online); EXPORT_SYMBOL(tape_generic_offline); EXPORT_SYMBOL(tape_generic_pm_suspend); EXPORT_SYMBOL(tape_put_device); -EXPORT_SYMBOL(tape_get_device_reference); +EXPORT_SYMBOL(tape_get_device); EXPORT_SYMBOL(tape_state_verbose); EXPORT_SYMBOL(tape_op_verbose); EXPORT_SYMBOL(tape_state_set); diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c index 202f42132939..0ceb37984f77 100644 --- a/drivers/s390/char/tape_proc.c +++ b/drivers/s390/char/tape_proc.c @@ -11,6 +11,9 @@ * PROCFS Functions */ +#define KMSG_COMPONENT "tape" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + #include <linux/module.h> #include <linux/vmalloc.h> #include <linux/seq_file.h> @@ -45,7 +48,7 @@ static int tape_proc_show(struct seq_file *m, void *v) seq_printf(m, "TapeNo\tBusID CuType/Model\t" "DevType/Model\tBlkSize\tState\tOp\tMedState\n"); } - device = tape_get_device(n); + device = tape_find_device(n); if (IS_ERR(device)) return 0; spin_lock_irq(get_ccwdev_lock(device->cdev)); diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index 750354ad16e5..03f07e5dd6e9 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c @@ -11,6 +11,9 @@ * Stefan Bader <shbader@de.ibm.com> */ +#define KMSG_COMPONENT "tape" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + #include <linux/stddef.h> #include <linux/kernel.h> #include <linux/bio.h> 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 @@ #include <linux/slab.h> #include <linux/bootmem.h> +#include <linux/compat.h> #include <asm/ccwdev.h> #include <asm/cio.h> @@ -1731,6 +1732,22 @@ tty3270_ioctl(struct tty_struct *tty, struct file *file, return kbd_ioctl(tp->kbd, file, cmd, arg); } +#ifdef CONFIG_COMPAT +static long +tty3270_compat_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct tty3270 *tp; + + tp = tty->driver_data; + if (!tp) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + return kbd_ioctl(tp->kbd, file, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + static const struct tty_operations tty3270_ops = { .open = tty3270_open, .close = tty3270_close, @@ -1745,6 +1762,9 @@ static const struct tty_operations tty3270_ops = { .hangup = tty3270_hangup, .wait_until_sent = tty3270_wait_until_sent, .ioctl = tty3270_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tty3270_compat_ioctl, +#endif .set_termios = tty3270_set_termios }; diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index a6087cec55b4..921dcda77676 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c @@ -19,6 +19,7 @@ #include <linux/kernel.h> #include <linux/miscdevice.h> #include <linux/module.h> +#include <asm/compat.h> #include <asm/cpcmd.h> #include <asm/debug.h> #include <asm/uaccess.h> @@ -139,21 +140,26 @@ vmcp_write(struct file *file, const char __user *buff, size_t count, static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct vmcp_session *session; + int __user *argp; int temp; session = (struct vmcp_session *)file->private_data; + if (is_compat_task()) + argp = compat_ptr(arg); + else + argp = (int __user *)arg; if (mutex_lock_interruptible(&session->mutex)) return -ERESTARTSYS; switch (cmd) { case VMCP_GETCODE: temp = session->resp_code; mutex_unlock(&session->mutex); - return put_user(temp, (int __user *)arg); + return put_user(temp, argp); case VMCP_SETBUF: free_pages((unsigned long)session->response, get_order(session->bufsize)); session->response=NULL; - temp = get_user(session->bufsize, (int __user *)arg); + temp = get_user(session->bufsize, argp); if (get_order(session->bufsize) > 8) { session->bufsize = PAGE_SIZE; temp = -EINVAL; @@ -163,7 +169,7 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case VMCP_GETSIZE: temp = session->resp_size; mutex_unlock(&session->mutex); - return put_user(temp, (int __user *)arg); + return put_user(temp, argp); default: mutex_unlock(&session->mutex); return -ENOIOCTLCMD; diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index d1a142fa3eb4..7dfa5412d5a8 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) return -ENOSYS; /* Besure this device hasn't already been opened */ - lock_kernel(); spin_lock_bh(&logptr->priv_lock); if (logptr->dev_in_use) { spin_unlock_bh(&logptr->priv_lock); - unlock_kernel(); return -EBUSY; } logptr->dev_in_use = 1; @@ -360,9 +358,8 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp) || (logptr->iucv_path_severed)); if (logptr->iucv_path_severed) goto out_record; - ret = nonseekable_open(inode, filp); - unlock_kernel(); - return ret; + nonseekable_open(inode, filp); + return 0; out_record: if (logptr->autorecording) @@ -372,7 +369,6 @@ out_path: logptr->path = NULL; out_dev: logptr->dev_in_use = 0; - unlock_kernel(); return -EIO; } @@ -679,7 +675,7 @@ static int vmlogrdr_pm_prepare(struct device *dev) } -static struct dev_pm_ops vmlogrdr_pm_ops = { +static const struct dev_pm_ops vmlogrdr_pm_ops = { .prepare = vmlogrdr_pm_prepare, }; 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) if (accmode == O_RDWR) return -EACCES; - lock_kernel(); /* * We treat the minor number as the devno of the ur device * to find in the driver tree. @@ -749,7 +748,6 @@ static int ur_open(struct inode *inode, struct file *file) goto fail_urfile_free; urf->file_reclen = rc; file->private_data = urf; - unlock_kernel(); return 0; fail_urfile_free: @@ -761,7 +759,6 @@ fail_unlock: fail_put: urdev_put(urd); out: - unlock_kernel(); return rc; } 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 @@ #include <linux/moduleparam.h> #include <linux/suspend.h> #include <linux/watchdog.h> -#include <linux/smp_lock.h> #include <asm/ebcdic.h> #include <asm/io.h> @@ -49,6 +48,8 @@ static unsigned int vmwdt_interval = 60; static unsigned long vmwdt_is_open; static int vmwdt_expect_close; +static DEFINE_MUTEX(vmwdt_mutex); + #define VMWDT_OPEN 0 /* devnode is open or suspend in progress */ #define VMWDT_RUNNING 1 /* The watchdog is armed */ @@ -133,15 +134,11 @@ static int __init vmwdt_probe(void) static int vmwdt_open(struct inode *i, struct file *f) { int ret; - lock_kernel(); - if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) { - unlock_kernel(); + if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) return -EBUSY; - } ret = vmwdt_keepalive(); if (ret) clear_bit(VMWDT_OPEN, &vmwdt_is_open); - unlock_kernel(); return ret ? ret : nonseekable_open(i, f); } @@ -160,8 +157,7 @@ static struct watchdog_info vmwdt_info = { .identity = "z/VM Watchdog Timer", }; -static int vmwdt_ioctl(struct inode *i, struct file *f, - unsigned int cmd, unsigned long arg) +static int __vmwdt_ioctl(unsigned int cmd, unsigned long arg) { switch (cmd) { case WDIOC_GETSUPPORT: @@ -205,10 +201,19 @@ static int vmwdt_ioctl(struct inode *i, struct file *f, case WDIOC_KEEPALIVE: return vmwdt_keepalive(); } - return -EINVAL; } +static long vmwdt_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + int rc; + + mutex_lock(&vmwdt_mutex); + rc = __vmwdt_ioctl(cmd, arg); + mutex_unlock(&vmwdt_mutex); + return (long) rc; +} + static ssize_t vmwdt_write(struct file *f, const char __user *buf, size_t count, loff_t *ppos) { @@ -288,7 +293,7 @@ static struct notifier_block vmwdt_power_notifier = { static const struct file_operations vmwdt_fops = { .open = &vmwdt_open, .release = &vmwdt_close, - .ioctl = &vmwdt_ioctl, + .unlocked_ioctl = &vmwdt_ioctl, .write = &vmwdt_write, .owner = THIS_MODULE, }; @@ -309,6 +314,10 @@ static int __init vmwdt_init(void) ret = register_pm_notifier(&vmwdt_power_notifier); if (ret) return ret; + /* + * misc_register() has to be the last action in module_init(), because + * file operations will be available right after this. + */ ret = misc_register(&vmwdt_dev); if (ret) { unregister_pm_notifier(&vmwdt_power_notifier); |