diff options
Diffstat (limited to 'drivers/s390/char')
28 files changed, 304 insertions, 322 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 = { | |||
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 | */ |
862 | static int __init con3215_init(void) | 861 | static int __init con3215_init(void) |
863 | { | 862 | { |
@@ -1038,22 +1037,6 @@ static void tty3215_flush_buffer(struct tty_struct *tty) | |||
1038 | } | 1037 | } |
1039 | 1038 | ||
1040 | /* | 1039 | /* |
1041 | * Currently we don't have any io controls for 3215 ttys | ||
1042 | */ | ||
1043 | static int tty3215_ioctl(struct tty_struct *tty, struct file * file, | ||
1044 | unsigned int cmd, unsigned long arg) | ||
1045 | { | ||
1046 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1047 | return -EIO; | ||
1048 | |||
1049 | switch (cmd) { | ||
1050 | default: | ||
1051 | return -ENOIOCTLCMD; | ||
1052 | } | ||
1053 | return 0; | ||
1054 | } | ||
1055 | |||
1056 | /* | ||
1057 | * Disable reading from a 3215 tty | 1040 | * Disable reading from a 3215 tty |
1058 | */ | 1041 | */ |
1059 | static void tty3215_throttle(struct tty_struct * tty) | 1042 | static void tty3215_throttle(struct tty_struct * tty) |
@@ -1118,7 +1101,6 @@ static const struct tty_operations tty3215_ops = { | |||
1118 | .write_room = tty3215_write_room, | 1101 | .write_room = tty3215_write_room, |
1119 | .chars_in_buffer = tty3215_chars_in_buffer, | 1102 | .chars_in_buffer = tty3215_chars_in_buffer, |
1120 | .flush_buffer = tty3215_flush_buffer, | 1103 | .flush_buffer = tty3215_flush_buffer, |
1121 | .ioctl = tty3215_ioctl, | ||
1122 | .throttle = tty3215_throttle, | 1104 | .throttle = tty3215_throttle, |
1123 | .unthrottle = tty3215_unthrottle, | 1105 | .unthrottle = tty3215_unthrottle, |
1124 | .stop = tty3215_stop, | 1106 | .stop = tty3215_stop, |
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index bb838bdf829d..bb07577e8fd4 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | #include <linux/list.h> | 13 | #include <linux/list.h> |
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/err.h> | 16 | #include <linux/err.h> |
16 | #include <linux/reboot.h> | 17 | #include <linux/reboot.h> |
17 | 18 | ||
@@ -572,7 +573,6 @@ static struct console con3270 = { | |||
572 | 573 | ||
573 | /* | 574 | /* |
574 | * 3270 console initialization code called from console_init(). | 575 | * 3270 console initialization code called from console_init(). |
575 | * NOTE: This is called before kmalloc is available. | ||
576 | */ | 576 | */ |
577 | static int __init | 577 | static int __init |
578 | con3270_init(void) | 578 | con3270_init(void) |
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 097d3846a828..0eabcca3c92d 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c | |||
@@ -12,9 +12,11 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/types.h> | 16 | #include <linux/types.h> |
16 | #include <linux/smp_lock.h> | 17 | #include <linux/smp_lock.h> |
17 | 18 | ||
19 | #include <asm/compat.h> | ||
18 | #include <asm/ccwdev.h> | 20 | #include <asm/ccwdev.h> |
19 | #include <asm/cio.h> | 21 | #include <asm/cio.h> |
20 | #include <asm/ebcdic.h> | 22 | #include <asm/ebcdic.h> |
@@ -38,6 +40,8 @@ struct fs3270 { | |||
38 | size_t rdbuf_size; /* size of data returned by RDBUF */ | 40 | size_t rdbuf_size; /* size of data returned by RDBUF */ |
39 | }; | 41 | }; |
40 | 42 | ||
43 | static DEFINE_MUTEX(fs3270_mutex); | ||
44 | |||
41 | static void | 45 | static void |
42 | fs3270_wake_up(struct raw3270_request *rq, void *data) | 46 | fs3270_wake_up(struct raw3270_request *rq, void *data) |
43 | { | 47 | { |
@@ -74,7 +78,7 @@ fs3270_do_io(struct raw3270_view *view, struct raw3270_request *rq) | |||
74 | } | 78 | } |
75 | rc = raw3270_start(view, rq); | 79 | rc = raw3270_start(view, rq); |
76 | if (rc == 0) { | 80 | if (rc == 0) { |
77 | /* Started sucessfully. Now wait for completion. */ | 81 | /* Started successfully. Now wait for completion. */ |
78 | wait_event(fp->wait, raw3270_request_final(rq)); | 82 | wait_event(fp->wait, raw3270_request_final(rq)); |
79 | } | 83 | } |
80 | } while (rc == -EACCES); | 84 | } while (rc == -EACCES); |
@@ -320,6 +324,7 @@ fs3270_write(struct file *filp, const char __user *data, size_t count, loff_t *o | |||
320 | static long | 324 | static long |
321 | fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 325 | fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
322 | { | 326 | { |
327 | char __user *argp; | ||
323 | struct fs3270 *fp; | 328 | struct fs3270 *fp; |
324 | struct raw3270_iocb iocb; | 329 | struct raw3270_iocb iocb; |
325 | int rc; | 330 | int rc; |
@@ -327,8 +332,12 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
327 | fp = filp->private_data; | 332 | fp = filp->private_data; |
328 | if (!fp) | 333 | if (!fp) |
329 | return -ENODEV; | 334 | return -ENODEV; |
335 | if (is_compat_task()) | ||
336 | argp = compat_ptr(arg); | ||
337 | else | ||
338 | argp = (char __user *)arg; | ||
330 | rc = 0; | 339 | rc = 0; |
331 | lock_kernel(); | 340 | mutex_lock(&fs3270_mutex); |
332 | switch (cmd) { | 341 | switch (cmd) { |
333 | case TUBICMD: | 342 | case TUBICMD: |
334 | fp->read_command = arg; | 343 | fp->read_command = arg; |
@@ -337,10 +346,10 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
337 | fp->write_command = arg; | 346 | fp->write_command = arg; |
338 | break; | 347 | break; |
339 | case TUBGETI: | 348 | case TUBGETI: |
340 | rc = put_user(fp->read_command, (char __user *) arg); | 349 | rc = put_user(fp->read_command, argp); |
341 | break; | 350 | break; |
342 | case TUBGETO: | 351 | case TUBGETO: |
343 | rc = put_user(fp->write_command,(char __user *) arg); | 352 | rc = put_user(fp->write_command, argp); |
344 | break; | 353 | break; |
345 | case TUBGETMOD: | 354 | case TUBGETMOD: |
346 | iocb.model = fp->view.model; | 355 | iocb.model = fp->view.model; |
@@ -349,12 +358,11 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
349 | iocb.pf_cnt = 24; | 358 | iocb.pf_cnt = 24; |
350 | iocb.re_cnt = 20; | 359 | iocb.re_cnt = 20; |
351 | iocb.map = 0; | 360 | iocb.map = 0; |
352 | if (copy_to_user((char __user *) arg, &iocb, | 361 | if (copy_to_user(argp, &iocb, sizeof(struct raw3270_iocb))) |
353 | sizeof(struct raw3270_iocb))) | ||
354 | rc = -EFAULT; | 362 | rc = -EFAULT; |
355 | break; | 363 | break; |
356 | } | 364 | } |
357 | unlock_kernel(); | 365 | mutex_unlock(&fs3270_mutex); |
358 | return rc; | 366 | return rc; |
359 | } | 367 | } |
360 | 368 | ||
@@ -437,7 +445,7 @@ fs3270_open(struct inode *inode, struct file *filp) | |||
437 | minor = tty->index + RAW3270_FIRSTMINOR; | 445 | minor = tty->index + RAW3270_FIRSTMINOR; |
438 | tty_kref_put(tty); | 446 | tty_kref_put(tty); |
439 | } | 447 | } |
440 | lock_kernel(); | 448 | mutex_lock(&fs3270_mutex); |
441 | /* Check if some other program is already using fullscreen mode. */ | 449 | /* Check if some other program is already using fullscreen mode. */ |
442 | fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); | 450 | fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); |
443 | if (!IS_ERR(fp)) { | 451 | if (!IS_ERR(fp)) { |
@@ -465,7 +473,7 @@ fs3270_open(struct inode *inode, struct file *filp) | |||
465 | if (IS_ERR(ib)) { | 473 | if (IS_ERR(ib)) { |
466 | raw3270_put_view(&fp->view); | 474 | raw3270_put_view(&fp->view); |
467 | raw3270_del_view(&fp->view); | 475 | raw3270_del_view(&fp->view); |
468 | rc = PTR_ERR(fp); | 476 | rc = PTR_ERR(ib); |
469 | goto out; | 477 | goto out; |
470 | } | 478 | } |
471 | fp->rdbuf = ib; | 479 | fp->rdbuf = ib; |
@@ -478,7 +486,7 @@ fs3270_open(struct inode *inode, struct file *filp) | |||
478 | } | 486 | } |
479 | filp->private_data = fp; | 487 | filp->private_data = fp; |
480 | out: | 488 | out: |
481 | unlock_kernel(); | 489 | mutex_unlock(&fs3270_mutex); |
482 | return rc; | 490 | return rc; |
483 | } | 491 | } |
484 | 492 | ||
@@ -509,8 +517,8 @@ static const struct file_operations fs3270_fops = { | |||
509 | .write = fs3270_write, /* write */ | 517 | .write = fs3270_write, /* write */ |
510 | .unlocked_ioctl = fs3270_ioctl, /* ioctl */ | 518 | .unlocked_ioctl = fs3270_ioctl, /* ioctl */ |
511 | .compat_ioctl = fs3270_ioctl, /* ioctl */ | 519 | .compat_ioctl = fs3270_ioctl, /* ioctl */ |
512 | .open = fs3270_open, /* open */ | 520 | .open = fs3270_open, /* open */ |
513 | .release = fs3270_close, /* release */ | 521 | .release = fs3270_close, /* release */ |
514 | }; | 522 | }; |
515 | 523 | ||
516 | /* | 524 | /* |
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index cee4d4e42429..cb6bffe7141a 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | #include <linux/slab.h> | ||
12 | #include <linux/sysrq.h> | 13 | #include <linux/sysrq.h> |
13 | 14 | ||
14 | #include <linux/consolemap.h> | 15 | #include <linux/consolemap.h> |
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 66e21dd23154..2ed3f82e5c30 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> |
@@ -22,6 +21,7 @@ | |||
22 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
23 | #include <linux/poll.h> | 22 | #include <linux/poll.h> |
24 | #include <linux/device.h> | 23 | #include <linux/device.h> |
24 | #include <linux/slab.h> | ||
25 | #include <net/iucv/iucv.h> | 25 | #include <net/iucv/iucv.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/ebcdic.h> | 27 | #include <asm/ebcdic.h> |
@@ -283,7 +283,6 @@ static int mon_open(struct inode *inode, struct file *filp) | |||
283 | /* | 283 | /* |
284 | * only one user allowed | 284 | * only one user allowed |
285 | */ | 285 | */ |
286 | lock_kernel(); | ||
287 | rc = -EBUSY; | 286 | rc = -EBUSY; |
288 | if (test_and_set_bit(MON_IN_USE, &mon_in_use)) | 287 | if (test_and_set_bit(MON_IN_USE, &mon_in_use)) |
289 | goto out; | 288 | goto out; |
@@ -321,7 +320,6 @@ static int mon_open(struct inode *inode, struct file *filp) | |||
321 | } | 320 | } |
322 | filp->private_data = monpriv; | 321 | filp->private_data = monpriv; |
323 | dev_set_drvdata(monreader_device, monpriv); | 322 | dev_set_drvdata(monreader_device, monpriv); |
324 | unlock_kernel(); | ||
325 | return nonseekable_open(inode, filp); | 323 | return nonseekable_open(inode, filp); |
326 | 324 | ||
327 | out_path: | 325 | out_path: |
@@ -331,7 +329,6 @@ out_priv: | |||
331 | out_use: | 329 | out_use: |
332 | clear_bit(MON_IN_USE, &mon_in_use); | 330 | clear_bit(MON_IN_USE, &mon_in_use); |
333 | out: | 331 | out: |
334 | unlock_kernel(); | ||
335 | return rc; | 332 | return rc; |
336 | } | 333 | } |
337 | 334 | ||
@@ -533,7 +530,7 @@ static int monreader_restore(struct device *dev) | |||
533 | return monreader_thaw(dev); | 530 | return monreader_thaw(dev); |
534 | } | 531 | } |
535 | 532 | ||
536 | static struct dev_pm_ops monreader_pm_ops = { | 533 | static const struct dev_pm_ops monreader_pm_ops = { |
537 | .freeze = monreader_freeze, | 534 | .freeze = monreader_freeze, |
538 | .thaw = monreader_thaw, | 535 | .thaw = monreader_thaw, |
539 | .restore = monreader_restore, | 536 | .restore = monreader_restore, |
@@ -607,6 +604,10 @@ static int __init mon_init(void) | |||
607 | } | 604 | } |
608 | dcss_mkname(mon_dcss_name, &user_data_connect[8]); | 605 | dcss_mkname(mon_dcss_name, &user_data_connect[8]); |
609 | 606 | ||
607 | /* | ||
608 | * misc_register() has to be the last action in module_init(), because | ||
609 | * file operations will be available right after this. | ||
610 | */ | ||
610 | rc = misc_register(&mon_dev); | 611 | rc = misc_register(&mon_dev); |
611 | if (rc < 0 ) | 612 | if (rc < 0 ) |
612 | goto out; | 613 | goto out; |
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index 66fb8eba93f4..98a49dfda1de 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> |
@@ -21,6 +20,7 @@ | |||
21 | #include <linux/poll.h> | 20 | #include <linux/poll.h> |
22 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
23 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/slab.h> | ||
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | #include <asm/ebcdic.h> | 25 | #include <asm/ebcdic.h> |
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
@@ -185,13 +185,11 @@ static int monwrite_open(struct inode *inode, struct file *filp) | |||
185 | monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); | 185 | monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); |
186 | if (!monpriv) | 186 | if (!monpriv) |
187 | return -ENOMEM; | 187 | return -ENOMEM; |
188 | lock_kernel(); | ||
189 | INIT_LIST_HEAD(&monpriv->list); | 188 | INIT_LIST_HEAD(&monpriv->list); |
190 | monpriv->hdr_to_read = sizeof(monpriv->hdr); | 189 | monpriv->hdr_to_read = sizeof(monpriv->hdr); |
191 | mutex_init(&monpriv->thread_mutex); | 190 | mutex_init(&monpriv->thread_mutex); |
192 | filp->private_data = monpriv; | 191 | filp->private_data = monpriv; |
193 | list_add_tail(&monpriv->priv_list, &mon_priv_list); | 192 | list_add_tail(&monpriv->priv_list, &mon_priv_list); |
194 | unlock_kernel(); | ||
195 | return nonseekable_open(inode, filp); | 193 | return nonseekable_open(inode, filp); |
196 | } | 194 | } |
197 | 195 | ||
@@ -326,7 +324,7 @@ static int monwriter_thaw(struct device *dev) | |||
326 | return monwriter_restore(dev); | 324 | return monwriter_restore(dev); |
327 | } | 325 | } |
328 | 326 | ||
329 | static struct dev_pm_ops monwriter_pm_ops = { | 327 | static const struct dev_pm_ops monwriter_pm_ops = { |
330 | .freeze = monwriter_freeze, | 328 | .freeze = monwriter_freeze, |
331 | .thaw = monwriter_thaw, | 329 | .thaw = monwriter_thaw, |
332 | .restore = monwriter_restore, | 330 | .restore = monwriter_restore, |
@@ -364,6 +362,10 @@ static int __init mon_init(void) | |||
364 | goto out_driver; | 362 | goto out_driver; |
365 | } | 363 | } |
366 | 364 | ||
365 | /* | ||
366 | * misc_register() has to be the last action in module_init(), because | ||
367 | * file operations will be available right after this. | ||
368 | */ | ||
367 | rc = misc_register(&mon_dev); | 369 | rc = misc_register(&mon_dev); |
368 | if (rc) | 370 | if (rc) |
369 | goto out_device; | 371 | goto out_device; |
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 62ddf5202b79..2a4c566456e7 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c | |||
@@ -373,7 +373,7 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
373 | rq->rc = ccw_device_start(rp->cdev, &rq->ccw, | 373 | rq->rc = ccw_device_start(rp->cdev, &rq->ccw, |
374 | (unsigned long) rq, 0, 0); | 374 | (unsigned long) rq, 0, 0); |
375 | if (rq->rc == 0) | 375 | if (rq->rc == 0) |
376 | return; /* Sucessfully restarted. */ | 376 | return; /* Successfully restarted. */ |
377 | break; | 377 | break; |
378 | case RAW3270_IO_STOP: | 378 | case RAW3270_IO_STOP: |
379 | if (!rq) | 379 | if (!rq) |
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index a983f5086788..f6d72e1f2a38 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
@@ -196,7 +196,7 @@ __sclp_start_request(struct sclp_req *req) | |||
196 | req->start_count++; | 196 | req->start_count++; |
197 | 197 | ||
198 | if (rc == 0) { | 198 | if (rc == 0) { |
199 | /* Sucessfully started request */ | 199 | /* Successfully started request */ |
200 | req->status = SCLP_REQ_RUNNING; | 200 | req->status = SCLP_REQ_RUNNING; |
201 | sclp_running_state = sclp_running_state_running; | 201 | sclp_running_state = sclp_running_state_running; |
202 | __sclp_set_request_timer(SCLP_RETRY_INTERVAL * HZ, | 202 | __sclp_set_request_timer(SCLP_RETRY_INTERVAL * HZ, |
@@ -1019,7 +1019,7 @@ static int sclp_restore(struct device *dev) | |||
1019 | return sclp_undo_suspend(SCLP_PM_EVENT_RESTORE); | 1019 | return sclp_undo_suspend(SCLP_PM_EVENT_RESTORE); |
1020 | } | 1020 | } |
1021 | 1021 | ||
1022 | static struct dev_pm_ops sclp_pm_ops = { | 1022 | static const struct dev_pm_ops sclp_pm_ops = { |
1023 | .freeze = sclp_freeze, | 1023 | .freeze = sclp_freeze, |
1024 | .thaw = sclp_thaw, | 1024 | .thaw = sclp_thaw, |
1025 | .restore = sclp_restore, | 1025 | .restore = sclp_restore, |
diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c index b44462a6c6d3..7ad30e72f868 100644 --- a/drivers/s390/char/sclp_async.c +++ b/drivers/s390/char/sclp_async.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include <linux/stat.h> | 12 | #include <linux/stat.h> |
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
15 | #include <linux/kmod.h> | 16 | #include <linux/kmod.h> |
16 | #include <linux/err.h> | 17 | #include <linux/err.h> |
@@ -84,6 +85,7 @@ static int proc_handler_callhome(struct ctl_table *ctl, int write, | |||
84 | rc = copy_from_user(buf, buffer, sizeof(buf)); | 85 | rc = copy_from_user(buf, buffer, sizeof(buf)); |
85 | if (rc != 0) | 86 | if (rc != 0) |
86 | return -EFAULT; | 87 | return -EFAULT; |
88 | buf[sizeof(buf) - 1] = '\0'; | ||
87 | if (strict_strtoul(buf, 0, &val) != 0) | 89 | if (strict_strtoul(buf, 0, &val) != 0) |
88 | return -EINVAL; | 90 | return -EINVAL; |
89 | if (val != 0 && val != 1) | 91 | if (val != 0 && val != 1) |
@@ -101,18 +103,17 @@ static struct ctl_table callhome_table[] = { | |||
101 | .mode = 0644, | 103 | .mode = 0644, |
102 | .proc_handler = proc_handler_callhome, | 104 | .proc_handler = proc_handler_callhome, |
103 | }, | 105 | }, |
104 | { .ctl_name = 0 } | 106 | {} |
105 | }; | 107 | }; |
106 | 108 | ||
107 | static struct ctl_table kern_dir_table[] = { | 109 | static struct ctl_table kern_dir_table[] = { |
108 | { | 110 | { |
109 | .ctl_name = CTL_KERN, | ||
110 | .procname = "kernel", | 111 | .procname = "kernel", |
111 | .maxlen = 0, | 112 | .maxlen = 0, |
112 | .mode = 0555, | 113 | .mode = 0555, |
113 | .child = callhome_table, | 114 | .child = callhome_table, |
114 | }, | 115 | }, |
115 | { .ctl_name = 0 } | 116 | {} |
116 | }; | 117 | }; |
117 | 118 | ||
118 | /* | 119 | /* |
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 5cc11c636d38..4b60ede07f0e 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); |
@@ -307,6 +308,13 @@ struct assign_storage_sccb { | |||
307 | u16 rn; | 308 | u16 rn; |
308 | } __packed; | 309 | } __packed; |
309 | 310 | ||
311 | int arch_get_memory_phys_device(unsigned long start_pfn) | ||
312 | { | ||
313 | if (!rzm) | ||
314 | return 0; | ||
315 | return PFN_PHYS(start_pfn) >> ilog2(rzm); | ||
316 | } | ||
317 | |||
310 | static unsigned long long rn2addr(u16 rn) | 318 | static unsigned long long rn2addr(u16 rn) |
311 | { | 319 | { |
312 | return (unsigned long long) (rn - 1) * rzm; | 320 | return (unsigned long long) (rn - 1) * rzm; |
@@ -546,7 +554,7 @@ struct read_storage_sccb { | |||
546 | u32 entries[0]; | 554 | u32 entries[0]; |
547 | } __packed; | 555 | } __packed; |
548 | 556 | ||
549 | static struct dev_pm_ops sclp_mem_pm_ops = { | 557 | static const struct dev_pm_ops sclp_mem_pm_ops = { |
550 | .freeze = sclp_mem_freeze, | 558 | .freeze = sclp_mem_freeze, |
551 | }; | 559 | }; |
552 | 560 | ||
diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index ad698d30cb3b..ecf45c54f8c4 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/termios.h> | 14 | #include <linux/termios.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/reboot.h> | 16 | #include <linux/reboot.h> |
17 | #include <linux/gfp.h> | ||
17 | 18 | ||
18 | #include "sclp.h" | 19 | #include "sclp.h" |
19 | #include "sclp_rw.h" | 20 | #include "sclp_rw.h" |
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 434ba04b1309..8258d590505f 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c | |||
@@ -13,10 +13,10 @@ | |||
13 | #include <linux/tty.h> | 13 | #include <linux/tty.h> |
14 | #include <linux/tty_driver.h> | 14 | #include <linux/tty_driver.h> |
15 | #include <linux/tty_flip.h> | 15 | #include <linux/tty_flip.h> |
16 | #include <linux/slab.h> | ||
17 | #include <linux/err.h> | 16 | #include <linux/err.h> |
18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
19 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/gfp.h> | ||
20 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
21 | 21 | ||
22 | #include "ctrlchar.h" | 22 | #include "ctrlchar.h" |
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index b9d2a007e93b..5d706e6c946f 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/reboot.h> | 25 | #include <linux/reboot.h> |
26 | #include <linux/slab.h> | ||
26 | 27 | ||
27 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
28 | #include "sclp.h" | 29 | #include "sclp.h" |
@@ -495,6 +496,10 @@ sclp_vt220_open(struct tty_struct *tty, struct file *filp) | |||
495 | if (tty->driver_data == NULL) | 496 | if (tty->driver_data == NULL) |
496 | return -ENOMEM; | 497 | return -ENOMEM; |
497 | tty->low_latency = 0; | 498 | tty->low_latency = 0; |
499 | if (!tty->winsize.ws_row && !tty->winsize.ws_col) { | ||
500 | tty->winsize.ws_row = 24; | ||
501 | tty->winsize.ws_col = 80; | ||
502 | } | ||
498 | } | 503 | } |
499 | return 0; | 504 | return 0; |
500 | } | 505 | } |
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 *); | |||
292 | extern int tape_generic_probe(struct ccw_device *); | 295 | extern int tape_generic_probe(struct ccw_device *); |
293 | extern void tape_generic_remove(struct ccw_device *); | 296 | extern void tape_generic_remove(struct ccw_device *); |
294 | 297 | ||
295 | extern struct tape_device *tape_get_device(int devindex); | 298 | extern struct tape_device *tape_find_device(int devindex); |
296 | extern struct tape_device *tape_get_device_reference(struct tape_device *); | 299 | extern struct tape_device *tape_get_device(struct tape_device *); |
297 | extern struct tape_device *tape_put_device(struct tape_device *); | 300 | extern void tape_put_device(struct tape_device *); |
298 | 301 | ||
299 | /* Externals from tape_char.c */ | 302 | /* Externals from tape_char.c */ |
300 | extern int tapechar_init(void); | 303 | extern int tapechar_init(void); |
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 2fe45ff77b75..c17f35b6136a 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c | |||
@@ -9,11 +9,13 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define KMSG_COMPONENT "tape_34xx" | 11 | #define KMSG_COMPONENT "tape_34xx" |
12 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
12 | 13 | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <linux/bio.h> | 16 | #include <linux/bio.h> |
16 | #include <linux/workqueue.h> | 17 | #include <linux/workqueue.h> |
18 | #include <linux/slab.h> | ||
17 | 19 | ||
18 | #define TAPE_DBF_AREA tape_34xx_dbf | 20 | #define TAPE_DBF_AREA tape_34xx_dbf |
19 | 21 | ||
@@ -113,16 +115,16 @@ tape_34xx_work_handler(struct work_struct *work) | |||
113 | { | 115 | { |
114 | struct tape_34xx_work *p = | 116 | struct tape_34xx_work *p = |
115 | container_of(work, struct tape_34xx_work, work); | 117 | container_of(work, struct tape_34xx_work, work); |
118 | struct tape_device *device = p->device; | ||
116 | 119 | ||
117 | switch(p->op) { | 120 | switch(p->op) { |
118 | case TO_MSEN: | 121 | case TO_MSEN: |
119 | tape_34xx_medium_sense(p->device); | 122 | tape_34xx_medium_sense(device); |
120 | break; | 123 | break; |
121 | default: | 124 | default: |
122 | DBF_EVENT(3, "T34XX: internal error: unknown work\n"); | 125 | DBF_EVENT(3, "T34XX: internal error: unknown work\n"); |
123 | } | 126 | } |
124 | 127 | tape_put_device(device); | |
125 | p->device = tape_put_device(p->device); | ||
126 | kfree(p); | 128 | kfree(p); |
127 | } | 129 | } |
128 | 130 | ||
@@ -136,7 +138,7 @@ tape_34xx_schedule_work(struct tape_device *device, enum tape_op op) | |||
136 | 138 | ||
137 | INIT_WORK(&p->work, tape_34xx_work_handler); | 139 | INIT_WORK(&p->work, tape_34xx_work_handler); |
138 | 140 | ||
139 | p->device = tape_get_device_reference(device); | 141 | p->device = tape_get_device(device); |
140 | p->op = op; | 142 | p->op = op; |
141 | 143 | ||
142 | schedule_work(&p->work); | 144 | schedule_work(&p->work); |
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index e4cc3aae9162..fc993acf99b6 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -9,8 +9,10 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define KMSG_COMPONENT "tape_3590" | 11 | #define KMSG_COMPONENT "tape_3590" |
12 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
12 | 13 | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/slab.h> | ||
14 | #include <linux/init.h> | 16 | #include <linux/init.h> |
15 | #include <linux/bio.h> | 17 | #include <linux/bio.h> |
16 | #include <asm/ebcdic.h> | 18 | #include <asm/ebcdic.h> |
@@ -136,7 +138,7 @@ static void int_to_ext_kekl(struct tape3592_kekl *in, | |||
136 | out->type_on_tape = TAPE390_KEKL_TYPE_LABEL; | 138 | out->type_on_tape = TAPE390_KEKL_TYPE_LABEL; |
137 | memcpy(out->label, in->label, sizeof(in->label)); | 139 | memcpy(out->label, in->label, sizeof(in->label)); |
138 | EBCASC(out->label, sizeof(in->label)); | 140 | EBCASC(out->label, sizeof(in->label)); |
139 | strstrip(out->label); | 141 | strim(out->label); |
140 | } | 142 | } |
141 | 143 | ||
142 | static void int_to_ext_kekl_pair(struct tape3592_kekl_pair *in, | 144 | static void int_to_ext_kekl_pair(struct tape3592_kekl_pair *in, |
@@ -608,7 +610,7 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op) | |||
608 | 610 | ||
609 | INIT_WORK(&p->work, tape_3590_work_handler); | 611 | INIT_WORK(&p->work, tape_3590_work_handler); |
610 | 612 | ||
611 | p->device = tape_get_device_reference(device); | 613 | p->device = tape_get_device(device); |
612 | p->op = op; | 614 | p->op = op; |
613 | 615 | ||
614 | schedule_work(&p->work); | 616 | schedule_work(&p->work); |
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 0c0705b91c28..097da8ce6be6 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define KMSG_COMPONENT "tape" | 13 | #define KMSG_COMPONENT "tape" |
14 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
14 | 15 | ||
15 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
@@ -45,8 +46,6 @@ | |||
45 | */ | 46 | */ |
46 | static int tapeblock_open(struct block_device *, fmode_t); | 47 | static int tapeblock_open(struct block_device *, fmode_t); |
47 | static int tapeblock_release(struct gendisk *, fmode_t); | 48 | static int tapeblock_release(struct gendisk *, fmode_t); |
48 | static int tapeblock_ioctl(struct block_device *, fmode_t, unsigned int, | ||
49 | unsigned long); | ||
50 | static int tapeblock_medium_changed(struct gendisk *); | 49 | static int tapeblock_medium_changed(struct gendisk *); |
51 | static int tapeblock_revalidate_disk(struct gendisk *); | 50 | static int tapeblock_revalidate_disk(struct gendisk *); |
52 | 51 | ||
@@ -54,7 +53,6 @@ static const struct block_device_operations tapeblock_fops = { | |||
54 | .owner = THIS_MODULE, | 53 | .owner = THIS_MODULE, |
55 | .open = tapeblock_open, | 54 | .open = tapeblock_open, |
56 | .release = tapeblock_release, | 55 | .release = tapeblock_release, |
57 | .locked_ioctl = tapeblock_ioctl, | ||
58 | .media_changed = tapeblock_medium_changed, | 56 | .media_changed = tapeblock_medium_changed, |
59 | .revalidate_disk = tapeblock_revalidate_disk, | 57 | .revalidate_disk = tapeblock_revalidate_disk, |
60 | }; | 58 | }; |
@@ -224,9 +222,8 @@ tapeblock_setup_device(struct tape_device * device) | |||
224 | goto cleanup_queue; | 222 | goto cleanup_queue; |
225 | 223 | ||
226 | blk_queue_logical_block_size(blkdat->request_queue, TAPEBLOCK_HSEC_SIZE); | 224 | blk_queue_logical_block_size(blkdat->request_queue, TAPEBLOCK_HSEC_SIZE); |
227 | blk_queue_max_sectors(blkdat->request_queue, TAPEBLOCK_MAX_SEC); | 225 | blk_queue_max_hw_sectors(blkdat->request_queue, TAPEBLOCK_MAX_SEC); |
228 | blk_queue_max_phys_segments(blkdat->request_queue, -1L); | 226 | blk_queue_max_segments(blkdat->request_queue, -1L); |
229 | blk_queue_max_hw_segments(blkdat->request_queue, -1L); | ||
230 | blk_queue_max_segment_size(blkdat->request_queue, -1L); | 227 | blk_queue_max_segment_size(blkdat->request_queue, -1L); |
231 | blk_queue_segment_boundary(blkdat->request_queue, -1L); | 228 | blk_queue_segment_boundary(blkdat->request_queue, -1L); |
232 | 229 | ||
@@ -239,7 +236,7 @@ tapeblock_setup_device(struct tape_device * device) | |||
239 | disk->major = tapeblock_major; | 236 | disk->major = tapeblock_major; |
240 | disk->first_minor = device->first_minor; | 237 | disk->first_minor = device->first_minor; |
241 | disk->fops = &tapeblock_fops; | 238 | disk->fops = &tapeblock_fops; |
242 | disk->private_data = tape_get_device_reference(device); | 239 | disk->private_data = tape_get_device(device); |
243 | disk->queue = blkdat->request_queue; | 240 | disk->queue = blkdat->request_queue; |
244 | set_capacity(disk, 0); | 241 | set_capacity(disk, 0); |
245 | sprintf(disk->disk_name, "btibm%d", | 242 | sprintf(disk->disk_name, "btibm%d", |
@@ -247,11 +244,11 @@ tapeblock_setup_device(struct tape_device * device) | |||
247 | 244 | ||
248 | blkdat->disk = disk; | 245 | blkdat->disk = disk; |
249 | blkdat->medium_changed = 1; | 246 | blkdat->medium_changed = 1; |
250 | blkdat->request_queue->queuedata = tape_get_device_reference(device); | 247 | blkdat->request_queue->queuedata = tape_get_device(device); |
251 | 248 | ||
252 | add_disk(disk); | 249 | add_disk(disk); |
253 | 250 | ||
254 | tape_get_device_reference(device); | 251 | tape_get_device(device); |
255 | INIT_WORK(&blkdat->requeue_task, tapeblock_requeue); | 252 | INIT_WORK(&blkdat->requeue_task, tapeblock_requeue); |
256 | 253 | ||
257 | return 0; | 254 | return 0; |
@@ -274,13 +271,14 @@ tapeblock_cleanup_device(struct tape_device *device) | |||
274 | } | 271 | } |
275 | 272 | ||
276 | del_gendisk(device->blk_data.disk); | 273 | del_gendisk(device->blk_data.disk); |
277 | device->blk_data.disk->private_data = | 274 | device->blk_data.disk->private_data = NULL; |
278 | tape_put_device(device->blk_data.disk->private_data); | 275 | tape_put_device(device); |
279 | put_disk(device->blk_data.disk); | 276 | put_disk(device->blk_data.disk); |
280 | 277 | ||
281 | device->blk_data.disk = NULL; | 278 | device->blk_data.disk = NULL; |
282 | cleanup_queue: | 279 | cleanup_queue: |
283 | device->blk_data.request_queue->queuedata = tape_put_device(device); | 280 | device->blk_data.request_queue->queuedata = NULL; |
281 | tape_put_device(device); | ||
284 | 282 | ||
285 | blk_cleanup_queue(device->blk_data.request_queue); | 283 | blk_cleanup_queue(device->blk_data.request_queue); |
286 | device->blk_data.request_queue = NULL; | 284 | device->blk_data.request_queue = NULL; |
@@ -363,7 +361,7 @@ tapeblock_open(struct block_device *bdev, fmode_t mode) | |||
363 | struct tape_device * device; | 361 | struct tape_device * device; |
364 | int rc; | 362 | int rc; |
365 | 363 | ||
366 | device = tape_get_device_reference(disk->private_data); | 364 | device = tape_get_device(disk->private_data); |
367 | 365 | ||
368 | if (device->required_tapemarks) { | 366 | if (device->required_tapemarks) { |
369 | DBF_EVENT(2, "TBLOCK: missing tapemarks\n"); | 367 | DBF_EVENT(2, "TBLOCK: missing tapemarks\n"); |
@@ -414,42 +412,6 @@ tapeblock_release(struct gendisk *disk, fmode_t mode) | |||
414 | } | 412 | } |
415 | 413 | ||
416 | /* | 414 | /* |
417 | * Support of some generic block device IOCTLs. | ||
418 | */ | ||
419 | static int | ||
420 | tapeblock_ioctl( | ||
421 | struct block_device * bdev, | ||
422 | fmode_t mode, | ||
423 | unsigned int command, | ||
424 | unsigned long arg | ||
425 | ) { | ||
426 | int rc; | ||
427 | int minor; | ||
428 | struct gendisk *disk = bdev->bd_disk; | ||
429 | struct tape_device *device; | ||
430 | |||
431 | rc = 0; | ||
432 | BUG_ON(!disk); | ||
433 | device = disk->private_data; | ||
434 | BUG_ON(!device); | ||
435 | minor = MINOR(bdev->bd_dev); | ||
436 | |||
437 | DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command); | ||
438 | DBF_LH(6, "device = %d:%d\n", tapeblock_major, minor); | ||
439 | |||
440 | switch (command) { | ||
441 | /* Refuse some IOCTL calls without complaining (mount). */ | ||
442 | case 0x5310: /* CDROMMULTISESSION */ | ||
443 | rc = -EINVAL; | ||
444 | break; | ||
445 | default: | ||
446 | rc = -EINVAL; | ||
447 | } | ||
448 | |||
449 | return rc; | ||
450 | } | ||
451 | |||
452 | /* | ||
453 | * Initialize block device frontend. | 415 | * Initialize block device frontend. |
454 | */ | 416 | */ |
455 | int | 417 | 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 @@ | |||
10 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 10 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define KMSG_COMPONENT "tape" | ||
14 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
15 | |||
13 | #include <linux/module.h> | 16 | #include <linux/module.h> |
14 | #include <linux/types.h> | 17 | #include <linux/types.h> |
15 | #include <linux/proc_fs.h> | 18 | #include <linux/proc_fs.h> |
16 | #include <linux/mtio.h> | 19 | #include <linux/mtio.h> |
17 | #include <linux/smp_lock.h> | 20 | #include <linux/smp_lock.h> |
21 | #include <linux/compat.h> | ||
18 | 22 | ||
19 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
20 | 24 | ||
@@ -33,18 +37,20 @@ static ssize_t tapechar_read(struct file *, char __user *, size_t, loff_t *); | |||
33 | static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *); | 37 | static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *); |
34 | static int tapechar_open(struct inode *,struct file *); | 38 | static int tapechar_open(struct inode *,struct file *); |
35 | static int tapechar_release(struct inode *,struct file *); | 39 | static int tapechar_release(struct inode *,struct file *); |
36 | static int tapechar_ioctl(struct inode *, struct file *, unsigned int, | 40 | static long tapechar_ioctl(struct file *, unsigned int, unsigned long); |
37 | unsigned long); | 41 | #ifdef CONFIG_COMPAT |
38 | static long tapechar_compat_ioctl(struct file *, unsigned int, | 42 | static long tapechar_compat_ioctl(struct file *, unsigned int, unsigned long); |
39 | unsigned long); | 43 | #endif |
40 | 44 | ||
41 | static const struct file_operations tape_fops = | 45 | static const struct file_operations tape_fops = |
42 | { | 46 | { |
43 | .owner = THIS_MODULE, | 47 | .owner = THIS_MODULE, |
44 | .read = tapechar_read, | 48 | .read = tapechar_read, |
45 | .write = tapechar_write, | 49 | .write = tapechar_write, |
46 | .ioctl = tapechar_ioctl, | 50 | .unlocked_ioctl = tapechar_ioctl, |
51 | #ifdef CONFIG_COMPAT | ||
47 | .compat_ioctl = tapechar_compat_ioctl, | 52 | .compat_ioctl = tapechar_compat_ioctl, |
53 | #endif | ||
48 | .open = tapechar_open, | 54 | .open = tapechar_open, |
49 | .release = tapechar_release, | 55 | .release = tapechar_release, |
50 | }; | 56 | }; |
@@ -170,7 +176,6 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) | |||
170 | if (rc == 0) { | 176 | if (rc == 0) { |
171 | rc = block_size - request->rescnt; | 177 | rc = block_size - request->rescnt; |
172 | DBF_EVENT(6, "TCHAR:rbytes: %x\n", rc); | 178 | DBF_EVENT(6, "TCHAR:rbytes: %x\n", rc); |
173 | filp->f_pos += rc; | ||
174 | /* Copy data from idal buffer to user space. */ | 179 | /* Copy data from idal buffer to user space. */ |
175 | if (idal_buffer_to_user(device->char_data.idal_buf, | 180 | if (idal_buffer_to_user(device->char_data.idal_buf, |
176 | data, rc) != 0) | 181 | data, rc) != 0) |
@@ -238,7 +243,6 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t | |||
238 | break; | 243 | break; |
239 | DBF_EVENT(6, "TCHAR:wbytes: %lx\n", | 244 | DBF_EVENT(6, "TCHAR:wbytes: %lx\n", |
240 | block_size - request->rescnt); | 245 | block_size - request->rescnt); |
241 | filp->f_pos += block_size - request->rescnt; | ||
242 | written += block_size - request->rescnt; | 246 | written += block_size - request->rescnt; |
243 | if (request->rescnt != 0) | 247 | if (request->rescnt != 0) |
244 | break; | 248 | break; |
@@ -286,26 +290,20 @@ tapechar_open (struct inode *inode, struct file *filp) | |||
286 | if (imajor(filp->f_path.dentry->d_inode) != tapechar_major) | 290 | if (imajor(filp->f_path.dentry->d_inode) != tapechar_major) |
287 | return -ENODEV; | 291 | return -ENODEV; |
288 | 292 | ||
289 | lock_kernel(); | ||
290 | minor = iminor(filp->f_path.dentry->d_inode); | 293 | minor = iminor(filp->f_path.dentry->d_inode); |
291 | device = tape_get_device(minor / TAPE_MINORS_PER_DEV); | 294 | device = tape_find_device(minor / TAPE_MINORS_PER_DEV); |
292 | if (IS_ERR(device)) { | 295 | if (IS_ERR(device)) { |
293 | DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n"); | 296 | DBF_EVENT(3, "TCHAR:open: tape_find_device() failed\n"); |
294 | rc = PTR_ERR(device); | 297 | return PTR_ERR(device); |
295 | goto out; | ||
296 | } | 298 | } |
297 | 299 | ||
298 | |||
299 | rc = tape_open(device); | 300 | rc = tape_open(device); |
300 | if (rc == 0) { | 301 | if (rc == 0) { |
301 | filp->private_data = device; | 302 | filp->private_data = device; |
302 | rc = nonseekable_open(inode, filp); | 303 | nonseekable_open(inode, filp); |
303 | } | 304 | } else |
304 | else | ||
305 | tape_put_device(device); | 305 | tape_put_device(device); |
306 | 306 | ||
307 | out: | ||
308 | unlock_kernel(); | ||
309 | return rc; | 307 | return rc; |
310 | } | 308 | } |
311 | 309 | ||
@@ -342,7 +340,8 @@ tapechar_release(struct inode *inode, struct file *filp) | |||
342 | device->char_data.idal_buf = NULL; | 340 | device->char_data.idal_buf = NULL; |
343 | } | 341 | } |
344 | tape_release(device); | 342 | tape_release(device); |
345 | filp->private_data = tape_put_device(device); | 343 | filp->private_data = NULL; |
344 | tape_put_device(device); | ||
346 | 345 | ||
347 | return 0; | 346 | return 0; |
348 | } | 347 | } |
@@ -351,16 +350,11 @@ tapechar_release(struct inode *inode, struct file *filp) | |||
351 | * Tape device io controls. | 350 | * Tape device io controls. |
352 | */ | 351 | */ |
353 | static int | 352 | static int |
354 | tapechar_ioctl(struct inode *inp, struct file *filp, | 353 | __tapechar_ioctl(struct tape_device *device, |
355 | unsigned int no, unsigned long data) | 354 | unsigned int no, unsigned long data) |
356 | { | 355 | { |
357 | struct tape_device *device; | ||
358 | int rc; | 356 | int rc; |
359 | 357 | ||
360 | DBF_EVENT(6, "TCHAR:ioct\n"); | ||
361 | |||
362 | device = (struct tape_device *) filp->private_data; | ||
363 | |||
364 | if (no == MTIOCTOP) { | 358 | if (no == MTIOCTOP) { |
365 | struct mtop op; | 359 | struct mtop op; |
366 | 360 | ||
@@ -453,21 +447,44 @@ tapechar_ioctl(struct inode *inp, struct file *filp, | |||
453 | } | 447 | } |
454 | 448 | ||
455 | static long | 449 | static long |
450 | tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data) | ||
451 | { | ||
452 | struct tape_device *device; | ||
453 | long rc; | ||
454 | |||
455 | DBF_EVENT(6, "TCHAR:ioct\n"); | ||
456 | |||
457 | device = (struct tape_device *) filp->private_data; | ||
458 | mutex_lock(&device->mutex); | ||
459 | rc = __tapechar_ioctl(device, no, data); | ||
460 | mutex_unlock(&device->mutex); | ||
461 | return rc; | ||
462 | } | ||
463 | |||
464 | #ifdef CONFIG_COMPAT | ||
465 | static long | ||
456 | tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) | 466 | tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) |
457 | { | 467 | { |
458 | struct tape_device *device = filp->private_data; | 468 | struct tape_device *device = filp->private_data; |
459 | int rval = -ENOIOCTLCMD; | 469 | int rval = -ENOIOCTLCMD; |
470 | unsigned long argp; | ||
460 | 471 | ||
472 | /* The 'arg' argument of any ioctl function may only be used for | ||
473 | * pointers because of the compat pointer conversion. | ||
474 | * Consider this when adding new ioctls. | ||
475 | */ | ||
476 | argp = (unsigned long) compat_ptr(data); | ||
461 | if (device->discipline->ioctl_fn) { | 477 | if (device->discipline->ioctl_fn) { |
462 | lock_kernel(); | 478 | mutex_lock(&device->mutex); |
463 | rval = device->discipline->ioctl_fn(device, no, data); | 479 | rval = device->discipline->ioctl_fn(device, no, argp); |
464 | unlock_kernel(); | 480 | mutex_unlock(&device->mutex); |
465 | if (rval == -EINVAL) | 481 | if (rval == -EINVAL) |
466 | rval = -ENOIOCTLCMD; | 482 | rval = -ENOIOCTLCMD; |
467 | } | 483 | } |
468 | 484 | ||
469 | return rval; | 485 | return rval; |
470 | } | 486 | } |
487 | #endif /* CONFIG_COMPAT */ | ||
471 | 488 | ||
472 | /* | 489 | /* |
473 | * Initialize character device frontend. | 490 | * Initialize character device frontend. |
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c index ddc914ccea8f..55343df61edd 100644 --- a/drivers/s390/char/tape_class.c +++ b/drivers/s390/char/tape_class.c | |||
@@ -7,6 +7,12 @@ | |||
7 | * Author: Stefan Bader <shbader@de.ibm.com> | 7 | * Author: Stefan Bader <shbader@de.ibm.com> |
8 | * Based on simple class device code by Greg K-H | 8 | * Based on simple class device code by Greg K-H |
9 | */ | 9 | */ |
10 | |||
11 | #define KMSG_COMPONENT "tape" | ||
12 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
13 | |||
14 | #include <linux/slab.h> | ||
15 | |||
10 | #include "tape_class.h" | 16 | #include "tape_class.h" |
11 | 17 | ||
12 | MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>"); | 18 | 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..29c2d73d719d 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c | |||
@@ -12,12 +12,15 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define KMSG_COMPONENT "tape" | 14 | #define KMSG_COMPONENT "tape" |
15 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
16 | |||
15 | #include <linux/module.h> | 17 | #include <linux/module.h> |
16 | #include <linux/init.h> // for kernel parameters | 18 | #include <linux/init.h> // for kernel parameters |
17 | #include <linux/kmod.h> // for requesting modules | 19 | #include <linux/kmod.h> // for requesting modules |
18 | #include <linux/spinlock.h> // for locks | 20 | #include <linux/spinlock.h> // for locks |
19 | #include <linux/vmalloc.h> | 21 | #include <linux/vmalloc.h> |
20 | #include <linux/list.h> | 22 | #include <linux/list.h> |
23 | #include <linux/slab.h> | ||
21 | 24 | ||
22 | #include <asm/types.h> // for variable types | 25 | #include <asm/types.h> // for variable types |
23 | 26 | ||
@@ -492,6 +495,7 @@ tape_alloc_device(void) | |||
492 | kfree(device); | 495 | kfree(device); |
493 | return ERR_PTR(-ENOMEM); | 496 | return ERR_PTR(-ENOMEM); |
494 | } | 497 | } |
498 | mutex_init(&device->mutex); | ||
495 | INIT_LIST_HEAD(&device->req_queue); | 499 | INIT_LIST_HEAD(&device->req_queue); |
496 | INIT_LIST_HEAD(&device->node); | 500 | INIT_LIST_HEAD(&device->node); |
497 | init_waitqueue_head(&device->state_change_wq); | 501 | init_waitqueue_head(&device->state_change_wq); |
@@ -511,11 +515,12 @@ tape_alloc_device(void) | |||
511 | * increment the reference count. | 515 | * increment the reference count. |
512 | */ | 516 | */ |
513 | struct tape_device * | 517 | struct tape_device * |
514 | tape_get_device_reference(struct tape_device *device) | 518 | tape_get_device(struct tape_device *device) |
515 | { | 519 | { |
516 | DBF_EVENT(4, "tape_get_device_reference(%p) = %i\n", device, | 520 | int count; |
517 | atomic_inc_return(&device->ref_count)); | ||
518 | 521 | ||
522 | count = atomic_inc_return(&device->ref_count); | ||
523 | DBF_EVENT(4, "tape_get_device(%p) = %i\n", device, count); | ||
519 | return device; | 524 | return device; |
520 | } | 525 | } |
521 | 526 | ||
@@ -525,32 +530,25 @@ tape_get_device_reference(struct tape_device *device) | |||
525 | * The function returns a NULL pointer to be used by the caller | 530 | * The function returns a NULL pointer to be used by the caller |
526 | * for clearing reference pointers. | 531 | * for clearing reference pointers. |
527 | */ | 532 | */ |
528 | struct tape_device * | 533 | void |
529 | tape_put_device(struct tape_device *device) | 534 | tape_put_device(struct tape_device *device) |
530 | { | 535 | { |
531 | int remain; | 536 | int count; |
532 | 537 | ||
533 | remain = atomic_dec_return(&device->ref_count); | 538 | count = atomic_dec_return(&device->ref_count); |
534 | if (remain > 0) { | 539 | DBF_EVENT(4, "tape_put_device(%p) -> %i\n", device, count); |
535 | DBF_EVENT(4, "tape_put_device(%p) -> %i\n", device, remain); | 540 | BUG_ON(count < 0); |
536 | } else { | 541 | if (count == 0) { |
537 | if (remain < 0) { | 542 | kfree(device->modeset_byte); |
538 | DBF_EVENT(4, "put device without reference\n"); | 543 | kfree(device); |
539 | } else { | ||
540 | DBF_EVENT(4, "tape_free_device(%p)\n", device); | ||
541 | kfree(device->modeset_byte); | ||
542 | kfree(device); | ||
543 | } | ||
544 | } | 544 | } |
545 | |||
546 | return NULL; | ||
547 | } | 545 | } |
548 | 546 | ||
549 | /* | 547 | /* |
550 | * Find tape device by a device index. | 548 | * Find tape device by a device index. |
551 | */ | 549 | */ |
552 | struct tape_device * | 550 | struct tape_device * |
553 | tape_get_device(int devindex) | 551 | tape_find_device(int devindex) |
554 | { | 552 | { |
555 | struct tape_device *device, *tmp; | 553 | struct tape_device *device, *tmp; |
556 | 554 | ||
@@ -558,7 +556,7 @@ tape_get_device(int devindex) | |||
558 | read_lock(&tape_device_lock); | 556 | read_lock(&tape_device_lock); |
559 | list_for_each_entry(tmp, &tape_device_list, node) { | 557 | list_for_each_entry(tmp, &tape_device_list, node) { |
560 | if (tmp->first_minor / TAPE_MINORS_PER_DEV == devindex) { | 558 | if (tmp->first_minor / TAPE_MINORS_PER_DEV == devindex) { |
561 | device = tape_get_device_reference(tmp); | 559 | device = tape_get_device(tmp); |
562 | break; | 560 | break; |
563 | } | 561 | } |
564 | } | 562 | } |
@@ -579,7 +577,8 @@ tape_generic_probe(struct ccw_device *cdev) | |||
579 | device = tape_alloc_device(); | 577 | device = tape_alloc_device(); |
580 | if (IS_ERR(device)) | 578 | if (IS_ERR(device)) |
581 | return -ENODEV; | 579 | return -ENODEV; |
582 | ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); | 580 | ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP | |
581 | CCWDEV_DO_MULTIPATH); | ||
583 | ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group); | 582 | ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group); |
584 | if (ret) { | 583 | if (ret) { |
585 | tape_put_device(device); | 584 | tape_put_device(device); |
@@ -606,7 +605,8 @@ __tape_discard_requests(struct tape_device *device) | |||
606 | list_del(&request->list); | 605 | list_del(&request->list); |
607 | 606 | ||
608 | /* Decrease ref_count for removed request. */ | 607 | /* Decrease ref_count for removed request. */ |
609 | request->device = tape_put_device(device); | 608 | request->device = NULL; |
609 | tape_put_device(device); | ||
610 | request->rc = -EIO; | 610 | request->rc = -EIO; |
611 | if (request->callback != NULL) | 611 | if (request->callback != NULL) |
612 | request->callback(request, request->callback_data); | 612 | request->callback(request, request->callback_data); |
@@ -664,9 +664,11 @@ tape_generic_remove(struct ccw_device *cdev) | |||
664 | tape_cleanup_device(device); | 664 | tape_cleanup_device(device); |
665 | } | 665 | } |
666 | 666 | ||
667 | if (!dev_get_drvdata(&cdev->dev)) { | 667 | device = dev_get_drvdata(&cdev->dev); |
668 | if (device) { | ||
668 | sysfs_remove_group(&cdev->dev.kobj, &tape_attr_group); | 669 | sysfs_remove_group(&cdev->dev.kobj, &tape_attr_group); |
669 | dev_set_drvdata(&cdev->dev, tape_put_device(dev_get_drvdata(&cdev->dev))); | 670 | dev_set_drvdata(&cdev->dev, NULL); |
671 | tape_put_device(device); | ||
670 | } | 672 | } |
671 | } | 673 | } |
672 | 674 | ||
@@ -721,9 +723,8 @@ tape_free_request (struct tape_request * request) | |||
721 | { | 723 | { |
722 | DBF_LH(6, "Free request %p\n", request); | 724 | DBF_LH(6, "Free request %p\n", request); |
723 | 725 | ||
724 | if (request->device != NULL) { | 726 | if (request->device) |
725 | request->device = tape_put_device(request->device); | 727 | tape_put_device(request->device); |
726 | } | ||
727 | kfree(request->cpdata); | 728 | kfree(request->cpdata); |
728 | kfree(request->cpaddr); | 729 | kfree(request->cpaddr); |
729 | kfree(request); | 730 | kfree(request); |
@@ -838,7 +839,8 @@ static void tape_long_busy_timeout(unsigned long data) | |||
838 | BUG_ON(request->status != TAPE_REQUEST_LONG_BUSY); | 839 | BUG_ON(request->status != TAPE_REQUEST_LONG_BUSY); |
839 | DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id); | 840 | DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id); |
840 | __tape_start_next_request(device); | 841 | __tape_start_next_request(device); |
841 | device->lb_timeout.data = (unsigned long) tape_put_device(device); | 842 | device->lb_timeout.data = 0UL; |
843 | tape_put_device(device); | ||
842 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); | 844 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); |
843 | } | 845 | } |
844 | 846 | ||
@@ -918,7 +920,7 @@ __tape_start_request(struct tape_device *device, struct tape_request *request) | |||
918 | } | 920 | } |
919 | 921 | ||
920 | /* Increase use count of device for the added request. */ | 922 | /* Increase use count of device for the added request. */ |
921 | request->device = tape_get_device_reference(device); | 923 | request->device = tape_get_device(device); |
922 | 924 | ||
923 | if (list_empty(&device->req_queue)) { | 925 | if (list_empty(&device->req_queue)) { |
924 | /* No other requests are on the queue. Start this one. */ | 926 | /* No other requests are on the queue. Start this one. */ |
@@ -1117,8 +1119,8 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1117 | if (req->status == TAPE_REQUEST_LONG_BUSY) { | 1119 | if (req->status == TAPE_REQUEST_LONG_BUSY) { |
1118 | DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id); | 1120 | DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id); |
1119 | if (del_timer(&device->lb_timeout)) { | 1121 | if (del_timer(&device->lb_timeout)) { |
1120 | device->lb_timeout.data = (unsigned long) | 1122 | device->lb_timeout.data = 0UL; |
1121 | tape_put_device(device); | 1123 | tape_put_device(device); |
1122 | __tape_start_next_request(device); | 1124 | __tape_start_next_request(device); |
1123 | } | 1125 | } |
1124 | return; | 1126 | return; |
@@ -1173,7 +1175,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1173 | break; | 1175 | break; |
1174 | case TAPE_IO_LONG_BUSY: | 1176 | case TAPE_IO_LONG_BUSY: |
1175 | device->lb_timeout.data = | 1177 | device->lb_timeout.data = |
1176 | (unsigned long)tape_get_device_reference(device); | 1178 | (unsigned long) tape_get_device(device); |
1177 | device->lb_timeout.expires = jiffies + | 1179 | device->lb_timeout.expires = jiffies + |
1178 | LONG_BUSY_TIMEOUT * HZ; | 1180 | LONG_BUSY_TIMEOUT * HZ; |
1179 | DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id); | 1181 | DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id); |
@@ -1326,7 +1328,7 @@ EXPORT_SYMBOL(tape_generic_online); | |||
1326 | EXPORT_SYMBOL(tape_generic_offline); | 1328 | EXPORT_SYMBOL(tape_generic_offline); |
1327 | EXPORT_SYMBOL(tape_generic_pm_suspend); | 1329 | EXPORT_SYMBOL(tape_generic_pm_suspend); |
1328 | EXPORT_SYMBOL(tape_put_device); | 1330 | EXPORT_SYMBOL(tape_put_device); |
1329 | EXPORT_SYMBOL(tape_get_device_reference); | 1331 | EXPORT_SYMBOL(tape_get_device); |
1330 | EXPORT_SYMBOL(tape_state_verbose); | 1332 | EXPORT_SYMBOL(tape_state_verbose); |
1331 | EXPORT_SYMBOL(tape_op_verbose); | 1333 | EXPORT_SYMBOL(tape_op_verbose); |
1332 | EXPORT_SYMBOL(tape_state_set); | 1334 | 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 @@ | |||
11 | * PROCFS Functions | 11 | * PROCFS Functions |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define KMSG_COMPONENT "tape" | ||
15 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
16 | |||
14 | #include <linux/module.h> | 17 | #include <linux/module.h> |
15 | #include <linux/vmalloc.h> | 18 | #include <linux/vmalloc.h> |
16 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
@@ -45,7 +48,7 @@ static int tape_proc_show(struct seq_file *m, void *v) | |||
45 | seq_printf(m, "TapeNo\tBusID CuType/Model\t" | 48 | seq_printf(m, "TapeNo\tBusID CuType/Model\t" |
46 | "DevType/Model\tBlkSize\tState\tOp\tMedState\n"); | 49 | "DevType/Model\tBlkSize\tState\tOp\tMedState\n"); |
47 | } | 50 | } |
48 | device = tape_get_device(n); | 51 | device = tape_find_device(n); |
49 | if (IS_ERR(device)) | 52 | if (IS_ERR(device)) |
50 | return 0; | 53 | return 0; |
51 | spin_lock_irq(get_ccwdev_lock(device->cdev)); | 54 | 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 @@ | |||
11 | * Stefan Bader <shbader@de.ibm.com> | 11 | * Stefan Bader <shbader@de.ibm.com> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define KMSG_COMPONENT "tape" | ||
15 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
16 | |||
14 | #include <linux/stddef.h> | 17 | #include <linux/stddef.h> |
15 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
16 | #include <linux/bio.h> | 19 | #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 @@ | |||
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 | ||
1736 | static long | ||
1737 | tty3270_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 | |||
1734 | static const struct tty_operations tty3270_ops = { | 1751 | static 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/vmcp.c b/drivers/s390/char/vmcp.c index a6087cec55b4..5bb59d36a6d4 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/miscdevice.h> | 20 | #include <linux/miscdevice.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/slab.h> | ||
23 | #include <asm/compat.h> | ||
22 | #include <asm/cpcmd.h> | 24 | #include <asm/cpcmd.h> |
23 | #include <asm/debug.h> | 25 | #include <asm/debug.h> |
24 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
@@ -139,21 +141,26 @@ vmcp_write(struct file *file, const char __user *buff, size_t count, | |||
139 | static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 141 | static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
140 | { | 142 | { |
141 | struct vmcp_session *session; | 143 | struct vmcp_session *session; |
144 | int __user *argp; | ||
142 | int temp; | 145 | int temp; |
143 | 146 | ||
144 | session = (struct vmcp_session *)file->private_data; | 147 | session = (struct vmcp_session *)file->private_data; |
148 | if (is_compat_task()) | ||
149 | argp = compat_ptr(arg); | ||
150 | else | ||
151 | argp = (int __user *)arg; | ||
145 | if (mutex_lock_interruptible(&session->mutex)) | 152 | if (mutex_lock_interruptible(&session->mutex)) |
146 | return -ERESTARTSYS; | 153 | return -ERESTARTSYS; |
147 | switch (cmd) { | 154 | switch (cmd) { |
148 | case VMCP_GETCODE: | 155 | case VMCP_GETCODE: |
149 | temp = session->resp_code; | 156 | temp = session->resp_code; |
150 | mutex_unlock(&session->mutex); | 157 | mutex_unlock(&session->mutex); |
151 | return put_user(temp, (int __user *)arg); | 158 | return put_user(temp, argp); |
152 | case VMCP_SETBUF: | 159 | case VMCP_SETBUF: |
153 | free_pages((unsigned long)session->response, | 160 | free_pages((unsigned long)session->response, |
154 | get_order(session->bufsize)); | 161 | get_order(session->bufsize)); |
155 | session->response=NULL; | 162 | session->response=NULL; |
156 | temp = get_user(session->bufsize, (int __user *)arg); | 163 | temp = get_user(session->bufsize, argp); |
157 | if (get_order(session->bufsize) > 8) { | 164 | if (get_order(session->bufsize) > 8) { |
158 | session->bufsize = PAGE_SIZE; | 165 | session->bufsize = PAGE_SIZE; |
159 | temp = -EINVAL; | 166 | temp = -EINVAL; |
@@ -163,7 +170,7 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
163 | case VMCP_GETSIZE: | 170 | case VMCP_GETSIZE: |
164 | temp = session->resp_size; | 171 | temp = session->resp_size; |
165 | mutex_unlock(&session->mutex); | 172 | mutex_unlock(&session->mutex); |
166 | return put_user(temp, (int __user *)arg); | 173 | return put_user(temp, argp); |
167 | default: | 174 | default: |
168 | mutex_unlock(&session->mutex); | 175 | mutex_unlock(&session->mutex); |
169 | return -ENOIOCTLCMD; | 176 | return -ENOIOCTLCMD; |
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index d1a142fa3eb4..e40a1b892866 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
20 | #include <linux/types.h> | 21 | #include <linux/types.h> |
21 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
@@ -312,11 +313,9 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp) | |||
312 | return -ENOSYS; | 313 | return -ENOSYS; |
313 | 314 | ||
314 | /* Besure this device hasn't already been opened */ | 315 | /* Besure this device hasn't already been opened */ |
315 | lock_kernel(); | ||
316 | spin_lock_bh(&logptr->priv_lock); | 316 | spin_lock_bh(&logptr->priv_lock); |
317 | if (logptr->dev_in_use) { | 317 | if (logptr->dev_in_use) { |
318 | spin_unlock_bh(&logptr->priv_lock); | 318 | spin_unlock_bh(&logptr->priv_lock); |
319 | unlock_kernel(); | ||
320 | return -EBUSY; | 319 | return -EBUSY; |
321 | } | 320 | } |
322 | logptr->dev_in_use = 1; | 321 | logptr->dev_in_use = 1; |
@@ -360,9 +359,8 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp) | |||
360 | || (logptr->iucv_path_severed)); | 359 | || (logptr->iucv_path_severed)); |
361 | if (logptr->iucv_path_severed) | 360 | if (logptr->iucv_path_severed) |
362 | goto out_record; | 361 | goto out_record; |
363 | ret = nonseekable_open(inode, filp); | 362 | nonseekable_open(inode, filp); |
364 | unlock_kernel(); | 363 | return 0; |
365 | return ret; | ||
366 | 364 | ||
367 | out_record: | 365 | out_record: |
368 | if (logptr->autorecording) | 366 | if (logptr->autorecording) |
@@ -372,7 +370,6 @@ out_path: | |||
372 | logptr->path = NULL; | 370 | logptr->path = NULL; |
373 | out_dev: | 371 | out_dev: |
374 | logptr->dev_in_use = 0; | 372 | logptr->dev_in_use = 0; |
375 | unlock_kernel(); | ||
376 | return -EIO; | 373 | return -EIO; |
377 | } | 374 | } |
378 | 375 | ||
@@ -679,7 +676,7 @@ static int vmlogrdr_pm_prepare(struct device *dev) | |||
679 | } | 676 | } |
680 | 677 | ||
681 | 678 | ||
682 | static struct dev_pm_ops vmlogrdr_pm_ops = { | 679 | static const struct dev_pm_ops vmlogrdr_pm_ops = { |
683 | .prepare = vmlogrdr_pm_prepare, | 680 | .prepare = vmlogrdr_pm_prepare, |
684 | }; | 681 | }; |
685 | 682 | ||
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 77571b68539a..1de672f21037 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 12 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
13 | 13 | ||
14 | #include <linux/cdev.h> | 14 | #include <linux/cdev.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/smp_lock.h> | 16 | #include <linux/smp_lock.h> |
16 | 17 | ||
17 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
@@ -695,7 +696,6 @@ static int ur_open(struct inode *inode, struct file *file) | |||
695 | 696 | ||
696 | if (accmode == O_RDWR) | 697 | if (accmode == O_RDWR) |
697 | return -EACCES; | 698 | return -EACCES; |
698 | lock_kernel(); | ||
699 | /* | 699 | /* |
700 | * We treat the minor number as the devno of the ur device | 700 | * We treat the minor number as the devno of the ur device |
701 | * to find in the driver tree. | 701 | * to find in the driver tree. |
@@ -749,7 +749,6 @@ static int ur_open(struct inode *inode, struct file *file) | |||
749 | goto fail_urfile_free; | 749 | goto fail_urfile_free; |
750 | urf->file_reclen = rc; | 750 | urf->file_reclen = rc; |
751 | file->private_data = urf; | 751 | file->private_data = urf; |
752 | unlock_kernel(); | ||
753 | return 0; | 752 | return 0; |
754 | 753 | ||
755 | fail_urfile_free: | 754 | fail_urfile_free: |
@@ -761,7 +760,6 @@ fail_unlock: | |||
761 | fail_put: | 760 | fail_put: |
762 | urdev_put(urd); | 761 | urdev_put(urd); |
763 | out: | 762 | out: |
764 | unlock_kernel(); | ||
765 | return rc; | 763 | return rc; |
766 | } | 764 | } |
767 | 765 | ||
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); |
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 82daa3c1dc9c..7217966f7d31 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -13,8 +13,10 @@ | |||
13 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 13 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
14 | 14 | ||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/slab.h> | ||
16 | #include <linux/miscdevice.h> | 17 | #include <linux/miscdevice.h> |
17 | #include <linux/debugfs.h> | 18 | #include <linux/debugfs.h> |
19 | #include <asm/asm-offsets.h> | ||
18 | #include <asm/ipl.h> | 20 | #include <asm/ipl.h> |
19 | #include <asm/sclp.h> | 21 | #include <asm/sclp.h> |
20 | #include <asm/setup.h> | 22 | #include <asm/setup.h> |
@@ -40,12 +42,12 @@ enum arch_id { | |||
40 | /* dump system info */ | 42 | /* dump system info */ |
41 | 43 | ||
42 | struct sys_info { | 44 | struct sys_info { |
43 | enum arch_id arch; | 45 | enum arch_id arch; |
44 | unsigned long sa_base; | 46 | unsigned long sa_base; |
45 | u32 sa_size; | 47 | u32 sa_size; |
46 | int cpu_map[NR_CPUS]; | 48 | int cpu_map[NR_CPUS]; |
47 | unsigned long mem_size; | 49 | unsigned long mem_size; |
48 | union save_area lc_mask; | 50 | struct save_area lc_mask; |
49 | }; | 51 | }; |
50 | 52 | ||
51 | struct ipib_info { | 53 | struct ipib_info { |
@@ -140,33 +142,6 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) | |||
140 | return memcpy_hsa(dest, src, count, TO_KERNEL); | 142 | return memcpy_hsa(dest, src, count, TO_KERNEL); |
141 | } | 143 | } |
142 | 144 | ||
143 | static int memcpy_real(void *dest, unsigned long src, size_t count) | ||
144 | { | ||
145 | unsigned long flags; | ||
146 | int rc = -EFAULT; | ||
147 | register unsigned long _dest asm("2") = (unsigned long) dest; | ||
148 | register unsigned long _len1 asm("3") = (unsigned long) count; | ||
149 | register unsigned long _src asm("4") = src; | ||
150 | register unsigned long _len2 asm("5") = (unsigned long) count; | ||
151 | |||
152 | if (count == 0) | ||
153 | return 0; | ||
154 | flags = __raw_local_irq_stnsm(0xf8UL); /* switch to real mode */ | ||
155 | asm volatile ( | ||
156 | "0: mvcle %1,%2,0x0\n" | ||
157 | "1: jo 0b\n" | ||
158 | " lhi %0,0x0\n" | ||
159 | "2:\n" | ||
160 | EX_TABLE(1b,2b) | ||
161 | : "+d" (rc), "+d" (_dest), "+d" (_src), "+d" (_len1), | ||
162 | "+d" (_len2), "=m" (*((long*)dest)) | ||
163 | : "m" (*((long*)src)) | ||
164 | : "cc", "memory"); | ||
165 | __raw_local_irq_ssm(flags); | ||
166 | |||
167 | return rc; | ||
168 | } | ||
169 | |||
170 | static int memcpy_real_user(void __user *dest, unsigned long src, size_t count) | 145 | static int memcpy_real_user(void __user *dest, unsigned long src, size_t count) |
171 | { | 146 | { |
172 | static char buf[4096]; | 147 | static char buf[4096]; |
@@ -174,7 +149,7 @@ static int memcpy_real_user(void __user *dest, unsigned long src, size_t count) | |||
174 | 149 | ||
175 | while (offs < count) { | 150 | while (offs < count) { |
176 | size = min(sizeof(buf), count - offs); | 151 | size = min(sizeof(buf), count - offs); |
177 | if (memcpy_real(buf, src + offs, size)) | 152 | if (memcpy_real(buf, (void *) src + offs, size)) |
178 | return -EFAULT; | 153 | return -EFAULT; |
179 | if (copy_to_user(dest + offs, buf, size)) | 154 | if (copy_to_user(dest + offs, buf, size)) |
180 | return -EFAULT; | 155 | return -EFAULT; |
@@ -183,52 +158,9 @@ static int memcpy_real_user(void __user *dest, unsigned long src, size_t count) | |||
183 | return 0; | 158 | return 0; |
184 | } | 159 | } |
185 | 160 | ||
186 | #ifdef __s390x__ | ||
187 | /* | ||
188 | * Convert s390x (64 bit) cpu info to s390 (32 bit) cpu info | ||
189 | */ | ||
190 | static void __init s390x_to_s390_regs(union save_area *out, union save_area *in, | ||
191 | int cpu) | ||
192 | { | ||
193 | int i; | ||
194 | |||
195 | for (i = 0; i < 16; i++) { | ||
196 | out->s390.gp_regs[i] = in->s390x.gp_regs[i] & 0x00000000ffffffff; | ||
197 | out->s390.acc_regs[i] = in->s390x.acc_regs[i]; | ||
198 | out->s390.ctrl_regs[i] = | ||
199 | in->s390x.ctrl_regs[i] & 0x00000000ffffffff; | ||
200 | } | ||
201 | /* locore for 31 bit has only space for fpregs 0,2,4,6 */ | ||
202 | out->s390.fp_regs[0] = in->s390x.fp_regs[0]; | ||
203 | out->s390.fp_regs[1] = in->s390x.fp_regs[2]; | ||
204 | out->s390.fp_regs[2] = in->s390x.fp_regs[4]; | ||
205 | out->s390.fp_regs[3] = in->s390x.fp_regs[6]; | ||
206 | memcpy(&(out->s390.psw[0]), &(in->s390x.psw[0]), 4); | ||
207 | out->s390.psw[1] |= 0x8; /* set bit 12 */ | ||
208 | memcpy(&(out->s390.psw[4]),&(in->s390x.psw[12]), 4); | ||
209 | out->s390.psw[4] |= 0x80; /* set (31bit) addressing bit */ | ||
210 | out->s390.pref_reg = in->s390x.pref_reg; | ||
211 | out->s390.timer = in->s390x.timer; | ||
212 | out->s390.clk_cmp = in->s390x.clk_cmp; | ||
213 | } | ||
214 | |||
215 | static void __init s390x_to_s390_save_areas(void) | ||
216 | { | ||
217 | int i = 1; | ||
218 | static union save_area tmp; | ||
219 | |||
220 | while (zfcpdump_save_areas[i]) { | ||
221 | s390x_to_s390_regs(&tmp, zfcpdump_save_areas[i], i); | ||
222 | memcpy(zfcpdump_save_areas[i], &tmp, sizeof(tmp)); | ||
223 | i++; | ||
224 | } | ||
225 | } | ||
226 | |||
227 | #endif /* __s390x__ */ | ||
228 | |||
229 | static int __init init_cpu_info(enum arch_id arch) | 161 | static int __init init_cpu_info(enum arch_id arch) |
230 | { | 162 | { |
231 | union save_area *sa; | 163 | struct save_area *sa; |
232 | 164 | ||
233 | /* get info for boot cpu from lowcore, stored in the HSA */ | 165 | /* get info for boot cpu from lowcore, stored in the HSA */ |
234 | 166 | ||
@@ -241,20 +173,12 @@ static int __init init_cpu_info(enum arch_id arch) | |||
241 | return -EIO; | 173 | return -EIO; |
242 | } | 174 | } |
243 | zfcpdump_save_areas[0] = sa; | 175 | zfcpdump_save_areas[0] = sa; |
244 | |||
245 | #ifdef __s390x__ | ||
246 | /* convert s390x regs to s390, if we are dumping an s390 Linux */ | ||
247 | |||
248 | if (arch == ARCH_S390) | ||
249 | s390x_to_s390_save_areas(); | ||
250 | #endif | ||
251 | |||
252 | return 0; | 176 | return 0; |
253 | } | 177 | } |
254 | 178 | ||
255 | static DEFINE_MUTEX(zcore_mutex); | 179 | static DEFINE_MUTEX(zcore_mutex); |
256 | 180 | ||
257 | #define DUMP_VERSION 0x3 | 181 | #define DUMP_VERSION 0x5 |
258 | #define DUMP_MAGIC 0xa8190173618f23fdULL | 182 | #define DUMP_MAGIC 0xa8190173618f23fdULL |
259 | #define DUMP_ARCH_S390X 2 | 183 | #define DUMP_ARCH_S390X 2 |
260 | #define DUMP_ARCH_S390 1 | 184 | #define DUMP_ARCH_S390 1 |
@@ -279,7 +203,14 @@ struct zcore_header { | |||
279 | u32 volnr; | 203 | u32 volnr; |
280 | u32 build_arch; | 204 | u32 build_arch; |
281 | u64 rmem_size; | 205 | u64 rmem_size; |
282 | char pad2[4016]; | 206 | u8 mvdump; |
207 | u16 cpu_cnt; | ||
208 | u16 real_cpu_cnt; | ||
209 | u8 end_pad1[0x200-0x061]; | ||
210 | u64 mvdump_sign; | ||
211 | u64 mvdump_zipl_time; | ||
212 | u8 end_pad2[0x800-0x210]; | ||
213 | u32 lc_vec[512]; | ||
283 | } __attribute__((packed,__aligned__(16))); | 214 | } __attribute__((packed,__aligned__(16))); |
284 | 215 | ||
285 | static struct zcore_header zcore_header = { | 216 | static struct zcore_header zcore_header = { |
@@ -289,7 +220,7 @@ static struct zcore_header zcore_header = { | |||
289 | .dump_level = 0, | 220 | .dump_level = 0, |
290 | .page_size = PAGE_SIZE, | 221 | .page_size = PAGE_SIZE, |
291 | .mem_start = 0, | 222 | .mem_start = 0, |
292 | #ifdef __s390x__ | 223 | #ifdef CONFIG_64BIT |
293 | .build_arch = DUMP_ARCH_S390X, | 224 | .build_arch = DUMP_ARCH_S390X, |
294 | #else | 225 | #else |
295 | .build_arch = DUMP_ARCH_S390, | 226 | .build_arch = DUMP_ARCH_S390, |
@@ -340,11 +271,7 @@ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) | |||
340 | unsigned long prefix; | 271 | unsigned long prefix; |
341 | unsigned long sa_off, len, buf_off; | 272 | unsigned long sa_off, len, buf_off; |
342 | 273 | ||
343 | if (sys_info.arch == ARCH_S390) | 274 | prefix = zfcpdump_save_areas[i]->pref_reg; |
344 | prefix = zfcpdump_save_areas[i]->s390.pref_reg; | ||
345 | else | ||
346 | prefix = zfcpdump_save_areas[i]->s390x.pref_reg; | ||
347 | |||
348 | sa_start = prefix + sys_info.sa_base; | 275 | sa_start = prefix + sys_info.sa_base; |
349 | sa_end = prefix + sys_info.sa_base + sys_info.sa_size; | 276 | sa_end = prefix + sys_info.sa_base + sys_info.sa_size; |
350 | 277 | ||
@@ -561,34 +488,39 @@ static const struct file_operations zcore_reipl_fops = { | |||
561 | .release = zcore_reipl_release, | 488 | .release = zcore_reipl_release, |
562 | }; | 489 | }; |
563 | 490 | ||
491 | #ifdef CONFIG_32BIT | ||
564 | 492 | ||
565 | static void __init set_s390_lc_mask(union save_area *map) | 493 | static void __init set_lc_mask(struct save_area *map) |
566 | { | 494 | { |
567 | memset(&map->s390.ext_save, 0xff, sizeof(map->s390.ext_save)); | 495 | memset(&map->ext_save, 0xff, sizeof(map->ext_save)); |
568 | memset(&map->s390.timer, 0xff, sizeof(map->s390.timer)); | 496 | memset(&map->timer, 0xff, sizeof(map->timer)); |
569 | memset(&map->s390.clk_cmp, 0xff, sizeof(map->s390.clk_cmp)); | 497 | memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp)); |
570 | memset(&map->s390.psw, 0xff, sizeof(map->s390.psw)); | 498 | memset(&map->psw, 0xff, sizeof(map->psw)); |
571 | memset(&map->s390.pref_reg, 0xff, sizeof(map->s390.pref_reg)); | 499 | memset(&map->pref_reg, 0xff, sizeof(map->pref_reg)); |
572 | memset(&map->s390.acc_regs, 0xff, sizeof(map->s390.acc_regs)); | 500 | memset(&map->acc_regs, 0xff, sizeof(map->acc_regs)); |
573 | memset(&map->s390.fp_regs, 0xff, sizeof(map->s390.fp_regs)); | 501 | memset(&map->fp_regs, 0xff, sizeof(map->fp_regs)); |
574 | memset(&map->s390.gp_regs, 0xff, sizeof(map->s390.gp_regs)); | 502 | memset(&map->gp_regs, 0xff, sizeof(map->gp_regs)); |
575 | memset(&map->s390.ctrl_regs, 0xff, sizeof(map->s390.ctrl_regs)); | 503 | memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs)); |
576 | } | 504 | } |
577 | 505 | ||
578 | static void __init set_s390x_lc_mask(union save_area *map) | 506 | #else /* CONFIG_32BIT */ |
507 | |||
508 | static void __init set_lc_mask(struct save_area *map) | ||
579 | { | 509 | { |
580 | memset(&map->s390x.fp_regs, 0xff, sizeof(map->s390x.fp_regs)); | 510 | memset(&map->fp_regs, 0xff, sizeof(map->fp_regs)); |
581 | memset(&map->s390x.gp_regs, 0xff, sizeof(map->s390x.gp_regs)); | 511 | memset(&map->gp_regs, 0xff, sizeof(map->gp_regs)); |
582 | memset(&map->s390x.psw, 0xff, sizeof(map->s390x.psw)); | 512 | memset(&map->psw, 0xff, sizeof(map->psw)); |
583 | memset(&map->s390x.pref_reg, 0xff, sizeof(map->s390x.pref_reg)); | 513 | memset(&map->pref_reg, 0xff, sizeof(map->pref_reg)); |
584 | memset(&map->s390x.fp_ctrl_reg, 0xff, sizeof(map->s390x.fp_ctrl_reg)); | 514 | memset(&map->fp_ctrl_reg, 0xff, sizeof(map->fp_ctrl_reg)); |
585 | memset(&map->s390x.tod_reg, 0xff, sizeof(map->s390x.tod_reg)); | 515 | memset(&map->tod_reg, 0xff, sizeof(map->tod_reg)); |
586 | memset(&map->s390x.timer, 0xff, sizeof(map->s390x.timer)); | 516 | memset(&map->timer, 0xff, sizeof(map->timer)); |
587 | memset(&map->s390x.clk_cmp, 0xff, sizeof(map->s390x.clk_cmp)); | 517 | memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp)); |
588 | memset(&map->s390x.acc_regs, 0xff, sizeof(map->s390x.acc_regs)); | 518 | memset(&map->acc_regs, 0xff, sizeof(map->acc_regs)); |
589 | memset(&map->s390x.ctrl_regs, 0xff, sizeof(map->s390x.ctrl_regs)); | 519 | memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs)); |
590 | } | 520 | } |
591 | 521 | ||
522 | #endif /* CONFIG_32BIT */ | ||
523 | |||
592 | /* | 524 | /* |
593 | * Initialize dump globals for a given architecture | 525 | * Initialize dump globals for a given architecture |
594 | */ | 526 | */ |
@@ -599,21 +531,18 @@ static int __init sys_info_init(enum arch_id arch) | |||
599 | switch (arch) { | 531 | switch (arch) { |
600 | case ARCH_S390X: | 532 | case ARCH_S390X: |
601 | pr_alert("DETECTED 'S390X (64 bit) OS'\n"); | 533 | pr_alert("DETECTED 'S390X (64 bit) OS'\n"); |
602 | sys_info.sa_base = SAVE_AREA_BASE_S390X; | ||
603 | sys_info.sa_size = sizeof(struct save_area_s390x); | ||
604 | set_s390x_lc_mask(&sys_info.lc_mask); | ||
605 | break; | 534 | break; |
606 | case ARCH_S390: | 535 | case ARCH_S390: |
607 | pr_alert("DETECTED 'S390 (32 bit) OS'\n"); | 536 | pr_alert("DETECTED 'S390 (32 bit) OS'\n"); |
608 | sys_info.sa_base = SAVE_AREA_BASE_S390; | ||
609 | sys_info.sa_size = sizeof(struct save_area_s390); | ||
610 | set_s390_lc_mask(&sys_info.lc_mask); | ||
611 | break; | 537 | break; |
612 | default: | 538 | default: |
613 | pr_alert("0x%x is an unknown architecture.\n",arch); | 539 | pr_alert("0x%x is an unknown architecture.\n",arch); |
614 | return -EINVAL; | 540 | return -EINVAL; |
615 | } | 541 | } |
542 | sys_info.sa_base = SAVE_AREA_BASE; | ||
543 | sys_info.sa_size = sizeof(struct save_area); | ||
616 | sys_info.arch = arch; | 544 | sys_info.arch = arch; |
545 | set_lc_mask(&sys_info.lc_mask); | ||
617 | rc = init_cpu_info(arch); | 546 | rc = init_cpu_info(arch); |
618 | if (rc) | 547 | if (rc) |
619 | return rc; | 548 | return rc; |
@@ -660,8 +589,9 @@ static int __init get_mem_size(unsigned long *mem) | |||
660 | 589 | ||
661 | static int __init zcore_header_init(int arch, struct zcore_header *hdr) | 590 | static int __init zcore_header_init(int arch, struct zcore_header *hdr) |
662 | { | 591 | { |
663 | int rc; | 592 | int rc, i; |
664 | unsigned long memory = 0; | 593 | unsigned long memory = 0; |
594 | u32 prefix; | ||
665 | 595 | ||
666 | if (arch == ARCH_S390X) | 596 | if (arch == ARCH_S390X) |
667 | hdr->arch_id = DUMP_ARCH_S390X; | 597 | hdr->arch_id = DUMP_ARCH_S390X; |
@@ -676,6 +606,14 @@ static int __init zcore_header_init(int arch, struct zcore_header *hdr) | |||
676 | hdr->num_pages = memory / PAGE_SIZE; | 606 | hdr->num_pages = memory / PAGE_SIZE; |
677 | hdr->tod = get_clock(); | 607 | hdr->tod = get_clock(); |
678 | get_cpu_id(&hdr->cpu_id); | 608 | get_cpu_id(&hdr->cpu_id); |
609 | for (i = 0; zfcpdump_save_areas[i]; i++) { | ||
610 | prefix = zfcpdump_save_areas[i]->pref_reg; | ||
611 | hdr->real_cpu_cnt++; | ||
612 | if (!prefix) | ||
613 | continue; | ||
614 | hdr->lc_vec[hdr->cpu_cnt] = prefix; | ||
615 | hdr->cpu_cnt++; | ||
616 | } | ||
679 | return 0; | 617 | return 0; |
680 | } | 618 | } |
681 | 619 | ||
@@ -699,12 +637,8 @@ static int __init zcore_reipl_init(void) | |||
699 | if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE) | 637 | if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE) |
700 | rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); | 638 | rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); |
701 | else | 639 | else |
702 | rc = memcpy_real(ipl_block, ipib_info.ipib, PAGE_SIZE); | 640 | rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE); |
703 | if (rc) { | 641 | if (rc || csum_partial(ipl_block, ipl_block->hdr.len, 0) != |
704 | free_page((unsigned long) ipl_block); | ||
705 | return rc; | ||
706 | } | ||
707 | if (csum_partial(ipl_block, ipl_block->hdr.len, 0) != | ||
708 | ipib_info.checksum) { | 642 | ipib_info.checksum) { |
709 | TRACE("Checksum does not match\n"); | 643 | TRACE("Checksum does not match\n"); |
710 | free_page((unsigned long) ipl_block); | 644 | free_page((unsigned long) ipl_block); |
@@ -741,14 +675,21 @@ static int __init zcore_init(void) | |||
741 | if (rc) | 675 | if (rc) |
742 | goto fail; | 676 | goto fail; |
743 | 677 | ||
744 | #ifndef __s390x__ | 678 | #ifdef CONFIG_64BIT |
679 | if (arch == ARCH_S390) { | ||
680 | pr_alert("The 64-bit dump tool cannot be used for a " | ||
681 | "32-bit system\n"); | ||
682 | rc = -EINVAL; | ||
683 | goto fail; | ||
684 | } | ||
685 | #else /* CONFIG_64BIT */ | ||
745 | if (arch == ARCH_S390X) { | 686 | if (arch == ARCH_S390X) { |
746 | pr_alert("The 32-bit dump tool cannot be used for a " | 687 | pr_alert("The 32-bit dump tool cannot be used for a " |
747 | "64-bit system\n"); | 688 | "64-bit system\n"); |
748 | rc = -EINVAL; | 689 | rc = -EINVAL; |
749 | goto fail; | 690 | goto fail; |
750 | } | 691 | } |
751 | #endif | 692 | #endif /* CONFIG_64BIT */ |
752 | 693 | ||
753 | rc = sys_info_init(arch); | 694 | rc = sys_info_init(arch); |
754 | if (rc) | 695 | if (rc) |