aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/s390/char
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/con3215.c195
-rw-r--r--drivers/s390/char/con3270.c1
-rw-r--r--drivers/s390/char/ctrlchar.c3
-rw-r--r--drivers/s390/char/ctrlchar.h3
-rw-r--r--drivers/s390/char/fs3270.c2
-rw-r--r--drivers/s390/char/keyboard.c33
-rw-r--r--drivers/s390/char/keyboard.h17
-rw-r--r--drivers/s390/char/monreader.c5
-rw-r--r--drivers/s390/char/raw3270.c5
-rw-r--r--drivers/s390/char/sclp.c20
-rw-r--r--drivers/s390/char/sclp.h13
-rw-r--r--drivers/s390/char/sclp_cmd.c137
-rw-r--r--drivers/s390/char/sclp_config.c10
-rw-r--r--drivers/s390/char/sclp_cpi.c1
-rw-r--r--drivers/s390/char/sclp_cpi_sys.c2
-rw-r--r--drivers/s390/char/sclp_cpi_sys.h1
-rw-r--r--drivers/s390/char/sclp_ocf.c1
-rw-r--r--drivers/s390/char/sclp_quiesce.c7
-rw-r--r--drivers/s390/char/sclp_rw.c2
-rw-r--r--drivers/s390/char/sclp_sdias.c107
-rw-r--r--drivers/s390/char/sclp_tty.c40
-rw-r--r--drivers/s390/char/sclp_tty.h3
-rw-r--r--drivers/s390/char/sclp_vt220.c37
-rw-r--r--drivers/s390/char/tape.h45
-rw-r--r--drivers/s390/char/tape_34xx.c138
-rw-r--r--drivers/s390/char/tape_3590.c107
-rw-r--r--drivers/s390/char/tape_3590.h3
-rw-r--r--drivers/s390/char/tape_char.c16
-rw-r--r--drivers/s390/char/tape_class.c5
-rw-r--r--drivers/s390/char/tape_class.h4
-rw-r--r--drivers/s390/char/tape_core.c19
-rw-r--r--drivers/s390/char/tape_proc.c3
-rw-r--r--drivers/s390/char/tape_std.c3
-rw-r--r--drivers/s390/char/tape_std.h7
-rw-r--r--drivers/s390/char/tty3270.c161
-rw-r--r--drivers/s390/char/tty3270.h2
-rw-r--r--drivers/s390/char/vmcp.c4
-rw-r--r--drivers/s390/char/vmcp.h2
-rw-r--r--drivers/s390/char/vmlogrdr.c47
-rw-r--r--drivers/s390/char/vmur.c6
-rw-r--r--drivers/s390/char/vmwatchdog.c6
-rw-r--r--drivers/s390/char/zcore.c26
42 files changed, 683 insertions, 566 deletions
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 33b7141a182..694464c65fc 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -9,6 +9,7 @@
9 * Dan Morrison, IBM Corporation <dmorriso@cse.buffalo.edu> 9 * Dan Morrison, IBM Corporation <dmorriso@cse.buffalo.edu>
10 */ 10 */
11 11
12#include <linux/kernel_stat.h>
12#include <linux/module.h> 13#include <linux/module.h>
13#include <linux/types.h> 14#include <linux/types.h>
14#include <linux/kdev_t.h> 15#include <linux/kdev_t.h>
@@ -20,7 +21,6 @@
20#include <linux/interrupt.h> 21#include <linux/interrupt.h>
21#include <linux/err.h> 22#include <linux/err.h>
22#include <linux/reboot.h> 23#include <linux/reboot.h>
23#include <linux/serial.h> /* ASYNC_* flags */
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <asm/ccwdev.h> 25#include <asm/ccwdev.h>
26#include <asm/cio.h> 26#include <asm/cio.h>
@@ -45,11 +45,14 @@
45#define RAW3215_TIMEOUT HZ/10 /* time for delayed output */ 45#define RAW3215_TIMEOUT HZ/10 /* time for delayed output */
46 46
47#define RAW3215_FIXED 1 /* 3215 console device is not be freed */ 47#define RAW3215_FIXED 1 /* 3215 console device is not be freed */
48#define RAW3215_ACTIVE 2 /* set if the device is in use */
48#define RAW3215_WORKING 4 /* set if a request is being worked on */ 49#define RAW3215_WORKING 4 /* set if a request is being worked on */
49#define RAW3215_THROTTLED 8 /* set if reading is disabled */ 50#define RAW3215_THROTTLED 8 /* set if reading is disabled */
50#define RAW3215_STOPPED 16 /* set if writing is disabled */ 51#define RAW3215_STOPPED 16 /* set if writing is disabled */
52#define RAW3215_CLOSING 32 /* set while in close process */
51#define RAW3215_TIMER_RUNS 64 /* set if the output delay timer is on */ 53#define RAW3215_TIMER_RUNS 64 /* set if the output delay timer is on */
52#define RAW3215_FLUSHING 128 /* set to flush buffer (no delay) */ 54#define RAW3215_FLUSHING 128 /* set to flush buffer (no delay) */
55#define RAW3215_FROZEN 256 /* set if 3215 is frozen for suspend */
53 56
54#define TAB_STOP_SIZE 8 /* tab stop size */ 57#define TAB_STOP_SIZE 8 /* tab stop size */
55 58
@@ -74,7 +77,6 @@ struct raw3215_req {
74} __attribute__ ((aligned(8))); 77} __attribute__ ((aligned(8)));
75 78
76struct raw3215_info { 79struct raw3215_info {
77 struct tty_port port;
78 struct ccw_device *cdev; /* device for tty driver */ 80 struct ccw_device *cdev; /* device for tty driver */
79 spinlock_t *lock; /* pointer to irq lock */ 81 spinlock_t *lock; /* pointer to irq lock */
80 int flags; /* state flags */ 82 int flags; /* state flags */
@@ -83,9 +85,9 @@ struct raw3215_info {
83 int head; /* first free byte in output buffer */ 85 int head; /* first free byte in output buffer */
84 int count; /* number of bytes in output buffer */ 86 int count; /* number of bytes in output buffer */
85 int written; /* number of bytes in write requests */ 87 int written; /* number of bytes in write requests */
88 struct tty_struct *tty; /* pointer to tty structure if present */
86 struct raw3215_req *queued_read; /* pointer to queued read requests */ 89 struct raw3215_req *queued_read; /* pointer to queued read requests */
87 struct raw3215_req *queued_write;/* pointer to queued write requests */ 90 struct raw3215_req *queued_write;/* pointer to queued write requests */
88 struct tasklet_struct tlet; /* tasklet to invoke tty_wakeup */
89 wait_queue_head_t empty_wait; /* wait queue for flushing */ 91 wait_queue_head_t empty_wait; /* wait queue for flushing */
90 struct timer_list timer; /* timer for delayed output */ 92 struct timer_list timer; /* timer for delayed output */
91 int line_pos; /* position on the line (for tabs) */ 93 int line_pos; /* position on the line (for tabs) */
@@ -291,7 +293,7 @@ static void raw3215_timeout(unsigned long __data)
291 if (raw->flags & RAW3215_TIMER_RUNS) { 293 if (raw->flags & RAW3215_TIMER_RUNS) {
292 del_timer(&raw->timer); 294 del_timer(&raw->timer);
293 raw->flags &= ~RAW3215_TIMER_RUNS; 295 raw->flags &= ~RAW3215_TIMER_RUNS;
294 if (!(raw->port.flags & ASYNC_SUSPENDED)) { 296 if (!(raw->flags & RAW3215_FROZEN)) {
295 raw3215_mk_write_req(raw); 297 raw3215_mk_write_req(raw);
296 raw3215_start_io(raw); 298 raw3215_start_io(raw);
297 } 299 }
@@ -307,8 +309,7 @@ static void raw3215_timeout(unsigned long __data)
307 */ 309 */
308static inline void raw3215_try_io(struct raw3215_info *raw) 310static inline void raw3215_try_io(struct raw3215_info *raw)
309{ 311{
310 if (!(raw->port.flags & ASYNC_INITIALIZED) || 312 if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FROZEN))
311 (raw->port.flags & ASYNC_SUSPENDED))
312 return; 313 return;
313 if (raw->queued_read != NULL) 314 if (raw->queued_read != NULL)
314 raw3215_start_io(raw); 315 raw3215_start_io(raw);
@@ -323,7 +324,10 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
323 } 324 }
324 } else if (!(raw->flags & RAW3215_TIMER_RUNS)) { 325 } else if (!(raw->flags & RAW3215_TIMER_RUNS)) {
325 /* delay small writes */ 326 /* delay small writes */
327 init_timer(&raw->timer);
326 raw->timer.expires = RAW3215_TIMEOUT + jiffies; 328 raw->timer.expires = RAW3215_TIMEOUT + jiffies;
329 raw->timer.data = (unsigned long) raw;
330 raw->timer.function = raw3215_timeout;
327 add_timer(&raw->timer); 331 add_timer(&raw->timer);
328 raw->flags |= RAW3215_TIMER_RUNS; 332 raw->flags |= RAW3215_TIMER_RUNS;
329 } 333 }
@@ -331,29 +335,19 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
331} 335}
332 336
333/* 337/*
334 * Call tty_wakeup from tasklet context 338 * Try to start the next IO and wake up processes waiting on the tty.
335 */ 339 */
336static void raw3215_wakeup(unsigned long data) 340static void raw3215_next_io(struct raw3215_info *raw)
337{ 341{
338 struct raw3215_info *raw = (struct raw3215_info *) data;
339 struct tty_struct *tty; 342 struct tty_struct *tty;
340 343
341 tty = tty_port_tty_get(&raw->port);
342 if (tty) {
343 tty_wakeup(tty);
344 tty_kref_put(tty);
345 }
346}
347
348/*
349 * Try to start the next IO and wake up processes waiting on the tty.
350 */
351static void raw3215_next_io(struct raw3215_info *raw, struct tty_struct *tty)
352{
353 raw3215_mk_write_req(raw); 344 raw3215_mk_write_req(raw);
354 raw3215_try_io(raw); 345 raw3215_try_io(raw);
355 if (tty && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) 346 tty = raw->tty;
356 tasklet_schedule(&raw->tlet); 347 if (tty != NULL &&
348 RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
349 tty_wakeup(tty);
350 }
357} 351}
358 352
359/* 353/*
@@ -368,13 +362,13 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
368 int cstat, dstat; 362 int cstat, dstat;
369 int count; 363 int count;
370 364
365 kstat_cpu(smp_processor_id()).irqs[IOINT_C15]++;
371 raw = dev_get_drvdata(&cdev->dev); 366 raw = dev_get_drvdata(&cdev->dev);
372 req = (struct raw3215_req *) intparm; 367 req = (struct raw3215_req *) intparm;
373 tty = tty_port_tty_get(&raw->port);
374 cstat = irb->scsw.cmd.cstat; 368 cstat = irb->scsw.cmd.cstat;
375 dstat = irb->scsw.cmd.dstat; 369 dstat = irb->scsw.cmd.dstat;
376 if (cstat != 0) 370 if (cstat != 0)
377 raw3215_next_io(raw, tty); 371 raw3215_next_io(raw);
378 if (dstat & 0x01) { /* we got a unit exception */ 372 if (dstat & 0x01) { /* we got a unit exception */
379 dstat &= ~0x01; /* we can ignore it */ 373 dstat &= ~0x01; /* we can ignore it */
380 } 374 }
@@ -384,13 +378,13 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
384 break; 378 break;
385 /* Attention interrupt, someone hit the enter key */ 379 /* Attention interrupt, someone hit the enter key */
386 raw3215_mk_read_req(raw); 380 raw3215_mk_read_req(raw);
387 raw3215_next_io(raw, tty); 381 raw3215_next_io(raw);
388 break; 382 break;
389 case 0x08: 383 case 0x08:
390 case 0x0C: 384 case 0x0C:
391 /* Channel end interrupt. */ 385 /* Channel end interrupt. */
392 if ((raw = req->info) == NULL) 386 if ((raw = req->info) == NULL)
393 goto put_tty; /* That shouldn't happen ... */ 387 return; /* That shouldn't happen ... */
394 if (req->type == RAW3215_READ) { 388 if (req->type == RAW3215_READ) {
395 /* store residual count, then wait for device end */ 389 /* store residual count, then wait for device end */
396 req->residual = irb->scsw.cmd.count; 390 req->residual = irb->scsw.cmd.count;
@@ -400,10 +394,11 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
400 case 0x04: 394 case 0x04:
401 /* Device end interrupt. */ 395 /* Device end interrupt. */
402 if ((raw = req->info) == NULL) 396 if ((raw = req->info) == NULL)
403 goto put_tty; /* That shouldn't happen ... */ 397 return; /* That shouldn't happen ... */
404 if (req->type == RAW3215_READ && tty != NULL) { 398 if (req->type == RAW3215_READ && raw->tty != NULL) {
405 unsigned int cchar; 399 unsigned int cchar;
406 400
401 tty = raw->tty;
407 count = 160 - req->residual; 402 count = 160 - req->residual;
408 EBCASC(raw->inbuf, count); 403 EBCASC(raw->inbuf, count);
409 cchar = ctrlchar_handle(raw->inbuf, count, tty); 404 cchar = ctrlchar_handle(raw->inbuf, count, tty);
@@ -413,7 +408,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
413 408
414 case CTRLCHAR_CTRL: 409 case CTRLCHAR_CTRL:
415 tty_insert_flip_char(tty, cchar, TTY_NORMAL); 410 tty_insert_flip_char(tty, cchar, TTY_NORMAL);
416 tty_flip_buffer_push(tty); 411 tty_flip_buffer_push(raw->tty);
417 break; 412 break;
418 413
419 case CTRLCHAR_NONE: 414 case CTRLCHAR_NONE:
@@ -426,7 +421,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
426 } else 421 } else
427 count -= 2; 422 count -= 2;
428 tty_insert_flip_string(tty, raw->inbuf, count); 423 tty_insert_flip_string(tty, raw->inbuf, count);
429 tty_flip_buffer_push(tty); 424 tty_flip_buffer_push(raw->tty);
430 break; 425 break;
431 } 426 }
432 } else if (req->type == RAW3215_WRITE) { 427 } else if (req->type == RAW3215_WRITE) {
@@ -441,7 +436,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
441 raw->queued_read == NULL) { 436 raw->queued_read == NULL) {
442 wake_up_interruptible(&raw->empty_wait); 437 wake_up_interruptible(&raw->empty_wait);
443 } 438 }
444 raw3215_next_io(raw, tty); 439 raw3215_next_io(raw);
445 break; 440 break;
446 default: 441 default:
447 /* Strange interrupt, I'll do my best to clean up */ 442 /* Strange interrupt, I'll do my best to clean up */
@@ -453,10 +448,9 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
453 raw->flags &= ~RAW3215_WORKING; 448 raw->flags &= ~RAW3215_WORKING;
454 raw3215_free_req(req); 449 raw3215_free_req(req);
455 } 450 }
456 raw3215_next_io(raw, tty); 451 raw3215_next_io(raw);
457 } 452 }
458put_tty: 453 return;
459 tty_kref_put(tty);
460} 454}
461 455
462/* 456/*
@@ -490,7 +484,7 @@ static void raw3215_make_room(struct raw3215_info *raw, unsigned int length)
490 /* While console is frozen for suspend we have no other 484 /* While console is frozen for suspend we have no other
491 * choice but to drop message from the buffer to make 485 * choice but to drop message from the buffer to make
492 * room for even more messages. */ 486 * room for even more messages. */
493 if (raw->port.flags & ASYNC_SUSPENDED) { 487 if (raw->flags & RAW3215_FROZEN) {
494 raw3215_drop_line(raw); 488 raw3215_drop_line(raw);
495 continue; 489 continue;
496 } 490 }
@@ -612,10 +606,10 @@ static int raw3215_startup(struct raw3215_info *raw)
612{ 606{
613 unsigned long flags; 607 unsigned long flags;
614 608
615 if (raw->port.flags & ASYNC_INITIALIZED) 609 if (raw->flags & RAW3215_ACTIVE)
616 return 0; 610 return 0;
617 raw->line_pos = 0; 611 raw->line_pos = 0;
618 raw->port.flags |= ASYNC_INITIALIZED; 612 raw->flags |= RAW3215_ACTIVE;
619 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); 613 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
620 raw3215_try_io(raw); 614 raw3215_try_io(raw);
621 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); 615 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
@@ -631,15 +625,14 @@ static void raw3215_shutdown(struct raw3215_info *raw)
631 DECLARE_WAITQUEUE(wait, current); 625 DECLARE_WAITQUEUE(wait, current);
632 unsigned long flags; 626 unsigned long flags;
633 627
634 if (!(raw->port.flags & ASYNC_INITIALIZED) || 628 if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED))
635 (raw->flags & RAW3215_FIXED))
636 return; 629 return;
637 /* Wait for outstanding requests, then free irq */ 630 /* Wait for outstanding requests, then free irq */
638 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); 631 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
639 if ((raw->flags & RAW3215_WORKING) || 632 if ((raw->flags & RAW3215_WORKING) ||
640 raw->queued_write != NULL || 633 raw->queued_write != NULL ||
641 raw->queued_read != NULL) { 634 raw->queued_read != NULL) {
642 raw->port.flags |= ASYNC_CLOSING; 635 raw->flags |= RAW3215_CLOSING;
643 add_wait_queue(&raw->empty_wait, &wait); 636 add_wait_queue(&raw->empty_wait, &wait);
644 set_current_state(TASK_INTERRUPTIBLE); 637 set_current_state(TASK_INTERRUPTIBLE);
645 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); 638 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
@@ -647,42 +640,11 @@ static void raw3215_shutdown(struct raw3215_info *raw)
647 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); 640 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
648 remove_wait_queue(&raw->empty_wait, &wait); 641 remove_wait_queue(&raw->empty_wait, &wait);
649 set_current_state(TASK_RUNNING); 642 set_current_state(TASK_RUNNING);
650 raw->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING); 643 raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING);
651 } 644 }
652 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); 645 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
653} 646}
654 647
655static struct raw3215_info *raw3215_alloc_info(void)
656{
657 struct raw3215_info *info;
658
659 info = kzalloc(sizeof(struct raw3215_info), GFP_KERNEL | GFP_DMA);
660 if (!info)
661 return NULL;
662
663 info->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
664 info->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA);
665 if (!info->buffer || !info->inbuf) {
666 kfree(info);
667 return NULL;
668 }
669
670 setup_timer(&info->timer, raw3215_timeout, (unsigned long)info);
671 init_waitqueue_head(&info->empty_wait);
672 tasklet_init(&info->tlet, raw3215_wakeup, (unsigned long)info);
673 tty_port_init(&info->port);
674
675 return info;
676}
677
678static void raw3215_free_info(struct raw3215_info *raw)
679{
680 kfree(raw->inbuf);
681 kfree(raw->buffer);
682 tty_port_destroy(&raw->port);
683 kfree(raw);
684}
685
686static int raw3215_probe (struct ccw_device *cdev) 648static int raw3215_probe (struct ccw_device *cdev)
687{ 649{
688 struct raw3215_info *raw; 650 struct raw3215_info *raw;
@@ -691,15 +653,11 @@ static int raw3215_probe (struct ccw_device *cdev)
691 /* Console is special. */ 653 /* Console is special. */
692 if (raw3215[0] && (raw3215[0] == dev_get_drvdata(&cdev->dev))) 654 if (raw3215[0] && (raw3215[0] == dev_get_drvdata(&cdev->dev)))
693 return 0; 655 return 0;
694 656 raw = kmalloc(sizeof(struct raw3215_info) +
695 raw = raw3215_alloc_info(); 657 RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA);
696 if (raw == NULL) 658 if (raw == NULL)
697 return -ENOMEM; 659 return -ENOMEM;
698 660
699 raw->cdev = cdev;
700 dev_set_drvdata(&cdev->dev, raw);
701 cdev->handler = raw3215_irq;
702
703 spin_lock(&raw3215_device_lock); 661 spin_lock(&raw3215_device_lock);
704 for (line = 0; line < NR_3215; line++) { 662 for (line = 0; line < NR_3215; line++) {
705 if (!raw3215[line]) { 663 if (!raw3215[line]) {
@@ -709,29 +667,40 @@ static int raw3215_probe (struct ccw_device *cdev)
709 } 667 }
710 spin_unlock(&raw3215_device_lock); 668 spin_unlock(&raw3215_device_lock);
711 if (line == NR_3215) { 669 if (line == NR_3215) {
712 raw3215_free_info(raw); 670 kfree(raw);
713 return -ENODEV; 671 return -ENODEV;
714 } 672 }
715 673
674 raw->cdev = cdev;
675 raw->inbuf = (char *) raw + sizeof(struct raw3215_info);
676 memset(raw, 0, sizeof(struct raw3215_info));
677 raw->buffer = kmalloc(RAW3215_BUFFER_SIZE,
678 GFP_KERNEL|GFP_DMA);
679 if (raw->buffer == NULL) {
680 spin_lock(&raw3215_device_lock);
681 raw3215[line] = NULL;
682 spin_unlock(&raw3215_device_lock);
683 kfree(raw);
684 return -ENOMEM;
685 }
686 init_waitqueue_head(&raw->empty_wait);
687
688 dev_set_drvdata(&cdev->dev, raw);
689 cdev->handler = raw3215_irq;
690
716 return 0; 691 return 0;
717} 692}
718 693
719static void raw3215_remove (struct ccw_device *cdev) 694static void raw3215_remove (struct ccw_device *cdev)
720{ 695{
721 struct raw3215_info *raw; 696 struct raw3215_info *raw;
722 unsigned int line;
723 697
724 ccw_device_set_offline(cdev); 698 ccw_device_set_offline(cdev);
725 raw = dev_get_drvdata(&cdev->dev); 699 raw = dev_get_drvdata(&cdev->dev);
726 if (raw) { 700 if (raw) {
727 spin_lock(&raw3215_device_lock);
728 for (line = 0; line < NR_3215; line++)
729 if (raw3215[line] == raw)
730 break;
731 raw3215[line] = NULL;
732 spin_unlock(&raw3215_device_lock);
733 dev_set_drvdata(&cdev->dev, NULL); 701 dev_set_drvdata(&cdev->dev, NULL);
734 raw3215_free_info(raw); 702 kfree(raw->buffer);
703 kfree(raw);
735 } 704 }
736} 705}
737 706
@@ -768,7 +737,7 @@ static int raw3215_pm_stop(struct ccw_device *cdev)
768 raw = dev_get_drvdata(&cdev->dev); 737 raw = dev_get_drvdata(&cdev->dev);
769 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); 738 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
770 raw3215_make_room(raw, RAW3215_BUFFER_SIZE); 739 raw3215_make_room(raw, RAW3215_BUFFER_SIZE);
771 raw->port.flags |= ASYNC_SUSPENDED; 740 raw->flags |= RAW3215_FROZEN;
772 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); 741 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
773 return 0; 742 return 0;
774} 743}
@@ -781,7 +750,7 @@ static int raw3215_pm_start(struct ccw_device *cdev)
781 /* Allow I/O again and flush output buffer. */ 750 /* Allow I/O again and flush output buffer. */
782 raw = dev_get_drvdata(&cdev->dev); 751 raw = dev_get_drvdata(&cdev->dev);
783 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); 752 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
784 raw->port.flags &= ~ASYNC_SUSPENDED; 753 raw->flags &= ~RAW3215_FROZEN;
785 raw->flags |= RAW3215_FLUSHING; 754 raw->flags |= RAW3215_FLUSHING;
786 raw3215_try_io(raw); 755 raw3215_try_io(raw);
787 raw->flags &= ~RAW3215_FLUSHING; 756 raw->flags &= ~RAW3215_FLUSHING;
@@ -807,7 +776,6 @@ static struct ccw_driver raw3215_ccw_driver = {
807 .freeze = &raw3215_pm_stop, 776 .freeze = &raw3215_pm_stop,
808 .thaw = &raw3215_pm_start, 777 .thaw = &raw3215_pm_start,
809 .restore = &raw3215_pm_start, 778 .restore = &raw3215_pm_start,
810 .int_class = IRQIO_C15,
811}; 779};
812 780
813#ifdef CONFIG_TN3215_CONSOLE 781#ifdef CONFIG_TN3215_CONSOLE
@@ -854,7 +822,7 @@ static void con3215_flush(void)
854 unsigned long flags; 822 unsigned long flags;
855 823
856 raw = raw3215[0]; /* console 3215 is the first one */ 824 raw = raw3215[0]; /* console 3215 is the first one */
857 if (raw->port.flags & ASYNC_SUSPENDED) 825 if (raw->flags & RAW3215_FROZEN)
858 /* The console is still frozen for suspend. */ 826 /* The console is still frozen for suspend. */
859 if (ccw_device_force_console()) 827 if (ccw_device_force_console())
860 /* Forcing didn't work, no panic message .. */ 828 /* Forcing didn't work, no panic message .. */
@@ -924,16 +892,22 @@ static int __init con3215_init(void)
924 if (IS_ERR(cdev)) 892 if (IS_ERR(cdev))
925 return -ENODEV; 893 return -ENODEV;
926 894
927 raw3215[0] = raw = raw3215_alloc_info(); 895 raw3215[0] = raw = (struct raw3215_info *)
896 kzalloc(sizeof(struct raw3215_info), GFP_KERNEL | GFP_DMA);
897 raw->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
898 raw->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA);
928 raw->cdev = cdev; 899 raw->cdev = cdev;
929 dev_set_drvdata(&cdev->dev, raw); 900 dev_set_drvdata(&cdev->dev, raw);
930 cdev->handler = raw3215_irq; 901 cdev->handler = raw3215_irq;
931 902
932 raw->flags |= RAW3215_FIXED; 903 raw->flags |= RAW3215_FIXED;
904 init_waitqueue_head(&raw->empty_wait);
933 905
934 /* Request the console irq */ 906 /* Request the console irq */
935 if (raw3215_startup(raw) != 0) { 907 if (raw3215_startup(raw) != 0) {
936 raw3215_free_info(raw); 908 kfree(raw->inbuf);
909 kfree(raw->buffer);
910 kfree(raw);
937 raw3215[0] = NULL; 911 raw3215[0] = NULL;
938 return -ENODEV; 912 return -ENODEV;
939 } 913 }
@@ -945,19 +919,6 @@ static int __init con3215_init(void)
945console_initcall(con3215_init); 919console_initcall(con3215_init);
946#endif 920#endif
947 921
948static int tty3215_install(struct tty_driver *driver, struct tty_struct *tty)
949{
950 struct raw3215_info *raw;
951
952 raw = raw3215[tty->index];
953 if (raw == NULL)
954 return -ENODEV;
955
956 tty->driver_data = raw;
957
958 return tty_port_install(&raw->port, driver, tty);
959}
960
961/* 922/*
962 * tty3215_open 923 * tty3215_open
963 * 924 *
@@ -965,10 +926,19 @@ static int tty3215_install(struct tty_driver *driver, struct tty_struct *tty)
965 */ 926 */
966static int tty3215_open(struct tty_struct *tty, struct file * filp) 927static int tty3215_open(struct tty_struct *tty, struct file * filp)
967{ 928{
968 struct raw3215_info *raw = tty->driver_data; 929 struct raw3215_info *raw;
969 int retval; 930 int retval, line;
931
932 line = tty->index;
933 if ((line < 0) || (line >= NR_3215))
934 return -ENODEV;
970 935
971 tty_port_tty_set(&raw->port, tty); 936 raw = raw3215[line];
937 if (raw == NULL)
938 return -ENODEV;
939
940 tty->driver_data = raw;
941 raw->tty = tty;
972 942
973 tty->low_latency = 0; /* don't use bottom half for pushing chars */ 943 tty->low_latency = 0; /* don't use bottom half for pushing chars */
974 /* 944 /*
@@ -997,9 +967,8 @@ static void tty3215_close(struct tty_struct *tty, struct file * filp)
997 tty->closing = 1; 967 tty->closing = 1;
998 /* Shutdown the terminal */ 968 /* Shutdown the terminal */
999 raw3215_shutdown(raw); 969 raw3215_shutdown(raw);
1000 tasklet_kill(&raw->tlet);
1001 tty->closing = 0; 970 tty->closing = 0;
1002 tty_port_tty_set(&raw->port, NULL); 971 raw->tty = NULL;
1003} 972}
1004 973
1005/* 974/*
@@ -1128,7 +1097,6 @@ static void tty3215_start(struct tty_struct *tty)
1128} 1097}
1129 1098
1130static const struct tty_operations tty3215_ops = { 1099static const struct tty_operations tty3215_ops = {
1131 .install = tty3215_install,
1132 .open = tty3215_open, 1100 .open = tty3215_open,
1133 .close = tty3215_close, 1101 .close = tty3215_close,
1134 .write = tty3215_write, 1102 .write = tty3215_write,
@@ -1170,6 +1138,7 @@ static int __init tty3215_init(void)
1170 * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc 1138 * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc
1171 */ 1139 */
1172 1140
1141 driver->owner = THIS_MODULE;
1173 driver->driver_name = "tty3215"; 1142 driver->driver_name = "tty3215";
1174 driver->name = "ttyS"; 1143 driver->name = "ttyS";
1175 driver->major = TTY_MAJOR; 1144 driver->major = TTY_MAJOR;
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index 699fd3e363d..bb07577e8fd 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -35,6 +35,7 @@ static struct raw3270_fn con3270_fn;
35 */ 35 */
36struct con3270 { 36struct con3270 {
37 struct raw3270_view view; 37 struct raw3270_view view;
38 spinlock_t lock;
38 struct list_head freemem; /* list of free memory for strings. */ 39 struct list_head freemem; /* list of free memory for strings. */
39 40
40 /* Output stuff. */ 41 /* Output stuff. */
diff --git a/drivers/s390/char/ctrlchar.c b/drivers/s390/char/ctrlchar.c
index 8de2deb176d..0e9a309b966 100644
--- a/drivers/s390/char/ctrlchar.c
+++ b/drivers/s390/char/ctrlchar.c
@@ -1,7 +1,8 @@
1/* 1/*
2 * drivers/s390/char/ctrlchar.c
2 * Unified handling of special chars. 3 * Unified handling of special chars.
3 * 4 *
4 * Copyright IBM Corp. 2001 5 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
5 * Author(s): Fritz Elfert <felfert@millenux.com> <elfert@de.ibm.com> 6 * Author(s): Fritz Elfert <felfert@millenux.com> <elfert@de.ibm.com>
6 * 7 *
7 */ 8 */
diff --git a/drivers/s390/char/ctrlchar.h b/drivers/s390/char/ctrlchar.h
index 1a53552f498..935ffa0ea7c 100644
--- a/drivers/s390/char/ctrlchar.h
+++ b/drivers/s390/char/ctrlchar.h
@@ -1,7 +1,8 @@
1/* 1/*
2 * drivers/s390/char/ctrlchar.c
2 * Unified handling of special chars. 3 * Unified handling of special chars.
3 * 4 *
4 * Copyright IBM Corp. 2001 5 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
5 * Author(s): Fritz Elfert <felfert@millenux.com> <elfert@de.ibm.com> 6 * Author(s): Fritz Elfert <felfert@millenux.com> <elfert@de.ibm.com>
6 * 7 *
7 */ 8 */
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 911704571b9..f6489eb7e97 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -11,8 +11,6 @@
11#include <linux/console.h> 11#include <linux/console.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/interrupt.h> 13#include <linux/interrupt.h>
14#include <linux/compat.h>
15#include <linux/module.h>
16#include <linux/list.h> 14#include <linux/list.h>
17#include <linux/slab.h> 15#include <linux/slab.h>
18#include <linux/types.h> 16#include <linux/types.h>
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 01463b052ae..80658819248 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -1,8 +1,9 @@
1/* 1/*
2 * drivers/s390/char/keyboard.c
2 * ebcdic keycode functions for s390 console drivers 3 * ebcdic keycode functions for s390 console drivers
3 * 4 *
4 * S390 version 5 * S390 version
5 * Copyright IBM Corp. 2003 6 * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), 7 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
7 */ 8 */
8 9
@@ -198,7 +199,7 @@ handle_diacr(struct kbd_data *kbd, unsigned int ch)
198 if (ch == ' ' || ch == d) 199 if (ch == ' ' || ch == d)
199 return d; 200 return d;
200 201
201 kbd_put_queue(kbd->port, d); 202 kbd_put_queue(kbd->tty, d);
202 return ch; 203 return ch;
203} 204}
204 205
@@ -220,7 +221,7 @@ k_self(struct kbd_data *kbd, unsigned char value)
220{ 221{
221 if (kbd->diacr) 222 if (kbd->diacr)
222 value = handle_diacr(kbd, value); 223 value = handle_diacr(kbd, value);
223 kbd_put_queue(kbd->port, value); 224 kbd_put_queue(kbd->tty, value);
224} 225}
225 226
226/* 227/*
@@ -238,7 +239,7 @@ static void
238k_fn(struct kbd_data *kbd, unsigned char value) 239k_fn(struct kbd_data *kbd, unsigned char value)
239{ 240{
240 if (kbd->func_table[value]) 241 if (kbd->func_table[value])
241 kbd_puts_queue(kbd->port, kbd->func_table[value]); 242 kbd_puts_queue(kbd->tty, kbd->func_table[value]);
242} 243}
243 244
244static void 245static void
@@ -256,20 +257,20 @@ k_spec(struct kbd_data *kbd, unsigned char value)
256 * but we need only 16 bits here 257 * but we need only 16 bits here
257 */ 258 */
258static void 259static void
259to_utf8(struct tty_port *port, ushort c) 260to_utf8(struct tty_struct *tty, ushort c)
260{ 261{
261 if (c < 0x80) 262 if (c < 0x80)
262 /* 0******* */ 263 /* 0******* */
263 kbd_put_queue(port, c); 264 kbd_put_queue(tty, c);
264 else if (c < 0x800) { 265 else if (c < 0x800) {
265 /* 110***** 10****** */ 266 /* 110***** 10****** */
266 kbd_put_queue(port, 0xc0 | (c >> 6)); 267 kbd_put_queue(tty, 0xc0 | (c >> 6));
267 kbd_put_queue(port, 0x80 | (c & 0x3f)); 268 kbd_put_queue(tty, 0x80 | (c & 0x3f));
268 } else { 269 } else {
269 /* 1110**** 10****** 10****** */ 270 /* 1110**** 10****** 10****** */
270 kbd_put_queue(port, 0xe0 | (c >> 12)); 271 kbd_put_queue(tty, 0xe0 | (c >> 12));
271 kbd_put_queue(port, 0x80 | ((c >> 6) & 0x3f)); 272 kbd_put_queue(tty, 0x80 | ((c >> 6) & 0x3f));
272 kbd_put_queue(port, 0x80 | (c & 0x3f)); 273 kbd_put_queue(tty, 0x80 | (c & 0x3f));
273 } 274 }
274} 275}
275 276
@@ -282,7 +283,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
282 unsigned short keysym; 283 unsigned short keysym;
283 unsigned char type, value; 284 unsigned char type, value;
284 285
285 if (!kbd) 286 if (!kbd || !kbd->tty)
286 return; 287 return;
287 288
288 if (keycode >= 384) 289 if (keycode >= 384)
@@ -322,7 +323,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
322#endif 323#endif
323 (*k_handler[type])(kbd, value); 324 (*k_handler[type])(kbd, value);
324 } else 325 } else
325 to_utf8(kbd->port, keysym); 326 to_utf8(kbd->tty, keysym);
326} 327}
327 328
328/* 329/*
@@ -456,7 +457,6 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs,
456 457
457int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg) 458int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
458{ 459{
459 struct tty_struct *tty;
460 void __user *argp; 460 void __user *argp;
461 unsigned int ct; 461 unsigned int ct;
462 int perm; 462 int perm;
@@ -467,10 +467,7 @@ int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
467 * To have permissions to do most of the vt ioctls, we either have 467 * To have permissions to do most of the vt ioctls, we either have
468 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. 468 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
469 */ 469 */
470 tty = tty_port_tty_get(kbd->port); 470 perm = current->signal->tty == kbd->tty || capable(CAP_SYS_TTY_CONFIG);
471 /* FIXME this test is pretty racy */
472 perm = current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG);
473 tty_kref_put(tty);
474 switch (cmd) { 471 switch (cmd) {
475 case KDGKBTYPE: 472 case KDGKBTYPE:
476 return put_user(KB_101, (char __user *)argp); 473 return put_user(KB_101, (char __user *)argp);
diff --git a/drivers/s390/char/keyboard.h b/drivers/s390/char/keyboard.h
index d0ae2be5819..7e736aaeae6 100644
--- a/drivers/s390/char/keyboard.h
+++ b/drivers/s390/char/keyboard.h
@@ -1,7 +1,8 @@
1/* 1/*
2 * drivers/s390/char/keyboard.h
2 * ebcdic keycode functions for s390 console drivers 3 * ebcdic keycode functions for s390 console drivers
3 * 4 *
4 * Copyright IBM Corp. 2003 5 * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
5 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), 6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
6 */ 7 */
7 8
@@ -20,7 +21,7 @@ typedef void (fn_handler_fn)(struct kbd_data *);
20 */ 21 */
21 22
22struct kbd_data { 23struct kbd_data {
23 struct tty_port *port; 24 struct tty_struct *tty;
24 unsigned short **key_maps; 25 unsigned short **key_maps;
25 char **func_table; 26 char **func_table;
26 fn_handler_fn **fn_handler; 27 fn_handler_fn **fn_handler;
@@ -41,24 +42,16 @@ int kbd_ioctl(struct kbd_data *, unsigned int, unsigned long);
41 * Helper Functions. 42 * Helper Functions.
42 */ 43 */
43static inline void 44static inline void
44kbd_put_queue(struct tty_port *port, int ch) 45kbd_put_queue(struct tty_struct *tty, int ch)
45{ 46{
46 struct tty_struct *tty = tty_port_tty_get(port);
47 if (!tty)
48 return;
49 tty_insert_flip_char(tty, ch, 0); 47 tty_insert_flip_char(tty, ch, 0);
50 tty_schedule_flip(tty); 48 tty_schedule_flip(tty);
51 tty_kref_put(tty);
52} 49}
53 50
54static inline void 51static inline void
55kbd_puts_queue(struct tty_port *port, char *cp) 52kbd_puts_queue(struct tty_struct *tty, char *cp)
56{ 53{
57 struct tty_struct *tty = tty_port_tty_get(port);
58 if (!tty)
59 return;
60 while (*cp) 54 while (*cp)
61 tty_insert_flip_char(tty, *cp++, 0); 55 tty_insert_flip_char(tty, *cp++, 0);
62 tty_schedule_flip(tty); 56 tty_schedule_flip(tty);
63 tty_kref_put(tty);
64} 57}
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index f4ff515db25..5b8b8592d31 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -571,11 +571,8 @@ static int __init mon_init(void)
571 if (rc) 571 if (rc)
572 goto out_iucv; 572 goto out_iucv;
573 monreader_device = kzalloc(sizeof(struct device), GFP_KERNEL); 573 monreader_device = kzalloc(sizeof(struct device), GFP_KERNEL);
574 if (!monreader_device) { 574 if (!monreader_device)
575 rc = -ENOMEM;
576 goto out_driver; 575 goto out_driver;
577 }
578
579 dev_set_name(monreader_device, "monreader-dev"); 576 dev_set_name(monreader_device, "monreader-dev");
580 monreader_device->bus = &iucv_bus; 577 monreader_device->bus = &iucv_bus;
581 monreader_device->parent = iucv_root; 578 monreader_device->parent = iucv_root;
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 9a6c140c5f0..810ac38631c 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -7,6 +7,7 @@
7 * Copyright IBM Corp. 2003, 2009 7 * Copyright IBM Corp. 2003, 2009
8 */ 8 */
9 9
10#include <linux/kernel_stat.h>
10#include <linux/module.h> 11#include <linux/module.h>
11#include <linux/err.h> 12#include <linux/err.h>
12#include <linux/init.h> 13#include <linux/init.h>
@@ -75,7 +76,7 @@ static LIST_HEAD(raw3270_devices);
75static int raw3270_registered; 76static int raw3270_registered;
76 77
77/* Module parameters */ 78/* Module parameters */
78static bool tubxcorrect = 0; 79static int tubxcorrect = 0;
79module_param(tubxcorrect, bool, 0); 80module_param(tubxcorrect, bool, 0);
80 81
81/* 82/*
@@ -329,6 +330,7 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
329 struct raw3270_request *rq; 330 struct raw3270_request *rq;
330 int rc; 331 int rc;
331 332
333 kstat_cpu(smp_processor_id()).irqs[IOINT_C70]++;
332 rp = dev_get_drvdata(&cdev->dev); 334 rp = dev_get_drvdata(&cdev->dev);
333 if (!rp) 335 if (!rp)
334 return; 336 return;
@@ -1396,7 +1398,6 @@ static struct ccw_driver raw3270_ccw_driver = {
1396 .freeze = &raw3270_pm_stop, 1398 .freeze = &raw3270_pm_stop,
1397 .thaw = &raw3270_pm_start, 1399 .thaw = &raw3270_pm_start,
1398 .restore = &raw3270_pm_start, 1400 .restore = &raw3270_pm_start,
1399 .int_class = IRQIO_C70,
1400}; 1401};
1401 1402
1402static int 1403static int
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 12c16a65dd2..eaa7e78186f 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -334,7 +334,7 @@ sclp_dispatch_evbufs(struct sccb_header *sccb)
334 reg->receiver_fn(evbuf); 334 reg->receiver_fn(evbuf);
335 spin_lock_irqsave(&sclp_lock, flags); 335 spin_lock_irqsave(&sclp_lock, flags);
336 } else if (reg == NULL) 336 } else if (reg == NULL)
337 rc = -EOPNOTSUPP; 337 rc = -ENOSYS;
338 } 338 }
339 spin_unlock_irqrestore(&sclp_lock, flags); 339 spin_unlock_irqrestore(&sclp_lock, flags);
340 return rc; 340 return rc;
@@ -393,14 +393,14 @@ __sclp_find_req(u32 sccb)
393/* Handler for external interruption. Perform request post-processing. 393/* Handler for external interruption. Perform request post-processing.
394 * Prepare read event data request if necessary. Start processing of next 394 * Prepare read event data request if necessary. Start processing of next
395 * request on queue. */ 395 * request on queue. */
396static void sclp_interrupt_handler(struct ext_code ext_code, 396static void sclp_interrupt_handler(unsigned int ext_int_code,
397 unsigned int param32, unsigned long param64) 397 unsigned int param32, unsigned long param64)
398{ 398{
399 struct sclp_req *req; 399 struct sclp_req *req;
400 u32 finished_sccb; 400 u32 finished_sccb;
401 u32 evbuf_pending; 401 u32 evbuf_pending;
402 402
403 inc_irq_stat(IRQEXT_SCP); 403 kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++;
404 spin_lock(&sclp_lock); 404 spin_lock(&sclp_lock);
405 finished_sccb = param32 & 0xfffffff8; 405 finished_sccb = param32 & 0xfffffff8;
406 evbuf_pending = param32 & 0x3; 406 evbuf_pending = param32 & 0x3;
@@ -654,6 +654,16 @@ sclp_remove_processed(struct sccb_header *sccb)
654 654
655EXPORT_SYMBOL(sclp_remove_processed); 655EXPORT_SYMBOL(sclp_remove_processed);
656 656
657struct init_sccb {
658 struct sccb_header header;
659 u16 _reserved;
660 u16 mask_length;
661 sccb_mask_t receive_mask;
662 sccb_mask_t send_mask;
663 sccb_mask_t sclp_receive_mask;
664 sccb_mask_t sclp_send_mask;
665} __attribute__((packed));
666
657/* Prepare init mask request. Called while sclp_lock is locked. */ 667/* Prepare init mask request. Called while sclp_lock is locked. */
658static inline void 668static inline void
659__sclp_make_init_req(u32 receive_mask, u32 send_mask) 669__sclp_make_init_req(u32 receive_mask, u32 send_mask)
@@ -808,12 +818,12 @@ EXPORT_SYMBOL(sclp_reactivate);
808 818
809/* Handler for external interruption used during initialization. Modify 819/* Handler for external interruption used during initialization. Modify
810 * request state to done. */ 820 * request state to done. */
811static void sclp_check_handler(struct ext_code ext_code, 821static void sclp_check_handler(unsigned int ext_int_code,
812 unsigned int param32, unsigned long param64) 822 unsigned int param32, unsigned long param64)
813{ 823{
814 u32 finished_sccb; 824 u32 finished_sccb;
815 825
816 inc_irq_stat(IRQEXT_SCP); 826 kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++;
817 finished_sccb = param32 & 0xfffffff8; 827 finished_sccb = param32 & 0xfffffff8;
818 /* Is this the interrupt we are waiting for? */ 828 /* Is this the interrupt we are waiting for? */
819 if (finished_sccb == 0) 829 if (finished_sccb == 0)
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index 25bcd4c0ed8..49a1bb52bc8 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright IBM Corp. 1999,2012 2 * Copyright IBM Corp. 1999, 2009
3 * 3 *
4 * Author(s): Martin Peschke <mpeschke@de.ibm.com> 4 * Author(s): Martin Peschke <mpeschke@de.ibm.com>
5 * Martin Schwidefsky <schwidefsky@de.ibm.com> 5 * Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -88,22 +88,11 @@ struct sccb_header {
88 u16 response_code; 88 u16 response_code;
89} __attribute__((packed)); 89} __attribute__((packed));
90 90
91struct init_sccb {
92 struct sccb_header header;
93 u16 _reserved;
94 u16 mask_length;
95 sccb_mask_t receive_mask;
96 sccb_mask_t send_mask;
97 sccb_mask_t sclp_receive_mask;
98 sccb_mask_t sclp_send_mask;
99} __attribute__((packed));
100
101extern u64 sclp_facilities; 91extern u64 sclp_facilities;
102#define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) 92#define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL)
103#define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) 93#define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL)
104#define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL) 94#define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL)
105#define SCLP_HAS_CPU_RECONFIG (sclp_facilities & 0x0400000000000000ULL) 95#define SCLP_HAS_CPU_RECONFIG (sclp_facilities & 0x0400000000000000ULL)
106#define SCLP_HAS_PCI_RECONFIG (sclp_facilities & 0x0000000040000000ULL)
107 96
108 97
109struct gds_subvector { 98struct gds_subvector {
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index c44d13f607b..837e010299a 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright IBM Corp. 2007,2012 2 * Copyright IBM Corp. 2007, 2009
3 * 3 *
4 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>, 4 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
5 * Peter Oberparleiter <peter.oberparleiter@de.ibm.com> 5 * Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
@@ -12,19 +12,15 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/err.h> 14#include <linux/err.h>
15#include <linux/export.h>
16#include <linux/slab.h> 15#include <linux/slab.h>
17#include <linux/string.h> 16#include <linux/string.h>
18#include <linux/mm.h> 17#include <linux/mm.h>
19#include <linux/mmzone.h> 18#include <linux/mmzone.h>
20#include <linux/memory.h> 19#include <linux/memory.h>
21#include <linux/module.h>
22#include <linux/platform_device.h> 20#include <linux/platform_device.h>
23#include <asm/ctl_reg.h>
24#include <asm/chpid.h> 21#include <asm/chpid.h>
25#include <asm/setup.h>
26#include <asm/page.h>
27#include <asm/sclp.h> 22#include <asm/sclp.h>
23#include <asm/setup.h>
28 24
29#include "sclp.h" 25#include "sclp.h"
30 26
@@ -41,8 +37,7 @@ struct read_info_sccb {
41 u64 facilities; /* 48-55 */ 37 u64 facilities; /* 48-55 */
42 u8 _reserved2[84 - 56]; /* 56-83 */ 38 u8 _reserved2[84 - 56]; /* 56-83 */
43 u8 fac84; /* 84 */ 39 u8 fac84; /* 84 */
44 u8 fac85; /* 85 */ 40 u8 _reserved3[91 - 85]; /* 85-90 */
45 u8 _reserved3[91 - 86]; /* 86-90 */
46 u8 flags; /* 91 */ 41 u8 flags; /* 91 */
47 u8 _reserved4[100 - 92]; /* 92-99 */ 42 u8 _reserved4[100 - 92]; /* 92-99 */
48 u32 rnsize2; /* 100-103 */ 43 u32 rnsize2; /* 100-103 */
@@ -50,13 +45,11 @@ struct read_info_sccb {
50 u8 _reserved5[4096 - 112]; /* 112-4095 */ 45 u8 _reserved5[4096 - 112]; /* 112-4095 */
51} __attribute__((packed, aligned(PAGE_SIZE))); 46} __attribute__((packed, aligned(PAGE_SIZE)));
52 47
53static struct init_sccb __initdata early_event_mask_sccb __aligned(PAGE_SIZE);
54static struct read_info_sccb __initdata early_read_info_sccb; 48static struct read_info_sccb __initdata early_read_info_sccb;
55static int __initdata early_read_info_sccb_valid; 49static int __initdata early_read_info_sccb_valid;
56 50
57u64 sclp_facilities; 51u64 sclp_facilities;
58static u8 sclp_fac84; 52static u8 sclp_fac84;
59static u8 sclp_fac85;
60static unsigned long long rzm; 53static unsigned long long rzm;
61static unsigned long long rnmax; 54static unsigned long long rnmax;
62 55
@@ -68,8 +61,8 @@ static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
68 rc = sclp_service_call(cmd, sccb); 61 rc = sclp_service_call(cmd, sccb);
69 if (rc) 62 if (rc)
70 goto out; 63 goto out;
71 __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | 64 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
72 PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT); 65 PSW_MASK_WAIT | PSW_DEFAULT_KEY);
73 local_irq_disable(); 66 local_irq_disable();
74out: 67out:
75 /* Contents of the sccb might have changed. */ 68 /* Contents of the sccb might have changed. */
@@ -107,19 +100,6 @@ static void __init sclp_read_info_early(void)
107 } 100 }
108} 101}
109 102
110static void __init sclp_event_mask_early(void)
111{
112 struct init_sccb *sccb = &early_event_mask_sccb;
113 int rc;
114
115 do {
116 memset(sccb, 0, sizeof(*sccb));
117 sccb->header.length = sizeof(*sccb);
118 sccb->mask_length = sizeof(sccb_mask_t);
119 rc = sclp_cmd_sync_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb);
120 } while (rc == -EBUSY);
121}
122
123void __init sclp_facilities_detect(void) 103void __init sclp_facilities_detect(void)
124{ 104{
125 struct read_info_sccb *sccb; 105 struct read_info_sccb *sccb;
@@ -131,34 +111,9 @@ void __init sclp_facilities_detect(void)
131 sccb = &early_read_info_sccb; 111 sccb = &early_read_info_sccb;
132 sclp_facilities = sccb->facilities; 112 sclp_facilities = sccb->facilities;
133 sclp_fac84 = sccb->fac84; 113 sclp_fac84 = sccb->fac84;
134 sclp_fac85 = sccb->fac85;
135 rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; 114 rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
136 rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; 115 rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
137 rzm <<= 20; 116 rzm <<= 20;
138
139 sclp_event_mask_early();
140}
141
142bool __init sclp_has_linemode(void)
143{
144 struct init_sccb *sccb = &early_event_mask_sccb;
145
146 if (sccb->header.response_code != 0x20)
147 return 0;
148 if (sccb->sclp_send_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))
149 return 1;
150 return 0;
151}
152
153bool __init sclp_has_vt220(void)
154{
155 struct init_sccb *sccb = &early_event_mask_sccb;
156
157 if (sccb->header.response_code != 0x20)
158 return 0;
159 if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK)
160 return 1;
161 return 0;
162} 117}
163 118
164unsigned long long sclp_get_rnmax(void) 119unsigned long long sclp_get_rnmax(void)
@@ -171,12 +126,6 @@ unsigned long long sclp_get_rzm(void)
171 return rzm; 126 return rzm;
172} 127}
173 128
174u8 sclp_get_fac85(void)
175{
176 return sclp_fac85;
177}
178EXPORT_SYMBOL_GPL(sclp_get_fac85);
179
180/* 129/*
181 * This function will be called after sclp_facilities_detect(), which gets 130 * This function will be called after sclp_facilities_detect(), which gets
182 * called from early.c code. Therefore the sccb should have valid contents. 131 * called from early.c code. Therefore the sccb should have valid contents.
@@ -402,15 +351,7 @@ out:
402 351
403static int sclp_assign_storage(u16 rn) 352static int sclp_assign_storage(u16 rn)
404{ 353{
405 unsigned long long start; 354 return do_assign_storage(0x000d0001, rn);
406 int rc;
407
408 rc = do_assign_storage(0x000d0001, rn);
409 if (rc)
410 return rc;
411 start = rn2addr(rn);
412 storage_key_init_range(start, start + rzm);
413 return 0;
414} 355}
415 356
416static int sclp_unassign_storage(u16 rn) 357static int sclp_unassign_storage(u16 rn)
@@ -500,8 +441,9 @@ static int sclp_mem_notifier(struct notifier_block *nb,
500 start = arg->start_pfn << PAGE_SHIFT; 441 start = arg->start_pfn << PAGE_SHIFT;
501 size = arg->nr_pages << PAGE_SHIFT; 442 size = arg->nr_pages << PAGE_SHIFT;
502 mutex_lock(&sclp_mem_mutex); 443 mutex_lock(&sclp_mem_mutex);
503 for_each_clear_bit(id, sclp_storage_ids, sclp_max_storage_id + 1) 444 for (id = 0; id <= sclp_max_storage_id; id++)
504 sclp_attach_storage(id); 445 if (!test_bit(id, sclp_storage_ids))
446 sclp_attach_storage(id);
505 switch (action) { 447 switch (action) {
506 case MEM_ONLINE: 448 case MEM_ONLINE:
507 case MEM_GOING_OFFLINE: 449 case MEM_GOING_OFFLINE:
@@ -702,67 +644,6 @@ __initcall(sclp_detect_standby_memory);
702#endif /* CONFIG_MEMORY_HOTPLUG */ 644#endif /* CONFIG_MEMORY_HOTPLUG */
703 645
704/* 646/*
705 * PCI I/O adapter configuration related functions.
706 */
707#define SCLP_CMDW_CONFIGURE_PCI 0x001a0001
708#define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001
709
710#define SCLP_RECONFIG_PCI_ATPYE 2
711
712struct pci_cfg_sccb {
713 struct sccb_header header;
714 u8 atype; /* adapter type */
715 u8 reserved1;
716 u16 reserved2;
717 u32 aid; /* adapter identifier */
718} __packed;
719
720static int do_pci_configure(sclp_cmdw_t cmd, u32 fid)
721{
722 struct pci_cfg_sccb *sccb;
723 int rc;
724
725 if (!SCLP_HAS_PCI_RECONFIG)
726 return -EOPNOTSUPP;
727
728 sccb = (struct pci_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
729 if (!sccb)
730 return -ENOMEM;
731
732 sccb->header.length = PAGE_SIZE;
733 sccb->atype = SCLP_RECONFIG_PCI_ATPYE;
734 sccb->aid = fid;
735 rc = do_sync_request(cmd, sccb);
736 if (rc)
737 goto out;
738 switch (sccb->header.response_code) {
739 case 0x0020:
740 case 0x0120:
741 break;
742 default:
743 pr_warn("configure PCI I/O adapter failed: cmd=0x%08x response=0x%04x\n",
744 cmd, sccb->header.response_code);
745 rc = -EIO;
746 break;
747 }
748out:
749 free_page((unsigned long) sccb);
750 return rc;
751}
752
753int sclp_pci_configure(u32 fid)
754{
755 return do_pci_configure(SCLP_CMDW_CONFIGURE_PCI, fid);
756}
757EXPORT_SYMBOL(sclp_pci_configure);
758
759int sclp_pci_deconfigure(u32 fid)
760{
761 return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI, fid);
762}
763EXPORT_SYMBOL(sclp_pci_deconfigure);
764
765/*
766 * Channel path configuration related functions. 647 * Channel path configuration related functions.
767 */ 648 */
768 649
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index 444d36183a2..95b909ac2b7 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -1,4 +1,6 @@
1/* 1/*
2 * drivers/s390/char/sclp_config.c
3 *
2 * Copyright IBM Corp. 2007 4 * Copyright IBM Corp. 2007
3 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> 5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
4 */ 6 */
@@ -9,7 +11,7 @@
9#include <linux/init.h> 11#include <linux/init.h>
10#include <linux/errno.h> 12#include <linux/errno.h>
11#include <linux/cpu.h> 13#include <linux/cpu.h>
12#include <linux/device.h> 14#include <linux/sysdev.h>
13#include <linux/workqueue.h> 15#include <linux/workqueue.h>
14#include <asm/smp.h> 16#include <asm/smp.h>
15 17
@@ -29,14 +31,14 @@ static struct work_struct sclp_cpu_change_work;
29static void sclp_cpu_capability_notify(struct work_struct *work) 31static void sclp_cpu_capability_notify(struct work_struct *work)
30{ 32{
31 int cpu; 33 int cpu;
32 struct device *dev; 34 struct sys_device *sysdev;
33 35
34 s390_adjust_jiffies(); 36 s390_adjust_jiffies();
35 pr_warning("cpu capability changed.\n"); 37 pr_warning("cpu capability changed.\n");
36 get_online_cpus(); 38 get_online_cpus();
37 for_each_online_cpu(cpu) { 39 for_each_online_cpu(cpu) {
38 dev = get_cpu_device(cpu); 40 sysdev = get_cpu_sysdev(cpu);
39 kobject_uevent(&dev->kobj, KOBJ_CHANGE); 41 kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
40 } 42 }
41 put_online_cpus(); 43 put_online_cpus();
42} 44}
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c
index d70d8c20229..5716487b8c9 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * drivers/s390/char/sclp_cpi.c
2 * SCLP control programm identification 3 * SCLP control programm identification
3 * 4 *
4 * Copyright IBM Corp. 2001, 2007 5 * Copyright IBM Corp. 2001, 2007
diff --git a/drivers/s390/char/sclp_cpi_sys.c b/drivers/s390/char/sclp_cpi_sys.c
index 2acea809e2a..4a51e3f0968 100644
--- a/drivers/s390/char/sclp_cpi_sys.c
+++ b/drivers/s390/char/sclp_cpi_sys.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * drivers/s390/char/sclp_cpi_sys.c
2 * SCLP control program identification sysfs interface 3 * SCLP control program identification sysfs interface
3 * 4 *
4 * Copyright IBM Corp. 2001, 2007 5 * Copyright IBM Corp. 2001, 2007
@@ -20,7 +21,6 @@
20#include <linux/err.h> 21#include <linux/err.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
22#include <linux/completion.h> 23#include <linux/completion.h>
23#include <linux/export.h>
24#include <asm/ebcdic.h> 24#include <asm/ebcdic.h>
25#include <asm/sclp.h> 25#include <asm/sclp.h>
26 26
diff --git a/drivers/s390/char/sclp_cpi_sys.h b/drivers/s390/char/sclp_cpi_sys.h
index 65bb6a99c97..deef3e6ff49 100644
--- a/drivers/s390/char/sclp_cpi_sys.h
+++ b/drivers/s390/char/sclp_cpi_sys.h
@@ -1,4 +1,5 @@
1/* 1/*
2 * drivers/s390/char/sclp_cpi_sys.h
2 * SCLP control program identification sysfs interface 3 * SCLP control program identification sysfs interface
3 * 4 *
4 * Copyright IBM Corp. 2007 5 * Copyright IBM Corp. 2007
diff --git a/drivers/s390/char/sclp_ocf.c b/drivers/s390/char/sclp_ocf.c
index 2553db0fdb5..ab294d5a534 100644
--- a/drivers/s390/char/sclp_ocf.c
+++ b/drivers/s390/char/sclp_ocf.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * drivers/s390/char/sclp_ocf.c
2 * SCLP OCF communication parameters sysfs interface 3 * SCLP OCF communication parameters sysfs interface
3 * 4 *
4 * Copyright IBM Corp. 2011 5 * Copyright IBM Corp. 2011
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 475e470d976..a90a02c28d6 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -1,7 +1,8 @@
1/* 1/*
2 * drivers/s390/char/sclp_quiesce.c
2 * signal quiesce handler 3 * signal quiesce handler
3 * 4 *
4 * Copyright IBM Corp. 1999, 2004 5 * (C) Copyright IBM Corp. 1999,2004
5 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> 6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
6 * Peter Oberparleiter <peter.oberparleiter@de.ibm.com> 7 * Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
7 */ 8 */
@@ -14,6 +15,7 @@
14#include <linux/reboot.h> 15#include <linux/reboot.h>
15#include <linux/atomic.h> 16#include <linux/atomic.h>
16#include <asm/ptrace.h> 17#include <asm/ptrace.h>
18#include <asm/sigp.h>
17#include <asm/smp.h> 19#include <asm/smp.h>
18 20
19#include "sclp.h" 21#include "sclp.h"
@@ -28,8 +30,7 @@ static void do_machine_quiesce(void)
28 psw_t quiesce_psw; 30 psw_t quiesce_psw;
29 31
30 smp_send_stop(); 32 smp_send_stop();
31 quiesce_psw.mask = 33 quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
32 PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA | PSW_MASK_WAIT;
33 quiesce_psw.addr = 0xfff; 34 quiesce_psw.addr = 0xfff;
34 __load_psw(quiesce_psw); 35 __load_psw(quiesce_psw);
35} 36}
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index 3b13d58fe87..4be63be7344 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -463,7 +463,7 @@ sclp_emit_buffer(struct sclp_buffer *buffer,
463 /* Use write priority message */ 463 /* Use write priority message */
464 sccb->msg_buf.header.type = EVTYP_PMSGCMD; 464 sccb->msg_buf.header.type = EVTYP_PMSGCMD;
465 else 465 else
466 return -EOPNOTSUPP; 466 return -ENOSYS;
467 buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA; 467 buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA;
468 buffer->request.status = SCLP_REQ_FILLED; 468 buffer->request.status = SCLP_REQ_FILLED;
469 buffer->request.callback = sclp_writedata_callback; 469 buffer->request.callback = sclp_writedata_callback;
diff --git a/drivers/s390/char/sclp_sdias.c b/drivers/s390/char/sclp_sdias.c
index b1032931a1c..fa733ecd3d7 100644
--- a/drivers/s390/char/sclp_sdias.c
+++ b/drivers/s390/char/sclp_sdias.c
@@ -1,14 +1,13 @@
1/* 1/*
2 * Sclp "store data in absolut storage" 2 * Sclp "store data in absolut storage"
3 * 3 *
4 * Copyright IBM Corp. 2003, 2007 4 * Copyright IBM Corp. 2003,2007
5 * Author(s): Michael Holzheu 5 * Author(s): Michael Holzheu
6 */ 6 */
7 7
8#define KMSG_COMPONENT "sclp_sdias" 8#define KMSG_COMPONENT "sclp_sdias"
9#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 9#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
10 10
11#include <linux/completion.h>
12#include <linux/sched.h> 11#include <linux/sched.h>
13#include <asm/sclp.h> 12#include <asm/sclp.h>
14#include <asm/debug.h> 13#include <asm/debug.h>
@@ -63,29 +62,15 @@ struct sdias_sccb {
63} __attribute__((packed)); 62} __attribute__((packed));
64 63
65static struct sdias_sccb sccb __attribute__((aligned(4096))); 64static struct sdias_sccb sccb __attribute__((aligned(4096)));
66static struct sdias_evbuf sdias_evbuf;
67 65
68static DECLARE_COMPLETION(evbuf_accepted); 66static int sclp_req_done;
69static DECLARE_COMPLETION(evbuf_done); 67static wait_queue_head_t sdias_wq;
70static DEFINE_MUTEX(sdias_mutex); 68static DEFINE_MUTEX(sdias_mutex);
71 69
72/*
73 * Called by SCLP base when read event data has been completed (async mode only)
74 */
75static void sclp_sdias_receiver_fn(struct evbuf_header *evbuf)
76{
77 memcpy(&sdias_evbuf, evbuf,
78 min_t(unsigned long, sizeof(sdias_evbuf), evbuf->length));
79 complete(&evbuf_done);
80 TRACE("sclp_sdias_receiver_fn done\n");
81}
82
83/*
84 * Called by SCLP base when sdias event has been accepted
85 */
86static void sdias_callback(struct sclp_req *request, void *data) 70static void sdias_callback(struct sclp_req *request, void *data)
87{ 71{
88 complete(&evbuf_accepted); 72 sclp_req_done = 1;
73 wake_up(&sdias_wq); /* Inform caller, that request is complete */
89 TRACE("callback done\n"); 74 TRACE("callback done\n");
90} 75}
91 76
@@ -95,6 +80,7 @@ static int sdias_sclp_send(struct sclp_req *req)
95 int rc; 80 int rc;
96 81
97 for (retries = SDIAS_RETRIES; retries; retries--) { 82 for (retries = SDIAS_RETRIES; retries; retries--) {
83 sclp_req_done = 0;
98 TRACE("add request\n"); 84 TRACE("add request\n");
99 rc = sclp_add_request(req); 85 rc = sclp_add_request(req);
100 if (rc) { 86 if (rc) {
@@ -105,31 +91,16 @@ static int sdias_sclp_send(struct sclp_req *req)
105 continue; 91 continue;
106 } 92 }
107 /* initiated, wait for completion of service call */ 93 /* initiated, wait for completion of service call */
108 wait_for_completion(&evbuf_accepted); 94 wait_event(sdias_wq, (sclp_req_done == 1));
109 if (req->status == SCLP_REQ_FAILED) { 95 if (req->status == SCLP_REQ_FAILED) {
110 TRACE("sclp request failed\n"); 96 TRACE("sclp request failed\n");
97 rc = -EIO;
111 continue; 98 continue;
112 } 99 }
113 /* if not accepted, retry */
114 if (!(sccb.evbuf.hdr.flags & 0x80)) {
115 TRACE("sclp request failed: flags=%x\n",
116 sccb.evbuf.hdr.flags);
117 continue;
118 }
119 /*
120 * for the sync interface the response is in the initial sccb
121 */
122 if (!sclp_sdias_register.receiver_fn) {
123 memcpy(&sdias_evbuf, &sccb.evbuf, sizeof(sdias_evbuf));
124 TRACE("sync request done\n");
125 return 0;
126 }
127 /* otherwise we wait for completion */
128 wait_for_completion(&evbuf_done);
129 TRACE("request done\n"); 100 TRACE("request done\n");
130 return 0; 101 break;
131 } 102 }
132 return -EIO; 103 return rc;
133} 104}
134 105
135/* 106/*
@@ -169,12 +140,13 @@ int sclp_sdias_blk_count(void)
169 goto out; 140 goto out;
170 } 141 }
171 142
172 switch (sdias_evbuf.event_status) { 143 switch (sccb.evbuf.event_status) {
173 case 0: 144 case 0:
174 rc = sdias_evbuf.blk_cnt; 145 rc = sccb.evbuf.blk_cnt;
175 break; 146 break;
176 default: 147 default:
177 pr_err("SCLP error: %x\n", sdias_evbuf.event_status); 148 pr_err("SCLP error: %x\n",
149 sccb.evbuf.event_status);
178 rc = -EIO; 150 rc = -EIO;
179 goto out; 151 goto out;
180 } 152 }
@@ -211,7 +183,7 @@ int sclp_sdias_copy(void *dest, int start_blk, int nr_blks)
211 sccb.evbuf.event_qual = EQ_STORE_DATA; 183 sccb.evbuf.event_qual = EQ_STORE_DATA;
212 sccb.evbuf.data_id = DI_FCP_DUMP; 184 sccb.evbuf.data_id = DI_FCP_DUMP;
213 sccb.evbuf.event_id = 4712; 185 sccb.evbuf.event_id = 4712;
214#ifdef CONFIG_64BIT 186#ifdef __s390x__
215 sccb.evbuf.asa_size = ASA_SIZE_64; 187 sccb.evbuf.asa_size = ASA_SIZE_64;
216#else 188#else
217 sccb.evbuf.asa_size = ASA_SIZE_32; 189 sccb.evbuf.asa_size = ASA_SIZE_32;
@@ -239,20 +211,18 @@ int sclp_sdias_copy(void *dest, int start_blk, int nr_blks)
239 goto out; 211 goto out;
240 } 212 }
241 213
242 switch (sdias_evbuf.event_status) { 214 switch (sccb.evbuf.event_status) {
243 case EVSTATE_ALL_STORED: 215 case EVSTATE_ALL_STORED:
244 TRACE("all stored\n"); 216 TRACE("all stored\n");
245 break;
246 case EVSTATE_PART_STORED: 217 case EVSTATE_PART_STORED:
247 TRACE("part stored: %i\n", sdias_evbuf.blk_cnt); 218 TRACE("part stored: %i\n", sccb.evbuf.blk_cnt);
248 break; 219 break;
249 case EVSTATE_NO_DATA: 220 case EVSTATE_NO_DATA:
250 TRACE("no data\n"); 221 TRACE("no data\n");
251 /* fall through */
252 default: 222 default:
253 pr_err("Error from SCLP while copying hsa. " 223 pr_err("Error from SCLP while copying hsa. "
254 "Event status = %x\n", 224 "Event status = %x\n",
255 sdias_evbuf.event_status); 225 sccb.evbuf.event_status);
256 rc = -EIO; 226 rc = -EIO;
257 } 227 }
258out: 228out:
@@ -260,50 +230,19 @@ out:
260 return rc; 230 return rc;
261} 231}
262 232
263static int __init sclp_sdias_register_check(void) 233int __init sclp_sdias_init(void)
264{ 234{
265 int rc; 235 int rc;
266 236
267 rc = sclp_register(&sclp_sdias_register);
268 if (rc)
269 return rc;
270 if (sclp_sdias_blk_count() == 0) {
271 sclp_unregister(&sclp_sdias_register);
272 return -ENODEV;
273 }
274 return 0;
275}
276
277static int __init sclp_sdias_init_sync(void)
278{
279 TRACE("Try synchronous mode\n");
280 sclp_sdias_register.receive_mask = 0;
281 sclp_sdias_register.receiver_fn = NULL;
282 return sclp_sdias_register_check();
283}
284
285static int __init sclp_sdias_init_async(void)
286{
287 TRACE("Try asynchronous mode\n");
288 sclp_sdias_register.receive_mask = EVTYP_SDIAS_MASK;
289 sclp_sdias_register.receiver_fn = sclp_sdias_receiver_fn;
290 return sclp_sdias_register_check();
291}
292
293int __init sclp_sdias_init(void)
294{
295 if (ipl_info.type != IPL_TYPE_FCP_DUMP) 237 if (ipl_info.type != IPL_TYPE_FCP_DUMP)
296 return 0; 238 return 0;
297 sdias_dbf = debug_register("dump_sdias", 4, 1, 4 * sizeof(long)); 239 sdias_dbf = debug_register("dump_sdias", 4, 1, 4 * sizeof(long));
298 debug_register_view(sdias_dbf, &debug_sprintf_view); 240 debug_register_view(sdias_dbf, &debug_sprintf_view);
299 debug_set_level(sdias_dbf, 6); 241 debug_set_level(sdias_dbf, 6);
300 if (sclp_sdias_init_sync() == 0) 242 rc = sclp_register(&sclp_sdias_register);
301 goto out; 243 if (rc)
302 if (sclp_sdias_init_async() == 0) 244 return rc;
303 goto out; 245 init_waitqueue_head(&sdias_wq);
304 TRACE("init failed\n");
305 return -ENODEV;
306out:
307 TRACE("init done\n"); 246 TRACE("init done\n");
308 return 0; 247 return 0;
309} 248}
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 877fbc37c1e..a879c139926 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -1,8 +1,9 @@
1/* 1/*
2 * drivers/s390/char/sclp_tty.c
2 * SCLP line mode terminal driver. 3 * SCLP line mode terminal driver.
3 * 4 *
4 * S390 version 5 * S390 version
5 * Copyright IBM Corp. 1999 6 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Martin Peschke <mpeschke@de.ibm.com> 7 * Author(s): Martin Peschke <mpeschke@de.ibm.com>
7 * Martin Schwidefsky <schwidefsky@de.ibm.com> 8 * Martin Schwidefsky <schwidefsky@de.ibm.com>
8 */ 9 */
@@ -47,7 +48,7 @@ static struct sclp_buffer *sclp_ttybuf;
47/* Timer for delayed output of console messages. */ 48/* Timer for delayed output of console messages. */
48static struct timer_list sclp_tty_timer; 49static struct timer_list sclp_tty_timer;
49 50
50static struct tty_port sclp_port; 51static struct tty_struct *sclp_tty;
51static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE]; 52static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE];
52static unsigned short int sclp_tty_chars_count; 53static unsigned short int sclp_tty_chars_count;
53 54
@@ -63,7 +64,7 @@ static int sclp_tty_columns = 80;
63static int 64static int
64sclp_tty_open(struct tty_struct *tty, struct file *filp) 65sclp_tty_open(struct tty_struct *tty, struct file *filp)
65{ 66{
66 tty_port_tty_set(&sclp_port, tty); 67 sclp_tty = tty;
67 tty->driver_data = NULL; 68 tty->driver_data = NULL;
68 tty->low_latency = 0; 69 tty->low_latency = 0;
69 return 0; 70 return 0;
@@ -75,7 +76,7 @@ sclp_tty_close(struct tty_struct *tty, struct file *filp)
75{ 76{
76 if (tty->count > 1) 77 if (tty->count > 1)
77 return; 78 return;
78 tty_port_tty_set(&sclp_port, NULL); 79 sclp_tty = NULL;
79} 80}
80 81
81/* 82/*
@@ -107,7 +108,6 @@ sclp_tty_write_room (struct tty_struct *tty)
107static void 108static void
108sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc) 109sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
109{ 110{
110 struct tty_struct *tty;
111 unsigned long flags; 111 unsigned long flags;
112 void *page; 112 void *page;
113 113
@@ -126,10 +126,8 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
126 spin_unlock_irqrestore(&sclp_tty_lock, flags); 126 spin_unlock_irqrestore(&sclp_tty_lock, flags);
127 } while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback)); 127 } while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback));
128 /* check if the tty needs a wake up call */ 128 /* check if the tty needs a wake up call */
129 tty = tty_port_tty_get(&sclp_port); 129 if (sclp_tty != NULL) {
130 if (tty != NULL) { 130 tty_wakeup(sclp_tty);
131 tty_wakeup(tty);
132 tty_kref_put(tty);
133 } 131 }
134} 132}
135 133
@@ -328,22 +326,21 @@ sclp_tty_flush_buffer(struct tty_struct *tty)
328static void 326static void
329sclp_tty_input(unsigned char* buf, unsigned int count) 327sclp_tty_input(unsigned char* buf, unsigned int count)
330{ 328{
331 struct tty_struct *tty = tty_port_tty_get(&sclp_port);
332 unsigned int cchar; 329 unsigned int cchar;
333 330
334 /* 331 /*
335 * If this tty driver is currently closed 332 * If this tty driver is currently closed
336 * then throw the received input away. 333 * then throw the received input away.
337 */ 334 */
338 if (tty == NULL) 335 if (sclp_tty == NULL)
339 return; 336 return;
340 cchar = ctrlchar_handle(buf, count, tty); 337 cchar = ctrlchar_handle(buf, count, sclp_tty);
341 switch (cchar & CTRLCHAR_MASK) { 338 switch (cchar & CTRLCHAR_MASK) {
342 case CTRLCHAR_SYSRQ: 339 case CTRLCHAR_SYSRQ:
343 break; 340 break;
344 case CTRLCHAR_CTRL: 341 case CTRLCHAR_CTRL:
345 tty_insert_flip_char(tty, cchar, TTY_NORMAL); 342 tty_insert_flip_char(sclp_tty, cchar, TTY_NORMAL);
346 tty_flip_buffer_push(tty); 343 tty_flip_buffer_push(sclp_tty);
347 break; 344 break;
348 case CTRLCHAR_NONE: 345 case CTRLCHAR_NONE:
349 /* send (normal) input to line discipline */ 346 /* send (normal) input to line discipline */
@@ -351,14 +348,13 @@ sclp_tty_input(unsigned char* buf, unsigned int count)
351 (strncmp((const char *) buf + count - 2, "^n", 2) && 348 (strncmp((const char *) buf + count - 2, "^n", 2) &&
352 strncmp((const char *) buf + count - 2, "\252n", 2))) { 349 strncmp((const char *) buf + count - 2, "\252n", 2))) {
353 /* add the auto \n */ 350 /* add the auto \n */
354 tty_insert_flip_string(tty, buf, count); 351 tty_insert_flip_string(sclp_tty, buf, count);
355 tty_insert_flip_char(tty, '\n', TTY_NORMAL); 352 tty_insert_flip_char(sclp_tty, '\n', TTY_NORMAL);
356 } else 353 } else
357 tty_insert_flip_string(tty, buf, count - 2); 354 tty_insert_flip_string(sclp_tty, buf, count - 2);
358 tty_flip_buffer_push(tty); 355 tty_flip_buffer_push(sclp_tty);
359 break; 356 break;
360 } 357 }
361 tty_kref_put(tty);
362} 358}
363 359
364/* 360/*
@@ -547,6 +543,7 @@ sclp_tty_init(void)
547 sclp_tty_tolower = 1; 543 sclp_tty_tolower = 1;
548 } 544 }
549 sclp_tty_chars_count = 0; 545 sclp_tty_chars_count = 0;
546 sclp_tty = NULL;
550 547
551 rc = sclp_register(&sclp_input_event); 548 rc = sclp_register(&sclp_input_event);
552 if (rc) { 549 if (rc) {
@@ -554,8 +551,7 @@ sclp_tty_init(void)
554 return rc; 551 return rc;
555 } 552 }
556 553
557 tty_port_init(&sclp_port); 554 driver->owner = THIS_MODULE;
558
559 driver->driver_name = "sclp_line"; 555 driver->driver_name = "sclp_line";
560 driver->name = "sclp_line"; 556 driver->name = "sclp_line";
561 driver->major = TTY_MAJOR; 557 driver->major = TTY_MAJOR;
@@ -568,11 +564,9 @@ sclp_tty_init(void)
568 driver->init_termios.c_lflag = ISIG | ECHO; 564 driver->init_termios.c_lflag = ISIG | ECHO;
569 driver->flags = TTY_DRIVER_REAL_RAW; 565 driver->flags = TTY_DRIVER_REAL_RAW;
570 tty_set_operations(driver, &sclp_ops); 566 tty_set_operations(driver, &sclp_ops);
571 tty_port_link_device(&sclp_port, driver, 0);
572 rc = tty_register_driver(driver); 567 rc = tty_register_driver(driver);
573 if (rc) { 568 if (rc) {
574 put_tty_driver(driver); 569 put_tty_driver(driver);
575 tty_port_destroy(&sclp_port);
576 return rc; 570 return rc;
577 } 571 }
578 sclp_tty_driver = driver; 572 sclp_tty_driver = driver;
diff --git a/drivers/s390/char/sclp_tty.h b/drivers/s390/char/sclp_tty.h
index c8773421c31..4b965b22fec 100644
--- a/drivers/s390/char/sclp_tty.h
+++ b/drivers/s390/char/sclp_tty.h
@@ -1,8 +1,9 @@
1/* 1/*
2 * drivers/s390/char/sclp_tty.h
2 * interface to the SCLP-read/write driver 3 * interface to the SCLP-read/write driver
3 * 4 *
4 * S390 version 5 * S390 version
5 * Copyright IBM Corp. 1999 6 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Martin Peschke <mpeschke@de.ibm.com> 7 * Author(s): Martin Peschke <mpeschke@de.ibm.com>
7 * Martin Schwidefsky <schwidefsky@de.ibm.com> 8 * Martin Schwidefsky <schwidefsky@de.ibm.com>
8 */ 9 */
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index effcc8756e0..5d706e6c946 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -34,6 +34,7 @@
34#define SCLP_VT220_DEVICE_NAME "ttysclp" 34#define SCLP_VT220_DEVICE_NAME "ttysclp"
35#define SCLP_VT220_CONSOLE_NAME "ttyS" 35#define SCLP_VT220_CONSOLE_NAME "ttyS"
36#define SCLP_VT220_CONSOLE_INDEX 1 /* console=ttyS1 */ 36#define SCLP_VT220_CONSOLE_INDEX 1 /* console=ttyS1 */
37#define SCLP_VT220_BUF_SIZE 80
37 38
38/* Representation of a single write request */ 39/* Representation of a single write request */
39struct sclp_vt220_request { 40struct sclp_vt220_request {
@@ -55,7 +56,8 @@ struct sclp_vt220_sccb {
55/* Structures and data needed to register tty driver */ 56/* Structures and data needed to register tty driver */
56static struct tty_driver *sclp_vt220_driver; 57static struct tty_driver *sclp_vt220_driver;
57 58
58static struct tty_port sclp_vt220_port; 59/* The tty_struct that the kernel associated with us */
60static struct tty_struct *sclp_vt220_tty;
59 61
60/* Lock to protect internal data from concurrent access */ 62/* Lock to protect internal data from concurrent access */
61static spinlock_t sclp_vt220_lock; 63static spinlock_t sclp_vt220_lock;
@@ -114,7 +116,6 @@ static struct sclp_register sclp_vt220_register = {
114static void 116static void
115sclp_vt220_process_queue(struct sclp_vt220_request *request) 117sclp_vt220_process_queue(struct sclp_vt220_request *request)
116{ 118{
117 struct tty_struct *tty;
118 unsigned long flags; 119 unsigned long flags;
119 void *page; 120 void *page;
120 121
@@ -140,10 +141,8 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request)
140 if (request == NULL && sclp_vt220_flush_later) 141 if (request == NULL && sclp_vt220_flush_later)
141 sclp_vt220_emit_current(); 142 sclp_vt220_emit_current();
142 /* Check if the tty needs a wake up call */ 143 /* Check if the tty needs a wake up call */
143 tty = tty_port_tty_get(&sclp_vt220_port); 144 if (sclp_vt220_tty != NULL) {
144 if (tty) { 145 tty_wakeup(sclp_vt220_tty);
145 tty_wakeup(tty);
146 tty_kref_put(tty);
147 } 146 }
148} 147}
149 148
@@ -461,12 +460,11 @@ sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
461static void 460static void
462sclp_vt220_receiver_fn(struct evbuf_header *evbuf) 461sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
463{ 462{
464 struct tty_struct *tty = tty_port_tty_get(&sclp_vt220_port);
465 char *buffer; 463 char *buffer;
466 unsigned int count; 464 unsigned int count;
467 465
468 /* Ignore input if device is not open */ 466 /* Ignore input if device is not open */
469 if (tty == NULL) 467 if (sclp_vt220_tty == NULL)
470 return; 468 return;
471 469
472 buffer = (char *) ((addr_t) evbuf + sizeof(struct evbuf_header)); 470 buffer = (char *) ((addr_t) evbuf + sizeof(struct evbuf_header));
@@ -480,11 +478,10 @@ sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
480 /* Send input to line discipline */ 478 /* Send input to line discipline */
481 buffer++; 479 buffer++;
482 count--; 480 count--;
483 tty_insert_flip_string(tty, buffer, count); 481 tty_insert_flip_string(sclp_vt220_tty, buffer, count);
484 tty_flip_buffer_push(tty); 482 tty_flip_buffer_push(sclp_vt220_tty);
485 break; 483 break;
486 } 484 }
487 tty_kref_put(tty);
488} 485}
489 486
490/* 487/*
@@ -494,7 +491,10 @@ static int
494sclp_vt220_open(struct tty_struct *tty, struct file *filp) 491sclp_vt220_open(struct tty_struct *tty, struct file *filp)
495{ 492{
496 if (tty->count == 1) { 493 if (tty->count == 1) {
497 tty_port_tty_set(&sclp_vt220_port, tty); 494 sclp_vt220_tty = tty;
495 tty->driver_data = kmalloc(SCLP_VT220_BUF_SIZE, GFP_KERNEL);
496 if (tty->driver_data == NULL)
497 return -ENOMEM;
498 tty->low_latency = 0; 498 tty->low_latency = 0;
499 if (!tty->winsize.ws_row && !tty->winsize.ws_col) { 499 if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
500 tty->winsize.ws_row = 24; 500 tty->winsize.ws_row = 24;
@@ -510,8 +510,11 @@ sclp_vt220_open(struct tty_struct *tty, struct file *filp)
510static void 510static void
511sclp_vt220_close(struct tty_struct *tty, struct file *filp) 511sclp_vt220_close(struct tty_struct *tty, struct file *filp)
512{ 512{
513 if (tty->count == 1) 513 if (tty->count == 1) {
514 tty_port_tty_set(&sclp_vt220_port, NULL); 514 sclp_vt220_tty = NULL;
515 kfree(tty->driver_data);
516 tty->driver_data = NULL;
517 }
515} 518}
516 519
517/* 520/*
@@ -615,7 +618,6 @@ static void __init __sclp_vt220_cleanup(void)
615 return; 618 return;
616 sclp_unregister(&sclp_vt220_register); 619 sclp_unregister(&sclp_vt220_register);
617 __sclp_vt220_free_pages(); 620 __sclp_vt220_free_pages();
618 tty_port_destroy(&sclp_vt220_port);
619} 621}
620 622
621/* Allocate buffer pages and register with sclp core. Controlled by init 623/* Allocate buffer pages and register with sclp core. Controlled by init
@@ -633,9 +635,9 @@ static int __init __sclp_vt220_init(int num_pages)
633 INIT_LIST_HEAD(&sclp_vt220_empty); 635 INIT_LIST_HEAD(&sclp_vt220_empty);
634 INIT_LIST_HEAD(&sclp_vt220_outqueue); 636 INIT_LIST_HEAD(&sclp_vt220_outqueue);
635 init_timer(&sclp_vt220_timer); 637 init_timer(&sclp_vt220_timer);
636 tty_port_init(&sclp_vt220_port);
637 sclp_vt220_current_request = NULL; 638 sclp_vt220_current_request = NULL;
638 sclp_vt220_buffered_chars = 0; 639 sclp_vt220_buffered_chars = 0;
640 sclp_vt220_tty = NULL;
639 sclp_vt220_flush_later = 0; 641 sclp_vt220_flush_later = 0;
640 642
641 /* Allocate pages for output buffering */ 643 /* Allocate pages for output buffering */
@@ -651,7 +653,6 @@ out:
651 if (rc) { 653 if (rc) {
652 __sclp_vt220_free_pages(); 654 __sclp_vt220_free_pages();
653 sclp_vt220_init_count--; 655 sclp_vt220_init_count--;
654 tty_port_destroy(&sclp_vt220_port);
655 } 656 }
656 return rc; 657 return rc;
657} 658}
@@ -684,6 +685,7 @@ static int __init sclp_vt220_tty_init(void)
684 if (rc) 685 if (rc)
685 goto out_driver; 686 goto out_driver;
686 687
688 driver->owner = THIS_MODULE;
687 driver->driver_name = SCLP_VT220_DRIVER_NAME; 689 driver->driver_name = SCLP_VT220_DRIVER_NAME;
688 driver->name = SCLP_VT220_DEVICE_NAME; 690 driver->name = SCLP_VT220_DEVICE_NAME;
689 driver->major = SCLP_VT220_MAJOR; 691 driver->major = SCLP_VT220_MAJOR;
@@ -693,7 +695,6 @@ static int __init sclp_vt220_tty_init(void)
693 driver->init_termios = tty_std_termios; 695 driver->init_termios = tty_std_termios;
694 driver->flags = TTY_DRIVER_REAL_RAW; 696 driver->flags = TTY_DRIVER_REAL_RAW;
695 tty_set_operations(driver, &sclp_vt220_ops); 697 tty_set_operations(driver, &sclp_vt220_ops);
696 tty_port_link_device(&sclp_vt220_port, driver, 0);
697 698
698 rc = tty_register_driver(driver); 699 rc = tty_register_driver(driver);
699 if (rc) 700 if (rc)
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index ea664dd4f56..267b54e8ff5 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -1,4 +1,5 @@
1/* 1/*
2 * drivers/s390/char/tape.h
2 * tape device driver for 3480/3490E/3590 tapes. 3 * tape device driver for 3480/3490E/3590 tapes.
3 * 4 *
4 * S390 and zSeries version 5 * S390 and zSeries version
@@ -15,6 +16,7 @@
15#include <asm/ccwdev.h> 16#include <asm/ccwdev.h>
16#include <asm/debug.h> 17#include <asm/debug.h>
17#include <asm/idals.h> 18#include <asm/idals.h>
19#include <linux/blkdev.h>
18#include <linux/kernel.h> 20#include <linux/kernel.h>
19#include <linux/module.h> 21#include <linux/module.h>
20#include <linux/mtio.h> 22#include <linux/mtio.h>
@@ -152,6 +154,12 @@ struct tape_discipline {
152 struct tape_request *(*read_block)(struct tape_device *, size_t); 154 struct tape_request *(*read_block)(struct tape_device *, size_t);
153 struct tape_request *(*write_block)(struct tape_device *, size_t); 155 struct tape_request *(*write_block)(struct tape_device *, size_t);
154 void (*process_eov)(struct tape_device*); 156 void (*process_eov)(struct tape_device*);
157#ifdef CONFIG_S390_TAPE_BLOCK
158 /* Block device stuff. */
159 struct tape_request *(*bread)(struct tape_device *, struct request *);
160 void (*check_locate)(struct tape_device *, struct tape_request *);
161 void (*free_bread)(struct tape_request *);
162#endif
155 /* ioctl function for additional ioctls. */ 163 /* ioctl function for additional ioctls. */
156 int (*ioctl_fn)(struct tape_device *, unsigned int, unsigned long); 164 int (*ioctl_fn)(struct tape_device *, unsigned int, unsigned long);
157 /* Array of tape commands with TAPE_NR_MTOPS entries */ 165 /* Array of tape commands with TAPE_NR_MTOPS entries */
@@ -174,6 +182,26 @@ struct tape_char_data {
174 int block_size; /* of size block_size. */ 182 int block_size; /* of size block_size. */
175}; 183};
176 184
185#ifdef CONFIG_S390_TAPE_BLOCK
186/* Block Frontend Data */
187struct tape_blk_data
188{
189 struct tape_device * device;
190 /* Block device request queue. */
191 struct request_queue * request_queue;
192 spinlock_t request_queue_lock;
193
194 /* Task to move entries from block request to CCS request queue. */
195 struct work_struct requeue_task;
196 atomic_t requeue_scheduled;
197
198 /* Current position on the tape. */
199 long block_position;
200 int medium_changed;
201 struct gendisk * disk;
202};
203#endif
204
177/* Tape Info */ 205/* Tape Info */
178struct tape_device { 206struct tape_device {
179 /* entry in tape_device_list */ 207 /* entry in tape_device_list */
@@ -220,6 +248,10 @@ struct tape_device {
220 248
221 /* Character device frontend data */ 249 /* Character device frontend data */
222 struct tape_char_data char_data; 250 struct tape_char_data char_data;
251#ifdef CONFIG_S390_TAPE_BLOCK
252 /* Block dev frontend data */
253 struct tape_blk_data blk_data;
254#endif
223 255
224 /* Function to start or stop the next request later. */ 256 /* Function to start or stop the next request later. */
225 struct delayed_work tape_dnr; 257 struct delayed_work tape_dnr;
@@ -281,6 +313,19 @@ extern void tapechar_exit(void);
281extern int tapechar_setup_device(struct tape_device *); 313extern int tapechar_setup_device(struct tape_device *);
282extern void tapechar_cleanup_device(struct tape_device *); 314extern void tapechar_cleanup_device(struct tape_device *);
283 315
316/* Externals from tape_block.c */
317#ifdef CONFIG_S390_TAPE_BLOCK
318extern int tapeblock_init (void);
319extern void tapeblock_exit(void);
320extern int tapeblock_setup_device(struct tape_device *);
321extern void tapeblock_cleanup_device(struct tape_device *);
322#else
323static inline int tapeblock_init (void) {return 0;}
324static inline void tapeblock_exit (void) {;}
325static inline int tapeblock_setup_device(struct tape_device *t) {return 0;}
326static inline void tapeblock_cleanup_device (struct tape_device *t) {;}
327#endif
328
284/* tape initialisation functions */ 329/* tape initialisation functions */
285#ifdef CONFIG_PROC_FS 330#ifdef CONFIG_PROC_FS
286extern void tape_proc_init (void); 331extern void tape_proc_init (void);
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 9aa79702b37..9eff2df70dd 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * drivers/s390/char/tape_34xx.c
2 * tape device discipline for 3480/3490 tapes. 3 * tape device discipline for 3480/3490 tapes.
3 * 4 *
4 * Copyright IBM Corp. 2001, 2009 5 * Copyright IBM Corp. 2001, 2009
@@ -322,6 +323,20 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
322 inhibit_cu_recovery = (*device->modeset_byte & 0x80) ? 1 : 0; 323 inhibit_cu_recovery = (*device->modeset_byte & 0x80) ? 1 : 0;
323 sense = irb->ecw; 324 sense = irb->ecw;
324 325
326#ifdef CONFIG_S390_TAPE_BLOCK
327 if (request->op == TO_BLOCK) {
328 /*
329 * Recovery for block device requests. Set the block_position
330 * to something invalid and retry.
331 */
332 device->blk_data.block_position = -1;
333 if (request->retries-- <= 0)
334 return tape_34xx_erp_failed(request, -EIO);
335 else
336 return tape_34xx_erp_retry(request);
337 }
338#endif
339
325 if ( 340 if (
326 sense[0] & SENSE_COMMAND_REJECT && 341 sense[0] & SENSE_COMMAND_REJECT &&
327 sense[1] & SENSE_WRITE_PROTECT 342 sense[1] & SENSE_WRITE_PROTECT
@@ -1114,6 +1129,123 @@ tape_34xx_mtseek(struct tape_device *device, int mt_count)
1114 return tape_do_io_free(device, request); 1129 return tape_do_io_free(device, request);
1115} 1130}
1116 1131
1132#ifdef CONFIG_S390_TAPE_BLOCK
1133/*
1134 * Tape block read for 34xx.
1135 */
1136static struct tape_request *
1137tape_34xx_bread(struct tape_device *device, struct request *req)
1138{
1139 struct tape_request *request;
1140 struct ccw1 *ccw;
1141 int count = 0;
1142 unsigned off;
1143 char *dst;
1144 struct bio_vec *bv;
1145 struct req_iterator iter;
1146 struct tape_34xx_block_id * start_block;
1147
1148 DBF_EVENT(6, "xBREDid:");
1149
1150 /* Count the number of blocks for the request. */
1151 rq_for_each_segment(bv, req, iter)
1152 count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9);
1153
1154 /* Allocate the ccw request. */
1155 request = tape_alloc_request(3+count+1, 8);
1156 if (IS_ERR(request))
1157 return request;
1158
1159 /* Setup ccws. */
1160 request->op = TO_BLOCK;
1161 start_block = (struct tape_34xx_block_id *) request->cpdata;
1162 start_block->block = blk_rq_pos(req) >> TAPEBLOCK_HSEC_S2B;
1163 DBF_EVENT(6, "start_block = %i\n", start_block->block);
1164
1165 ccw = request->cpaddr;
1166 ccw = tape_ccw_cc(ccw, MODE_SET_DB, 1, device->modeset_byte);
1167
1168 /*
1169 * We always setup a nop after the mode set ccw. This slot is
1170 * used in tape_std_check_locate to insert a locate ccw if the
1171 * current tape position doesn't match the start block to be read.
1172 * The second nop will be filled with a read block id which is in
1173 * turn used by tape_34xx_free_bread to populate the segment bid
1174 * table.
1175 */
1176 ccw = tape_ccw_cc(ccw, NOP, 0, NULL);
1177 ccw = tape_ccw_cc(ccw, NOP, 0, NULL);
1178
1179 rq_for_each_segment(bv, req, iter) {
1180 dst = kmap(bv->bv_page) + bv->bv_offset;
1181 for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) {
1182 ccw->flags = CCW_FLAG_CC;
1183 ccw->cmd_code = READ_FORWARD;
1184 ccw->count = TAPEBLOCK_HSEC_SIZE;
1185 set_normalized_cda(ccw, (void*) __pa(dst));
1186 ccw++;
1187 dst += TAPEBLOCK_HSEC_SIZE;
1188 }
1189 }
1190
1191 ccw = tape_ccw_end(ccw, NOP, 0, NULL);
1192 DBF_EVENT(6, "xBREDccwg\n");
1193 return request;
1194}
1195
1196static void
1197tape_34xx_free_bread (struct tape_request *request)
1198{
1199 struct ccw1* ccw;
1200
1201 ccw = request->cpaddr;
1202 if ((ccw + 2)->cmd_code == READ_BLOCK_ID) {
1203 struct {
1204 struct tape_34xx_block_id cbid;
1205 struct tape_34xx_block_id dbid;
1206 } __attribute__ ((packed)) *rbi_data;
1207
1208 rbi_data = request->cpdata;
1209
1210 if (request->device)
1211 tape_34xx_add_sbid(request->device, rbi_data->cbid);
1212 }
1213
1214 /* Last ccw is a nop and doesn't need clear_normalized_cda */
1215 for (; ccw->flags & CCW_FLAG_CC; ccw++)
1216 if (ccw->cmd_code == READ_FORWARD)
1217 clear_normalized_cda(ccw);
1218 tape_free_request(request);
1219}
1220
1221/*
1222 * check_locate is called just before the tape request is passed to
1223 * the common io layer for execution. It has to check the current
1224 * tape position and insert a locate ccw if it doesn't match the
1225 * start block for the request.
1226 */
1227static void
1228tape_34xx_check_locate(struct tape_device *device, struct tape_request *request)
1229{
1230 struct tape_34xx_block_id * start_block;
1231
1232 start_block = (struct tape_34xx_block_id *) request->cpdata;
1233 if (start_block->block == device->blk_data.block_position)
1234 return;
1235
1236 DBF_LH(4, "Block seek(%06d+%06d)\n", start_block->block, device->bof);
1237 start_block->wrap = 0;
1238 start_block->segment = 1;
1239 start_block->format = (*device->modeset_byte & 0x08) ?
1240 TAPE34XX_FMT_3480_XF :
1241 TAPE34XX_FMT_3480;
1242 start_block->block = start_block->block + device->bof;
1243 tape_34xx_merge_sbid(device, start_block);
1244 tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata);
1245 tape_ccw_cc(request->cpaddr + 2, READ_BLOCK_ID, 8, request->cpdata);
1246}
1247#endif
1248
1117/* 1249/*
1118 * List of 3480/3490 magnetic tape commands. 1250 * List of 3480/3490 magnetic tape commands.
1119 */ 1251 */
@@ -1163,6 +1295,11 @@ static struct tape_discipline tape_discipline_34xx = {
1163 .irq = tape_34xx_irq, 1295 .irq = tape_34xx_irq,
1164 .read_block = tape_std_read_block, 1296 .read_block = tape_std_read_block,
1165 .write_block = tape_std_write_block, 1297 .write_block = tape_std_write_block,
1298#ifdef CONFIG_S390_TAPE_BLOCK
1299 .bread = tape_34xx_bread,
1300 .free_bread = tape_34xx_free_bread,
1301 .check_locate = tape_34xx_check_locate,
1302#endif
1166 .ioctl_fn = tape_34xx_ioctl, 1303 .ioctl_fn = tape_34xx_ioctl,
1167 .mtop_array = tape_34xx_mtop 1304 .mtop_array = tape_34xx_mtop
1168}; 1305};
@@ -1193,7 +1330,6 @@ static struct ccw_driver tape_34xx_driver = {
1193 .set_online = tape_34xx_online, 1330 .set_online = tape_34xx_online,
1194 .set_offline = tape_generic_offline, 1331 .set_offline = tape_generic_offline,
1195 .freeze = tape_generic_pm_suspend, 1332 .freeze = tape_generic_pm_suspend,
1196 .int_class = IRQIO_TAP,
1197}; 1333};
1198 1334
1199static int 1335static int
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 327cb19ad0b..a7d57072888 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * drivers/s390/char/tape_3590.c
2 * tape device discipline for 3590 tapes. 3 * tape device discipline for 3590 tapes.
3 * 4 *
4 * Copyright IBM Corp. 2001, 2009 5 * Copyright IBM Corp. 2001, 2009
@@ -669,6 +670,92 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op)
669 return 0; 670 return 0;
670} 671}
671 672
673#ifdef CONFIG_S390_TAPE_BLOCK
674/*
675 * Tape Block READ
676 */
677static struct tape_request *
678tape_3590_bread(struct tape_device *device, struct request *req)
679{
680 struct tape_request *request;
681 struct ccw1 *ccw;
682 int count = 0, start_block;
683 unsigned off;
684 char *dst;
685 struct bio_vec *bv;
686 struct req_iterator iter;
687
688 DBF_EVENT(6, "xBREDid:");
689 start_block = blk_rq_pos(req) >> TAPEBLOCK_HSEC_S2B;
690 DBF_EVENT(6, "start_block = %i\n", start_block);
691
692 rq_for_each_segment(bv, req, iter)
693 count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9);
694
695 request = tape_alloc_request(2 + count + 1, 4);
696 if (IS_ERR(request))
697 return request;
698 request->op = TO_BLOCK;
699 *(__u32 *) request->cpdata = start_block;
700 ccw = request->cpaddr;
701 ccw = tape_ccw_cc(ccw, MODE_SET_DB, 1, device->modeset_byte);
702
703 /*
704 * We always setup a nop after the mode set ccw. This slot is
705 * used in tape_std_check_locate to insert a locate ccw if the
706 * current tape position doesn't match the start block to be read.
707 */
708 ccw = tape_ccw_cc(ccw, NOP, 0, NULL);
709
710 rq_for_each_segment(bv, req, iter) {
711 dst = page_address(bv->bv_page) + bv->bv_offset;
712 for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) {
713 ccw->flags = CCW_FLAG_CC;
714 ccw->cmd_code = READ_FORWARD;
715 ccw->count = TAPEBLOCK_HSEC_SIZE;
716 set_normalized_cda(ccw, (void *) __pa(dst));
717 ccw++;
718 dst += TAPEBLOCK_HSEC_SIZE;
719 }
720 BUG_ON(off > bv->bv_len);
721 }
722 ccw = tape_ccw_end(ccw, NOP, 0, NULL);
723 DBF_EVENT(6, "xBREDccwg\n");
724 return request;
725}
726
727static void
728tape_3590_free_bread(struct tape_request *request)
729{
730 struct ccw1 *ccw;
731
732 /* Last ccw is a nop and doesn't need clear_normalized_cda */
733 for (ccw = request->cpaddr; ccw->flags & CCW_FLAG_CC; ccw++)
734 if (ccw->cmd_code == READ_FORWARD)
735 clear_normalized_cda(ccw);
736 tape_free_request(request);
737}
738
739/*
740 * check_locate is called just before the tape request is passed to
741 * the common io layer for execution. It has to check the current
742 * tape position and insert a locate ccw if it doesn't match the
743 * start block for the request.
744 */
745static void
746tape_3590_check_locate(struct tape_device *device, struct tape_request *request)
747{
748 __u32 *start_block;
749
750 start_block = (__u32 *) request->cpdata;
751 if (*start_block != device->blk_data.block_position) {
752 /* Add the start offset of the file to get the real block. */
753 *start_block += device->bof;
754 tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata);
755 }
756}
757#endif
758
672static void tape_3590_med_state_set(struct tape_device *device, 759static void tape_3590_med_state_set(struct tape_device *device,
673 struct tape_3590_med_sense *sense) 760 struct tape_3590_med_sense *sense)
674{ 761{
@@ -1336,6 +1423,20 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
1336{ 1423{
1337 struct tape_3590_sense *sense; 1424 struct tape_3590_sense *sense;
1338 1425
1426#ifdef CONFIG_S390_TAPE_BLOCK
1427 if (request->op == TO_BLOCK) {
1428 /*
1429 * Recovery for block device requests. Set the block_position
1430 * to something invalid and retry.
1431 */
1432 device->blk_data.block_position = -1;
1433 if (request->retries-- <= 0)
1434 return tape_3590_erp_failed(device, request, irb, -EIO);
1435 else
1436 return tape_3590_erp_retry(device, request, irb);
1437 }
1438#endif
1439
1339 sense = (struct tape_3590_sense *) irb->ecw; 1440 sense = (struct tape_3590_sense *) irb->ecw;
1340 1441
1341 DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc); 1442 DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc);
@@ -1628,6 +1729,11 @@ static struct tape_discipline tape_discipline_3590 = {
1628 .irq = tape_3590_irq, 1729 .irq = tape_3590_irq,
1629 .read_block = tape_std_read_block, 1730 .read_block = tape_std_read_block,
1630 .write_block = tape_std_write_block, 1731 .write_block = tape_std_write_block,
1732#ifdef CONFIG_S390_TAPE_BLOCK
1733 .bread = tape_3590_bread,
1734 .free_bread = tape_3590_free_bread,
1735 .check_locate = tape_3590_check_locate,
1736#endif
1631 .ioctl_fn = tape_3590_ioctl, 1737 .ioctl_fn = tape_3590_ioctl,
1632 .mtop_array = tape_3590_mtop 1738 .mtop_array = tape_3590_mtop
1633}; 1739};
@@ -1656,7 +1762,6 @@ static struct ccw_driver tape_3590_driver = {
1656 .set_offline = tape_generic_offline, 1762 .set_offline = tape_generic_offline,
1657 .set_online = tape_3590_online, 1763 .set_online = tape_3590_online,
1658 .freeze = tape_generic_pm_suspend, 1764 .freeze = tape_generic_pm_suspend,
1659 .int_class = IRQIO_TAP,
1660}; 1765};
1661 1766
1662/* 1767/*
diff --git a/drivers/s390/char/tape_3590.h b/drivers/s390/char/tape_3590.h
index 36b759e89d2..4534055f137 100644
--- a/drivers/s390/char/tape_3590.h
+++ b/drivers/s390/char/tape_3590.h
@@ -1,7 +1,8 @@
1/* 1/*
2 * drivers/s390/char/tape_3590.h
2 * tape device discipline for 3590 tapes. 3 * tape device discipline for 3590 tapes.
3 * 4 *
4 * Copyright IBM Corp. 2001, 2006 5 * Copyright IBM Corp. 2001,2006
5 * Author(s): Stefan Bader <shbader@de.ibm.com> 6 * Author(s): Stefan Bader <shbader@de.ibm.com>
6 * Michael Holzheu <holzheu@de.ibm.com> 7 * Michael Holzheu <holzheu@de.ibm.com>
7 * Martin Schwidefsky <schwidefsky@de.ibm.com> 8 * Martin Schwidefsky <schwidefsky@de.ibm.com>
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 2d61db3fc62..87cd0ab242d 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -1,8 +1,9 @@
1/* 1/*
2 * drivers/s390/char/tape_char.c
2 * character device frontend for tape device driver 3 * character device frontend for tape device driver
3 * 4 *
4 * S390 and zSeries version 5 * S390 and zSeries version
5 * Copyright IBM Corp. 2001, 2006 6 * Copyright IBM Corp. 2001,2006
6 * Author(s): Carsten Otte <cotte@de.ibm.com> 7 * Author(s): Carsten Otte <cotte@de.ibm.com>
7 * Michael Holzheu <holzheu@de.ibm.com> 8 * Michael Holzheu <holzheu@de.ibm.com>
8 * Tuan Ngo-Anh <ngoanh@de.ibm.com> 9 * Tuan Ngo-Anh <ngoanh@de.ibm.com>
@@ -160,6 +161,11 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
160 if (rc) 161 if (rc)
161 return rc; 162 return rc;
162 163
164#ifdef CONFIG_S390_TAPE_BLOCK
165 /* Changes position. */
166 device->blk_data.medium_changed = 1;
167#endif
168
163 DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size); 169 DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size);
164 /* Let the discipline build the ccw chain. */ 170 /* Let the discipline build the ccw chain. */
165 request = device->discipline->read_block(device, block_size); 171 request = device->discipline->read_block(device, block_size);
@@ -212,6 +218,11 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t
212 if (rc) 218 if (rc)
213 return rc; 219 return rc;
214 220
221#ifdef CONFIG_S390_TAPE_BLOCK
222 /* Changes position. */
223 device->blk_data.medium_changed = 1;
224#endif
225
215 DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size); 226 DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size);
216 DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks); 227 DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks);
217 /* Let the discipline build the ccw chain. */ 228 /* Let the discipline build the ccw chain. */
@@ -368,6 +379,9 @@ __tapechar_ioctl(struct tape_device *device,
368 case MTBSFM: 379 case MTBSFM:
369 case MTFSFM: 380 case MTFSFM:
370 case MTSEEK: 381 case MTSEEK:
382#ifdef CONFIG_S390_TAPE_BLOCK
383 device->blk_data.medium_changed = 1;
384#endif
371 if (device->required_tapemarks) 385 if (device->required_tapemarks)
372 tape_std_terminate_write(device); 386 tape_std_terminate_write(device);
373 default: 387 default:
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 54b3c79203f..55343df61ed 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright IBM Corp. 2004 2 * (C) Copyright IBM Corp. 2004
3 * tape_class.c
3 * 4 *
4 * Tape class device support 5 * Tape class device support
5 * 6 *
@@ -16,7 +17,7 @@
16 17
17MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>"); 18MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>");
18MODULE_DESCRIPTION( 19MODULE_DESCRIPTION(
19 "Copyright IBM Corp. 2004 All Rights Reserved.\n" 20 "(C) Copyright IBM Corp. 2004 All Rights Reserved.\n"
20 "tape_class.c" 21 "tape_class.c"
21); 22);
22MODULE_LICENSE("GPL"); 23MODULE_LICENSE("GPL");
diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
index a332c10d50a..9e32780c317 100644
--- a/drivers/s390/char/tape_class.h
+++ b/drivers/s390/char/tape_class.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright IBM Corp. 2004 All Rights Reserved. 2 * (C) Copyright IBM Corp. 2004 All Rights Reserved.
3 * tape_class.h
3 * 4 *
4 * Tape class device support 5 * Tape class device support
5 * 6 *
@@ -13,6 +14,7 @@
13#include <linux/module.h> 14#include <linux/module.h>
14#include <linux/fs.h> 15#include <linux/fs.h>
15#include <linux/major.h> 16#include <linux/major.h>
17#include <linux/kobj_map.h>
16#include <linux/cdev.h> 18#include <linux/cdev.h>
17 19
18#include <linux/device.h> 20#include <linux/device.h>
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index f3b5123faf0..7978a0adeaf 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * drivers/s390/char/tape_core.c
2 * basic function of the tape device driver 3 * basic function of the tape device driver
3 * 4 *
4 * S390 and zSeries version 5 * S390 and zSeries version
@@ -13,6 +14,7 @@
13#define KMSG_COMPONENT "tape" 14#define KMSG_COMPONENT "tape"
14#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 15#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
15 16
17#include <linux/kernel_stat.h>
16#include <linux/module.h> 18#include <linux/module.h>
17#include <linux/init.h> // for kernel parameters 19#include <linux/init.h> // for kernel parameters
18#include <linux/kmod.h> // for requesting modules 20#include <linux/kmod.h> // for requesting modules
@@ -400,6 +402,9 @@ tape_generic_online(struct tape_device *device,
400 rc = tapechar_setup_device(device); 402 rc = tapechar_setup_device(device);
401 if (rc) 403 if (rc)
402 goto out_minor; 404 goto out_minor;
405 rc = tapeblock_setup_device(device);
406 if (rc)
407 goto out_char;
403 408
404 tape_state_set(device, TS_UNUSED); 409 tape_state_set(device, TS_UNUSED);
405 410
@@ -407,6 +412,8 @@ tape_generic_online(struct tape_device *device,
407 412
408 return 0; 413 return 0;
409 414
415out_char:
416 tapechar_cleanup_device(device);
410out_minor: 417out_minor:
411 tape_remove_minor(device); 418 tape_remove_minor(device);
412out_discipline: 419out_discipline:
@@ -420,6 +427,7 @@ out:
420static void 427static void
421tape_cleanup_device(struct tape_device *device) 428tape_cleanup_device(struct tape_device *device)
422{ 429{
430 tapeblock_cleanup_device(device);
423 tapechar_cleanup_device(device); 431 tapechar_cleanup_device(device);
424 device->discipline->cleanup_device(device); 432 device->discipline->cleanup_device(device);
425 module_put(device->discipline->owner); 433 module_put(device->discipline->owner);
@@ -778,6 +786,10 @@ __tape_start_io(struct tape_device *device, struct tape_request *request)
778{ 786{
779 int rc; 787 int rc;
780 788
789#ifdef CONFIG_S390_TAPE_BLOCK
790 if (request->op == TO_BLOCK)
791 device->discipline->check_locate(device, request);
792#endif
781 rc = ccw_device_start( 793 rc = ccw_device_start(
782 device->cdev, 794 device->cdev,
783 request->cpaddr, 795 request->cpaddr,
@@ -1103,6 +1115,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
1103 struct tape_request *request; 1115 struct tape_request *request;
1104 int rc; 1116 int rc;
1105 1117
1118 kstat_cpu(smp_processor_id()).irqs[IOINT_TAP]++;
1106 device = dev_get_drvdata(&cdev->dev); 1119 device = dev_get_drvdata(&cdev->dev);
1107 if (device == NULL) { 1120 if (device == NULL) {
1108 return; 1121 return;
@@ -1242,7 +1255,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
1242} 1255}
1243 1256
1244/* 1257/*
1245 * Tape device open function used by tape_char frontend. 1258 * Tape device open function used by tape_char & tape_block frontends.
1246 */ 1259 */
1247int 1260int
1248tape_open(struct tape_device *device) 1261tape_open(struct tape_device *device)
@@ -1272,7 +1285,7 @@ tape_open(struct tape_device *device)
1272} 1285}
1273 1286
1274/* 1287/*
1275 * Tape device release function used by tape_char frontend. 1288 * Tape device release function used by tape_char & tape_block frontends.
1276 */ 1289 */
1277int 1290int
1278tape_release(struct tape_device *device) 1291tape_release(struct tape_device *device)
@@ -1333,6 +1346,7 @@ tape_init (void)
1333 DBF_EVENT(3, "tape init\n"); 1346 DBF_EVENT(3, "tape init\n");
1334 tape_proc_init(); 1347 tape_proc_init();
1335 tapechar_init (); 1348 tapechar_init ();
1349 tapeblock_init ();
1336 return 0; 1350 return 0;
1337} 1351}
1338 1352
@@ -1346,6 +1360,7 @@ tape_exit(void)
1346 1360
1347 /* Get rid of the frontends */ 1361 /* Get rid of the frontends */
1348 tapechar_exit(); 1362 tapechar_exit();
1363 tapeblock_exit();
1349 tape_proc_cleanup(); 1364 tape_proc_cleanup();
1350 debug_unregister (TAPE_DBF_AREA); 1365 debug_unregister (TAPE_DBF_AREA);
1351} 1366}
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index 8733b232a11..0ceb37984f7 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -1,8 +1,9 @@
1/* 1/*
2 * drivers/s390/char/tape.c
2 * tape device driver for S/390 and zSeries tapes. 3 * tape device driver for S/390 and zSeries tapes.
3 * 4 *
4 * S390 and zSeries version 5 * S390 and zSeries version
5 * Copyright IBM Corp. 2001 6 * Copyright (C) 2001 IBM Corporation
6 * Author(s): Carsten Otte <cotte@de.ibm.com> 7 * Author(s): Carsten Otte <cotte@de.ibm.com>
7 * Michael Holzheu <holzheu@de.ibm.com> 8 * Michael Holzheu <holzheu@de.ibm.com>
8 * Tuan Ngo-Anh <ngoanh@de.ibm.com> 9 * Tuan Ngo-Anh <ngoanh@de.ibm.com>
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c
index 981a99fd8d4..e7650170274 100644
--- a/drivers/s390/char/tape_std.c
+++ b/drivers/s390/char/tape_std.c
@@ -1,8 +1,9 @@
1/* 1/*
2 * drivers/s390/char/tape_std.c
2 * standard tape device functions for ibm tapes. 3 * standard tape device functions for ibm tapes.
3 * 4 *
4 * S390 and zSeries version 5 * S390 and zSeries version
5 * Copyright IBM Corp. 2001, 2002 6 * Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Carsten Otte <cotte@de.ibm.com> 7 * Author(s): Carsten Otte <cotte@de.ibm.com>
7 * Michael Holzheu <holzheu@de.ibm.com> 8 * Michael Holzheu <holzheu@de.ibm.com>
8 * Tuan Ngo-Anh <ngoanh@de.ibm.com> 9 * Tuan Ngo-Anh <ngoanh@de.ibm.com>
diff --git a/drivers/s390/char/tape_std.h b/drivers/s390/char/tape_std.h
index 8c760c03683..1fc95235934 100644
--- a/drivers/s390/char/tape_std.h
+++ b/drivers/s390/char/tape_std.h
@@ -1,7 +1,8 @@
1/* 1/*
2 * drivers/s390/char/tape_std.h
2 * standard tape device functions for ibm tapes. 3 * standard tape device functions for ibm tapes.
3 * 4 *
4 * Copyright IBM Corp. 2001, 2006 5 * Copyright (C) IBM Corp. 2001,2006
5 * Author(s): Carsten Otte <cotte@de.ibm.com> 6 * Author(s): Carsten Otte <cotte@de.ibm.com>
6 * Tuan Ngo-Anh <ngoanh@de.ibm.com> 7 * Tuan Ngo-Anh <ngoanh@de.ibm.com>
7 * Martin Schwidefsky <schwidefsky@de.ibm.com> 8 * Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -100,7 +101,11 @@ struct tape_request *tape_std_read_block(struct tape_device *, size_t);
100void tape_std_read_backward(struct tape_device *device, 101void tape_std_read_backward(struct tape_device *device,
101 struct tape_request *request); 102 struct tape_request *request);
102struct tape_request *tape_std_write_block(struct tape_device *, size_t); 103struct tape_request *tape_std_write_block(struct tape_device *, size_t);
104struct tape_request *tape_std_bread(struct tape_device *, struct request *);
105void tape_std_free_bread(struct tape_request *);
103void tape_std_check_locate(struct tape_device *, struct tape_request *); 106void tape_std_check_locate(struct tape_device *, struct tape_request *);
107struct tape_request *tape_std_bwrite(struct request *,
108 struct tape_device *, int);
104 109
105/* Some non-mtop commands. */ 110/* Some non-mtop commands. */
106int tape_std_assign(struct tape_device *); 111int tape_std_assign(struct tape_device *);
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 43ea0593bdb..2db1482b406 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -1,10 +1,11 @@
1/* 1/*
2 * drivers/s390/char/tty3270.c
2 * IBM/3270 Driver - tty functions. 3 * IBM/3270 Driver - tty functions.
3 * 4 *
4 * Author(s): 5 * Author(s):
5 * Original 3270 Code for 2.4 written by Richard Hitt (UTS Global) 6 * Original 3270 Code for 2.4 written by Richard Hitt (UTS Global)
6 * Rewritten for 2.5 by Martin Schwidefsky <schwidefsky@de.ibm.com> 7 * Rewritten for 2.5 by Martin Schwidefsky <schwidefsky@de.ibm.com>
7 * -- Copyright IBM Corp. 2003 8 * -- Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
8 */ 9 */
9 10
10#include <linux/module.h> 11#include <linux/module.h>
@@ -60,7 +61,7 @@ struct tty3270_line {
60 */ 61 */
61struct tty3270 { 62struct tty3270 {
62 struct raw3270_view view; 63 struct raw3270_view view;
63 struct tty_port port; 64 struct tty_struct *tty; /* Pointer to tty structure */
64 void **freemem_pages; /* Array of pages used for freemem. */ 65 void **freemem_pages; /* Array of pages used for freemem. */
65 struct list_head freemem; /* List of free memory for strings. */ 66 struct list_head freemem; /* List of free memory for strings. */
66 67
@@ -323,8 +324,9 @@ tty3270_blank_line(struct tty3270 *tp)
323static void 324static void
324tty3270_write_callback(struct raw3270_request *rq, void *data) 325tty3270_write_callback(struct raw3270_request *rq, void *data)
325{ 326{
326 struct tty3270 *tp = container_of(rq->view, struct tty3270, view); 327 struct tty3270 *tp;
327 328
329 tp = (struct tty3270 *) rq->view;
328 if (rq->rc != 0) { 330 if (rq->rc != 0) {
329 /* Write wasn't successful. Refresh all. */ 331 /* Write wasn't successful. Refresh all. */
330 tp->update_flags = TTY_UPDATE_ALL; 332 tp->update_flags = TTY_UPDATE_ALL;
@@ -448,9 +450,10 @@ tty3270_rcl_add(struct tty3270 *tp, char *input, int len)
448static void 450static void
449tty3270_rcl_backward(struct kbd_data *kbd) 451tty3270_rcl_backward(struct kbd_data *kbd)
450{ 452{
451 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port); 453 struct tty3270 *tp;
452 struct string *s; 454 struct string *s;
453 455
456 tp = kbd->tty->driver_data;
454 spin_lock_bh(&tp->view.lock); 457 spin_lock_bh(&tp->view.lock);
455 if (tp->inattr == TF_INPUT) { 458 if (tp->inattr == TF_INPUT) {
456 if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines) 459 if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines)
@@ -475,8 +478,9 @@ tty3270_rcl_backward(struct kbd_data *kbd)
475static void 478static void
476tty3270_exit_tty(struct kbd_data *kbd) 479tty3270_exit_tty(struct kbd_data *kbd)
477{ 480{
478 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port); 481 struct tty3270 *tp;
479 482
483 tp = kbd->tty->driver_data;
480 raw3270_deactivate_view(&tp->view); 484 raw3270_deactivate_view(&tp->view);
481} 485}
482 486
@@ -486,9 +490,10 @@ tty3270_exit_tty(struct kbd_data *kbd)
486static void 490static void
487tty3270_scroll_forward(struct kbd_data *kbd) 491tty3270_scroll_forward(struct kbd_data *kbd)
488{ 492{
489 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port); 493 struct tty3270 *tp;
490 int nr_up; 494 int nr_up;
491 495
496 tp = kbd->tty->driver_data;
492 spin_lock_bh(&tp->view.lock); 497 spin_lock_bh(&tp->view.lock);
493 nr_up = tp->nr_up - tp->view.rows + 2; 498 nr_up = tp->nr_up - tp->view.rows + 2;
494 if (nr_up < 0) 499 if (nr_up < 0)
@@ -508,9 +513,10 @@ tty3270_scroll_forward(struct kbd_data *kbd)
508static void 513static void
509tty3270_scroll_backward(struct kbd_data *kbd) 514tty3270_scroll_backward(struct kbd_data *kbd)
510{ 515{
511 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port); 516 struct tty3270 *tp;
512 int nr_up; 517 int nr_up;
513 518
519 tp = kbd->tty->driver_data;
514 spin_lock_bh(&tp->view.lock); 520 spin_lock_bh(&tp->view.lock);
515 nr_up = tp->nr_up + tp->view.rows - 2; 521 nr_up = tp->nr_up + tp->view.rows - 2;
516 if (nr_up + tp->view.rows - 2 > tp->nr_lines) 522 if (nr_up + tp->view.rows - 2 > tp->nr_lines)
@@ -531,10 +537,11 @@ static void
531tty3270_read_tasklet(struct raw3270_request *rrq) 537tty3270_read_tasklet(struct raw3270_request *rrq)
532{ 538{
533 static char kreset_data = TW_KR; 539 static char kreset_data = TW_KR;
534 struct tty3270 *tp = container_of(rrq->view, struct tty3270, view); 540 struct tty3270 *tp;
535 char *input; 541 char *input;
536 int len; 542 int len;
537 543
544 tp = (struct tty3270 *) rrq->view;
538 spin_lock_bh(&tp->view.lock); 545 spin_lock_bh(&tp->view.lock);
539 /* 546 /*
540 * Two AID keys are special: For 0x7d (enter) the input line 547 * Two AID keys are special: For 0x7d (enter) the input line
@@ -570,10 +577,13 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
570 raw3270_request_add_data(tp->kreset, &kreset_data, 1); 577 raw3270_request_add_data(tp->kreset, &kreset_data, 1);
571 raw3270_start(&tp->view, tp->kreset); 578 raw3270_start(&tp->view, tp->kreset);
572 579
573 while (len-- > 0) 580 /* Emit input string. */
574 kbd_keycode(tp->kbd, *input++); 581 if (tp->tty) {
575 /* Emit keycode for AID byte. */ 582 while (len-- > 0)
576 kbd_keycode(tp->kbd, 256 + tp->input->string[0]); 583 kbd_keycode(tp->kbd, *input++);
584 /* Emit keycode for AID byte. */
585 kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
586 }
577 587
578 raw3270_request_reset(rrq); 588 raw3270_request_reset(rrq);
579 xchg(&tp->read, rrq); 589 xchg(&tp->read, rrq);
@@ -586,10 +596,9 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
586static void 596static void
587tty3270_read_callback(struct raw3270_request *rq, void *data) 597tty3270_read_callback(struct raw3270_request *rq, void *data)
588{ 598{
589 struct tty3270 *tp = container_of(rq->view, struct tty3270, view);
590 raw3270_get_view(rq->view); 599 raw3270_get_view(rq->view);
591 /* Schedule tasklet to pass input to tty. */ 600 /* Schedule tasklet to pass input to tty. */
592 tasklet_schedule(&tp->readlet); 601 tasklet_schedule(&((struct tty3270 *) rq->view)->readlet);
593} 602}
594 603
595/* 604/*
@@ -626,8 +635,9 @@ tty3270_issue_read(struct tty3270 *tp, int lock)
626static int 635static int
627tty3270_activate(struct raw3270_view *view) 636tty3270_activate(struct raw3270_view *view)
628{ 637{
629 struct tty3270 *tp = container_of(view, struct tty3270, view); 638 struct tty3270 *tp;
630 639
640 tp = (struct tty3270 *) view;
631 tp->update_flags = TTY_UPDATE_ALL; 641 tp->update_flags = TTY_UPDATE_ALL;
632 tty3270_set_timer(tp, 1); 642 tty3270_set_timer(tp, 1);
633 return 0; 643 return 0;
@@ -636,8 +646,9 @@ tty3270_activate(struct raw3270_view *view)
636static void 646static void
637tty3270_deactivate(struct raw3270_view *view) 647tty3270_deactivate(struct raw3270_view *view)
638{ 648{
639 struct tty3270 *tp = container_of(view, struct tty3270, view); 649 struct tty3270 *tp;
640 650
651 tp = (struct tty3270 *) view;
641 del_timer(&tp->timer); 652 del_timer(&tp->timer);
642} 653}
643 654
@@ -679,17 +690,6 @@ tty3270_alloc_view(void)
679 if (!tp->freemem_pages) 690 if (!tp->freemem_pages)
680 goto out_tp; 691 goto out_tp;
681 INIT_LIST_HEAD(&tp->freemem); 692 INIT_LIST_HEAD(&tp->freemem);
682 INIT_LIST_HEAD(&tp->lines);
683 INIT_LIST_HEAD(&tp->update);
684 INIT_LIST_HEAD(&tp->rcl_lines);
685 tp->rcl_max = 20;
686 tty_port_init(&tp->port);
687 setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
688 (unsigned long) tp);
689 tasklet_init(&tp->readlet,
690 (void (*)(unsigned long)) tty3270_read_tasklet,
691 (unsigned long) tp->read);
692
693 for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) { 693 for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) {
694 tp->freemem_pages[pages] = (void *) 694 tp->freemem_pages[pages] = (void *)
695 __get_free_pages(GFP_KERNEL|GFP_DMA, 0); 695 __get_free_pages(GFP_KERNEL|GFP_DMA, 0);
@@ -722,7 +722,6 @@ out_pages:
722 while (pages--) 722 while (pages--)
723 free_pages((unsigned long) tp->freemem_pages[pages], 0); 723 free_pages((unsigned long) tp->freemem_pages[pages], 0);
724 kfree(tp->freemem_pages); 724 kfree(tp->freemem_pages);
725 tty_port_destroy(&tp->port);
726out_tp: 725out_tp:
727 kfree(tp); 726 kfree(tp);
728out_err: 727out_err:
@@ -745,7 +744,6 @@ tty3270_free_view(struct tty3270 *tp)
745 for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) 744 for (pages = 0; pages < TTY3270_STRING_PAGES; pages++)
746 free_pages((unsigned long) tp->freemem_pages[pages], 0); 745 free_pages((unsigned long) tp->freemem_pages[pages], 0);
747 kfree(tp->freemem_pages); 746 kfree(tp->freemem_pages);
748 tty_port_destroy(&tp->port);
749 kfree(tp); 747 kfree(tp);
750} 748}
751 749
@@ -796,15 +794,16 @@ tty3270_free_screen(struct tty3270 *tp)
796static void 794static void
797tty3270_release(struct raw3270_view *view) 795tty3270_release(struct raw3270_view *view)
798{ 796{
799 struct tty3270 *tp = container_of(view, struct tty3270, view); 797 struct tty3270 *tp;
800 struct tty_struct *tty = tty_port_tty_get(&tp->port); 798 struct tty_struct *tty;
801 799
800 tp = (struct tty3270 *) view;
801 tty = tp->tty;
802 if (tty) { 802 if (tty) {
803 tty->driver_data = NULL; 803 tty->driver_data = NULL;
804 tty_port_tty_set(&tp->port, NULL); 804 tp->tty = tp->kbd->tty = NULL;
805 tty_hangup(tty); 805 tty_hangup(tty);
806 raw3270_put_view(&tp->view); 806 raw3270_put_view(&tp->view);
807 tty_kref_put(tty);
808 } 807 }
809} 808}
810 809
@@ -814,9 +813,8 @@ tty3270_release(struct raw3270_view *view)
814static void 813static void
815tty3270_free(struct raw3270_view *view) 814tty3270_free(struct raw3270_view *view)
816{ 815{
817 struct tty3270 *tp = container_of(view, struct tty3270, view); 816 tty3270_free_screen((struct tty3270 *) view);
818 tty3270_free_screen(tp); 817 tty3270_free_view((struct tty3270 *) view);
819 tty3270_free_view(tp);
820} 818}
821 819
822/* 820/*
@@ -825,13 +823,14 @@ tty3270_free(struct raw3270_view *view)
825static void 823static void
826tty3270_del_views(void) 824tty3270_del_views(void)
827{ 825{
826 struct tty3270 *tp;
828 int i; 827 int i;
829 828
830 for (i = 0; i < tty3270_max_index; i++) { 829 for (i = 0; i < tty3270_max_index; i++) {
831 struct raw3270_view *view = 830 tp = (struct tty3270 *)
832 raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR); 831 raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR);
833 if (!IS_ERR(view)) 832 if (!IS_ERR(tp))
834 raw3270_del_view(view); 833 raw3270_del_view(&tp->view);
835 } 834 }
836} 835}
837 836
@@ -844,33 +843,35 @@ static struct raw3270_fn tty3270_fn = {
844}; 843};
845 844
846/* 845/*
847 * This routine is called whenever a 3270 tty is opened first time. 846 * This routine is called whenever a 3270 tty is opened.
848 */ 847 */
849static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty) 848static int
849tty3270_open(struct tty_struct *tty, struct file * filp)
850{ 850{
851 struct raw3270_view *view;
852 struct tty3270 *tp; 851 struct tty3270 *tp;
853 int i, rc; 852 int i, rc;
854 853
854 if (tty->count > 1)
855 return 0;
855 /* Check if the tty3270 is already there. */ 856 /* Check if the tty3270 is already there. */
856 view = raw3270_find_view(&tty3270_fn, 857 tp = (struct tty3270 *)
858 raw3270_find_view(&tty3270_fn,
857 tty->index + RAW3270_FIRSTMINOR); 859 tty->index + RAW3270_FIRSTMINOR);
858 if (!IS_ERR(view)) { 860 if (!IS_ERR(tp)) {
859 tp = container_of(view, struct tty3270, view);
860 tty->driver_data = tp; 861 tty->driver_data = tp;
861 tty->winsize.ws_row = tp->view.rows - 2; 862 tty->winsize.ws_row = tp->view.rows - 2;
862 tty->winsize.ws_col = tp->view.cols; 863 tty->winsize.ws_col = tp->view.cols;
863 tty->low_latency = 0; 864 tty->low_latency = 0;
864 /* why to reassign? */ 865 tp->tty = tty;
865 tty_port_tty_set(&tp->port, tty); 866 tp->kbd->tty = tty;
866 tp->inattr = TF_INPUT; 867 tp->inattr = TF_INPUT;
867 return tty_port_install(&tp->port, driver, tty); 868 return 0;
868 } 869 }
869 if (tty3270_max_index < tty->index + 1) 870 if (tty3270_max_index < tty->index + 1)
870 tty3270_max_index = tty->index + 1; 871 tty3270_max_index = tty->index + 1;
871 872
872 /* Quick exit if there is no device for tty->index. */ 873 /* Quick exit if there is no device for tty->index. */
873 if (PTR_ERR(view) == -ENODEV) 874 if (PTR_ERR(tp) == -ENODEV)
874 return -ENODEV; 875 return -ENODEV;
875 876
876 /* Allocate tty3270 structure on first open. */ 877 /* Allocate tty3270 structure on first open. */
@@ -878,6 +879,16 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
878 if (IS_ERR(tp)) 879 if (IS_ERR(tp))
879 return PTR_ERR(tp); 880 return PTR_ERR(tp);
880 881
882 INIT_LIST_HEAD(&tp->lines);
883 INIT_LIST_HEAD(&tp->update);
884 INIT_LIST_HEAD(&tp->rcl_lines);
885 tp->rcl_max = 20;
886 setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
887 (unsigned long) tp);
888 tasklet_init(&tp->readlet,
889 (void (*)(unsigned long)) tty3270_read_tasklet,
890 (unsigned long) tp->read);
891
881 rc = raw3270_add_view(&tp->view, &tty3270_fn, 892 rc = raw3270_add_view(&tp->view, &tty3270_fn,
882 tty->index + RAW3270_FIRSTMINOR); 893 tty->index + RAW3270_FIRSTMINOR);
883 if (rc) { 894 if (rc) {
@@ -892,8 +903,9 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
892 return rc; 903 return rc;
893 } 904 }
894 905
895 tty_port_tty_set(&tp->port, tty); 906 tp->tty = tty;
896 tty->low_latency = 0; 907 tty->low_latency = 0;
908 tty->driver_data = tp;
897 tty->winsize.ws_row = tp->view.rows - 2; 909 tty->winsize.ws_row = tp->view.rows - 2;
898 tty->winsize.ws_col = tp->view.cols; 910 tty->winsize.ws_col = tp->view.cols;
899 911
@@ -905,7 +917,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
905 for (i = 0; i < tp->view.rows - 2; i++) 917 for (i = 0; i < tp->view.rows - 2; i++)
906 tty3270_blank_line(tp); 918 tty3270_blank_line(tp);
907 919
908 tp->kbd->port = &tp->port; 920 tp->kbd->tty = tty;
909 tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty; 921 tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty;
910 tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward; 922 tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward;
911 tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward; 923 tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward;
@@ -913,15 +925,6 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
913 kbd_ascebc(tp->kbd, tp->view.ascebc); 925 kbd_ascebc(tp->kbd, tp->view.ascebc);
914 926
915 raw3270_activate_view(&tp->view); 927 raw3270_activate_view(&tp->view);
916
917 rc = tty_port_install(&tp->port, driver, tty);
918 if (rc) {
919 raw3270_put_view(&tp->view);
920 return rc;
921 }
922
923 tty->driver_data = tp;
924
925 return 0; 928 return 0;
926} 929}
927 930
@@ -932,22 +935,16 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
932static void 935static void
933tty3270_close(struct tty_struct *tty, struct file * filp) 936tty3270_close(struct tty_struct *tty, struct file * filp)
934{ 937{
935 struct tty3270 *tp = tty->driver_data; 938 struct tty3270 *tp;
936 939
937 if (tty->count > 1) 940 if (tty->count > 1)
938 return; 941 return;
942 tp = (struct tty3270 *) tty->driver_data;
939 if (tp) { 943 if (tp) {
940 tty->driver_data = NULL; 944 tty->driver_data = NULL;
941 tty_port_tty_set(&tp->port, NULL); 945 tp->tty = tp->kbd->tty = NULL;
942 }
943}
944
945static void tty3270_cleanup(struct tty_struct *tty)
946{
947 struct tty3270 *tp = tty->driver_data;
948
949 if (tp)
950 raw3270_put_view(&tp->view); 946 raw3270_put_view(&tp->view);
947 }
951} 948}
952 949
953/* 950/*
@@ -1394,7 +1391,7 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
1394 tty3270_lf(tp); 1391 tty3270_lf(tp);
1395 break; 1392 break;
1396 case 'Z': /* Respond ID. */ 1393 case 'Z': /* Respond ID. */
1397 kbd_puts_queue(&tp->port, "\033[?6c"); 1394 kbd_puts_queue(tp->tty, "\033[?6c");
1398 break; 1395 break;
1399 case '7': /* Save cursor position. */ 1396 case '7': /* Save cursor position. */
1400 tp->saved_cx = tp->cx; 1397 tp->saved_cx = tp->cx;
@@ -1440,11 +1437,11 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
1440 tp->esc_state = ESnormal; 1437 tp->esc_state = ESnormal;
1441 if (ch == 'n' && !tp->esc_ques) { 1438 if (ch == 'n' && !tp->esc_ques) {
1442 if (tp->esc_par[0] == 5) /* Status report. */ 1439 if (tp->esc_par[0] == 5) /* Status report. */
1443 kbd_puts_queue(&tp->port, "\033[0n"); 1440 kbd_puts_queue(tp->tty, "\033[0n");
1444 else if (tp->esc_par[0] == 6) { /* Cursor report. */ 1441 else if (tp->esc_par[0] == 6) { /* Cursor report. */
1445 char buf[40]; 1442 char buf[40];
1446 sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1); 1443 sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1);
1447 kbd_puts_queue(&tp->port, buf); 1444 kbd_puts_queue(tp->tty, buf);
1448 } 1445 }
1449 return; 1446 return;
1450 } 1447 }
@@ -1516,13 +1513,12 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
1516 * String write routine for 3270 ttys 1513 * String write routine for 3270 ttys
1517 */ 1514 */
1518static void 1515static void
1519tty3270_do_write(struct tty3270 *tp, struct tty_struct *tty, 1516tty3270_do_write(struct tty3270 *tp, const unsigned char *buf, int count)
1520 const unsigned char *buf, int count)
1521{ 1517{
1522 int i_msg, i; 1518 int i_msg, i;
1523 1519
1524 spin_lock_bh(&tp->view.lock); 1520 spin_lock_bh(&tp->view.lock);
1525 for (i_msg = 0; !tty->stopped && i_msg < count; i_msg++) { 1521 for (i_msg = 0; !tp->tty->stopped && i_msg < count; i_msg++) {
1526 if (tp->esc_state != 0) { 1522 if (tp->esc_state != 0) {
1527 /* Continue escape sequence. */ 1523 /* Continue escape sequence. */
1528 tty3270_escape_sequence(tp, buf[i_msg]); 1524 tty3270_escape_sequence(tp, buf[i_msg]);
@@ -1599,10 +1595,10 @@ tty3270_write(struct tty_struct * tty,
1599 if (!tp) 1595 if (!tp)
1600 return 0; 1596 return 0;
1601 if (tp->char_count > 0) { 1597 if (tp->char_count > 0) {
1602 tty3270_do_write(tp, tty, tp->char_buf, tp->char_count); 1598 tty3270_do_write(tp, tp->char_buf, tp->char_count);
1603 tp->char_count = 0; 1599 tp->char_count = 0;
1604 } 1600 }
1605 tty3270_do_write(tp, tty, buf, count); 1601 tty3270_do_write(tp, buf, count);
1606 return count; 1602 return count;
1607} 1603}
1608 1604
@@ -1633,7 +1629,7 @@ tty3270_flush_chars(struct tty_struct *tty)
1633 if (!tp) 1629 if (!tp)
1634 return; 1630 return;
1635 if (tp->char_count > 0) { 1631 if (tp->char_count > 0) {
1636 tty3270_do_write(tp, tty, tp->char_buf, tp->char_count); 1632 tty3270_do_write(tp, tp->char_buf, tp->char_count);
1637 tp->char_count = 0; 1633 tp->char_count = 0;
1638 } 1634 }
1639} 1635}
@@ -1751,8 +1747,7 @@ static long tty3270_compat_ioctl(struct tty_struct *tty,
1751#endif 1747#endif
1752 1748
1753static const struct tty_operations tty3270_ops = { 1749static const struct tty_operations tty3270_ops = {
1754 .install = tty3270_install, 1750 .open = tty3270_open,
1755 .cleanup = tty3270_cleanup,
1756 .close = tty3270_close, 1751 .close = tty3270_close,
1757 .write = tty3270_write, 1752 .write = tty3270_write,
1758 .put_char = tty3270_put_char, 1753 .put_char = tty3270_put_char,
@@ -1789,6 +1784,7 @@ static int __init tty3270_init(void)
1789 * Entries in tty3270_driver that are NOT initialized: 1784 * Entries in tty3270_driver that are NOT initialized:
1790 * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc 1785 * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc
1791 */ 1786 */
1787 driver->owner = THIS_MODULE;
1792 driver->driver_name = "ttyTUB"; 1788 driver->driver_name = "ttyTUB";
1793 driver->name = "ttyTUB"; 1789 driver->name = "ttyTUB";
1794 driver->major = IBM_TTY3270_MAJOR; 1790 driver->major = IBM_TTY3270_MAJOR;
@@ -1796,7 +1792,7 @@ static int __init tty3270_init(void)
1796 driver->type = TTY_DRIVER_TYPE_SYSTEM; 1792 driver->type = TTY_DRIVER_TYPE_SYSTEM;
1797 driver->subtype = SYSTEM_TYPE_TTY; 1793 driver->subtype = SYSTEM_TYPE_TTY;
1798 driver->init_termios = tty_std_termios; 1794 driver->init_termios = tty_std_termios;
1799 driver->flags = TTY_DRIVER_RESET_TERMIOS; 1795 driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_DYNAMIC_DEV;
1800 tty_set_operations(driver, &tty3270_ops); 1796 tty_set_operations(driver, &tty3270_ops);
1801 ret = tty_register_driver(driver); 1797 ret = tty_register_driver(driver);
1802 if (ret) { 1798 if (ret) {
@@ -1815,7 +1811,6 @@ tty3270_exit(void)
1815 driver = tty3270_driver; 1811 driver = tty3270_driver;
1816 tty3270_driver = NULL; 1812 tty3270_driver = NULL;
1817 tty_unregister_driver(driver); 1813 tty_unregister_driver(driver);
1818 put_tty_driver(driver);
1819 tty3270_del_views(); 1814 tty3270_del_views();
1820} 1815}
1821 1816
diff --git a/drivers/s390/char/tty3270.h b/drivers/s390/char/tty3270.h
index 11141a8f897..799da57f039 100644
--- a/drivers/s390/char/tty3270.h
+++ b/drivers/s390/char/tty3270.h
@@ -1,4 +1,6 @@
1/* 1/*
2 * drivers/s390/char/tty3270.h
3 *
2 * Copyright IBM Corp. 2007 4 * Copyright IBM Corp. 2007
3 * 5 *
4 */ 6 */
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 0fdedadff7b..31a3ccbb649 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright IBM Corp. 2004, 2010 2 * Copyright IBM Corp. 2004,2010
3 * Interface implementation for communication with the z/VM control program 3 * Interface implementation for communication with the z/VM control program
4 * 4 *
5 * Author(s): Christian Borntraeger <borntraeger@de.ibm.com> 5 * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
@@ -13,11 +13,9 @@
13 13
14#include <linux/fs.h> 14#include <linux/fs.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/compat.h>
17#include <linux/kernel.h> 16#include <linux/kernel.h>
18#include <linux/miscdevice.h> 17#include <linux/miscdevice.h>
19#include <linux/slab.h> 18#include <linux/slab.h>
20#include <linux/export.h>
21#include <asm/compat.h> 19#include <asm/compat.h>
22#include <asm/cpcmd.h> 20#include <asm/cpcmd.h>
23#include <asm/debug.h> 21#include <asm/debug.h>
diff --git a/drivers/s390/char/vmcp.h b/drivers/s390/char/vmcp.h
index 1e29b041838..6a993948e18 100644
--- a/drivers/s390/char/vmcp.h
+++ b/drivers/s390/char/vmcp.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright IBM Corp. 2004, 2005 2 * Copyright (C) 2004, 2005 IBM Corporation
3 * Interface implementation for communication with the z/VM control program 3 * Interface implementation for communication with the z/VM control program
4 * Version 1.0 4 * Version 1.0
5 * Author(s): Christian Borntraeger <cborntra@de.ibm.com> 5 * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 9b3a24e8d3a..524d988d89d 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * drivers/s390/char/vmlogrdr.c
2 * character device driver for reading z/VM system service records 3 * character device driver for reading z/VM system service records
3 * 4 *
4 * 5 *
@@ -321,7 +322,7 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp)
321 * only allow for blocking reads to be open 322 * only allow for blocking reads to be open
322 */ 323 */
323 if (filp->f_flags & O_NONBLOCK) 324 if (filp->f_flags & O_NONBLOCK)
324 return -EOPNOTSUPP; 325 return -ENOSYS;
325 326
326 /* Besure this device hasn't already been opened */ 327 /* Besure this device hasn't already been opened */
327 spin_lock_bh(&logptr->priv_lock); 328 spin_lock_bh(&logptr->priv_lock);
@@ -655,19 +656,10 @@ static ssize_t vmlogrdr_recording_status_show(struct device_driver *driver,
655 len = strlen(buf); 656 len = strlen(buf);
656 return len; 657 return len;
657} 658}
659
660
658static DRIVER_ATTR(recording_status, 0444, vmlogrdr_recording_status_show, 661static DRIVER_ATTR(recording_status, 0444, vmlogrdr_recording_status_show,
659 NULL); 662 NULL);
660static struct attribute *vmlogrdr_drv_attrs[] = {
661 &driver_attr_recording_status.attr,
662 NULL,
663};
664static struct attribute_group vmlogrdr_drv_attr_group = {
665 .attrs = vmlogrdr_drv_attrs,
666};
667static const struct attribute_group *vmlogrdr_drv_attr_groups[] = {
668 &vmlogrdr_drv_attr_group,
669 NULL,
670};
671 663
672static struct attribute *vmlogrdr_attrs[] = { 664static struct attribute *vmlogrdr_attrs[] = {
673 &dev_attr_autopurge.attr, 665 &dev_attr_autopurge.attr,
@@ -676,13 +668,6 @@ static struct attribute *vmlogrdr_attrs[] = {
676 &dev_attr_recording.attr, 668 &dev_attr_recording.attr,
677 NULL, 669 NULL,
678}; 670};
679static struct attribute_group vmlogrdr_attr_group = {
680 .attrs = vmlogrdr_attrs,
681};
682static const struct attribute_group *vmlogrdr_attr_groups[] = {
683 &vmlogrdr_attr_group,
684 NULL,
685};
686 671
687static int vmlogrdr_pm_prepare(struct device *dev) 672static int vmlogrdr_pm_prepare(struct device *dev)
688{ 673{
@@ -707,14 +692,18 @@ static const struct dev_pm_ops vmlogrdr_pm_ops = {
707 .prepare = vmlogrdr_pm_prepare, 692 .prepare = vmlogrdr_pm_prepare,
708}; 693};
709 694
695static struct attribute_group vmlogrdr_attr_group = {
696 .attrs = vmlogrdr_attrs,
697};
698
710static struct class *vmlogrdr_class; 699static struct class *vmlogrdr_class;
711static struct device_driver vmlogrdr_driver = { 700static struct device_driver vmlogrdr_driver = {
712 .name = "vmlogrdr", 701 .name = "vmlogrdr",
713 .bus = &iucv_bus, 702 .bus = &iucv_bus,
714 .pm = &vmlogrdr_pm_ops, 703 .pm = &vmlogrdr_pm_ops,
715 .groups = vmlogrdr_drv_attr_groups,
716}; 704};
717 705
706
718static int vmlogrdr_register_driver(void) 707static int vmlogrdr_register_driver(void)
719{ 708{
720 int ret; 709 int ret;
@@ -728,14 +717,21 @@ static int vmlogrdr_register_driver(void)
728 if (ret) 717 if (ret)
729 goto out_iucv; 718 goto out_iucv;
730 719
720 ret = driver_create_file(&vmlogrdr_driver,
721 &driver_attr_recording_status);
722 if (ret)
723 goto out_driver;
724
731 vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr"); 725 vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
732 if (IS_ERR(vmlogrdr_class)) { 726 if (IS_ERR(vmlogrdr_class)) {
733 ret = PTR_ERR(vmlogrdr_class); 727 ret = PTR_ERR(vmlogrdr_class);
734 vmlogrdr_class = NULL; 728 vmlogrdr_class = NULL;
735 goto out_driver; 729 goto out_attr;
736 } 730 }
737 return 0; 731 return 0;
738 732
733out_attr:
734 driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
739out_driver: 735out_driver:
740 driver_unregister(&vmlogrdr_driver); 736 driver_unregister(&vmlogrdr_driver);
741out_iucv: 737out_iucv:
@@ -749,6 +745,7 @@ static void vmlogrdr_unregister_driver(void)
749{ 745{
750 class_destroy(vmlogrdr_class); 746 class_destroy(vmlogrdr_class);
751 vmlogrdr_class = NULL; 747 vmlogrdr_class = NULL;
748 driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
752 driver_unregister(&vmlogrdr_driver); 749 driver_unregister(&vmlogrdr_driver);
753 iucv_unregister(&vmlogrdr_iucv_handler, 1); 750 iucv_unregister(&vmlogrdr_iucv_handler, 1);
754} 751}
@@ -765,7 +762,6 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
765 dev->bus = &iucv_bus; 762 dev->bus = &iucv_bus;
766 dev->parent = iucv_root; 763 dev->parent = iucv_root;
767 dev->driver = &vmlogrdr_driver; 764 dev->driver = &vmlogrdr_driver;
768 dev->groups = vmlogrdr_attr_groups;
769 dev_set_drvdata(dev, priv); 765 dev_set_drvdata(dev, priv);
770 /* 766 /*
771 * The release function could be called after the 767 * The release function could be called after the
@@ -783,6 +779,11 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
783 return ret; 779 return ret;
784 } 780 }
785 781
782 ret = sysfs_create_group(&dev->kobj, &vmlogrdr_attr_group);
783 if (ret) {
784 device_unregister(dev);
785 return ret;
786 }
786 priv->class_device = device_create(vmlogrdr_class, dev, 787 priv->class_device = device_create(vmlogrdr_class, dev,
787 MKDEV(vmlogrdr_major, 788 MKDEV(vmlogrdr_major,
788 priv->minor_num), 789 priv->minor_num),
@@ -790,6 +791,7 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
790 if (IS_ERR(priv->class_device)) { 791 if (IS_ERR(priv->class_device)) {
791 ret = PTR_ERR(priv->class_device); 792 ret = PTR_ERR(priv->class_device);
792 priv->class_device=NULL; 793 priv->class_device=NULL;
794 sysfs_remove_group(&dev->kobj, &vmlogrdr_attr_group);
793 device_unregister(dev); 795 device_unregister(dev);
794 return ret; 796 return ret;
795 } 797 }
@@ -802,6 +804,7 @@ static int vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv)
802{ 804{
803 device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num)); 805 device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
804 if (priv->device != NULL) { 806 if (priv->device != NULL) {
807 sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
805 device_unregister(priv->device); 808 device_unregister(priv->device);
806 priv->device=NULL; 809 priv->device=NULL;
807 } 810 }
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 483f72ba030..f6b00c3df42 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -11,9 +11,9 @@
11#define KMSG_COMPONENT "vmur" 11#define KMSG_COMPONENT "vmur"
12#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 12#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
13 13
14#include <linux/kernel_stat.h>
14#include <linux/cdev.h> 15#include <linux/cdev.h>
15#include <linux/slab.h> 16#include <linux/slab.h>
16#include <linux/module.h>
17 17
18#include <asm/uaccess.h> 18#include <asm/uaccess.h>
19#include <asm/cio.h> 19#include <asm/cio.h>
@@ -74,7 +74,6 @@ static struct ccw_driver ur_driver = {
74 .set_online = ur_set_online, 74 .set_online = ur_set_online,
75 .set_offline = ur_set_offline, 75 .set_offline = ur_set_offline,
76 .freeze = ur_pm_suspend, 76 .freeze = ur_pm_suspend,
77 .int_class = IRQIO_VMR,
78}; 77};
79 78
80static DEFINE_MUTEX(vmur_mutex); 79static DEFINE_MUTEX(vmur_mutex);
@@ -306,6 +305,7 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
306{ 305{
307 struct urdev *urd; 306 struct urdev *urd;
308 307
308 kstat_cpu(smp_processor_id()).irqs[IOINT_VMR]++;
309 TRACE("ur_int_handler: intparm=0x%lx cstat=%02x dstat=%02x res=%u\n", 309 TRACE("ur_int_handler: intparm=0x%lx cstat=%02x dstat=%02x res=%u\n",
310 intparm, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat, 310 intparm, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
311 irb->scsw.cmd.count); 311 irb->scsw.cmd.count);
@@ -903,7 +903,7 @@ static int ur_set_online(struct ccw_device *cdev)
903 goto fail_urdev_put; 903 goto fail_urdev_put;
904 } 904 }
905 905
906 urd->char_device->ops = &ur_fops; 906 cdev_init(urd->char_device, &ur_fops);
907 urd->char_device->dev = MKDEV(major, minor); 907 urd->char_device->dev = MKDEV(major, minor);
908 urd->char_device->owner = ur_fops.owner; 908 urd->char_device->owner = ur_fops.owner;
909 909
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index e9b72311e25..11312f401c7 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Watchdog implementation based on z/VM Watchdog Timer API 2 * Watchdog implementation based on z/VM Watchdog Timer API
3 * 3 *
4 * Copyright IBM Corp. 2004, 2009 4 * Copyright IBM Corp. 2004,2009
5 * 5 *
6 * The user space watchdog daemon can use this driver as 6 * The user space watchdog daemon can use this driver as
7 * /dev/vmwatchdog to have z/VM execute the specified CP 7 * /dev/vmwatchdog to have z/VM execute the specified CP
@@ -28,9 +28,9 @@
28#define MAX_CMDLEN 240 28#define MAX_CMDLEN 240
29#define MIN_INTERVAL 15 29#define MIN_INTERVAL 15
30static char vmwdt_cmd[MAX_CMDLEN] = "IPL"; 30static char vmwdt_cmd[MAX_CMDLEN] = "IPL";
31static bool vmwdt_conceal; 31static int vmwdt_conceal;
32 32
33static bool vmwdt_nowayout = WATCHDOG_NOWAYOUT; 33static int vmwdt_nowayout = WATCHDOG_NOWAYOUT;
34 34
35MODULE_LICENSE("GPL"); 35MODULE_LICENSE("GPL");
36MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>"); 36MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index e3b9308b0fe..3b94044027c 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * For more information please refer to Documentation/s390/zfcpdump.txt 6 * For more information please refer to Documentation/s390/zfcpdump.txt
7 * 7 *
8 * Copyright IBM Corp. 2003, 2008 8 * Copyright IBM Corp. 2003,2008
9 * Author(s): Michael Holzheu 9 * Author(s): Michael Holzheu
10 */ 10 */
11 11
@@ -16,11 +16,11 @@
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/miscdevice.h> 17#include <linux/miscdevice.h>
18#include <linux/debugfs.h> 18#include <linux/debugfs.h>
19#include <linux/module.h>
20#include <asm/asm-offsets.h> 19#include <asm/asm-offsets.h>
21#include <asm/ipl.h> 20#include <asm/ipl.h>
22#include <asm/sclp.h> 21#include <asm/sclp.h>
23#include <asm/setup.h> 22#include <asm/setup.h>
23#include <asm/sigp.h>
24#include <asm/uaccess.h> 24#include <asm/uaccess.h>
25#include <asm/debug.h> 25#include <asm/debug.h>
26#include <asm/processor.h> 26#include <asm/processor.h>
@@ -142,6 +142,22 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
142 return memcpy_hsa(dest, src, count, TO_KERNEL); 142 return memcpy_hsa(dest, src, count, TO_KERNEL);
143} 143}
144 144
145static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
146{
147 static char buf[4096];
148 int offs = 0, size;
149
150 while (offs < count) {
151 size = min(sizeof(buf), count - offs);
152 if (memcpy_real(buf, (void *) src + offs, size))
153 return -EFAULT;
154 if (copy_to_user(dest + offs, buf, size))
155 return -EFAULT;
156 offs += size;
157 }
158 return 0;
159}
160
145static int __init init_cpu_info(enum arch_id arch) 161static int __init init_cpu_info(enum arch_id arch)
146{ 162{
147 struct save_area *sa; 163 struct save_area *sa;
@@ -330,8 +346,8 @@ static ssize_t zcore_read(struct file *file, char __user *buf, size_t count,
330 346
331 /* Copy from real mem */ 347 /* Copy from real mem */
332 size = count - mem_offs - hdr_count; 348 size = count - mem_offs - hdr_count;
333 rc = copy_to_user_real(buf + hdr_count + mem_offs, 349 rc = memcpy_real_user(buf + hdr_count + mem_offs, mem_start + mem_offs,
334 (void *) mem_start + mem_offs, size); 350 size);
335 if (rc) 351 if (rc)
336 goto fail; 352 goto fail;
337 353
@@ -640,8 +656,6 @@ static int __init zcore_init(void)
640 656
641 if (ipl_info.type != IPL_TYPE_FCP_DUMP) 657 if (ipl_info.type != IPL_TYPE_FCP_DUMP)
642 return -ENODATA; 658 return -ENODATA;
643 if (OLDMEM_BASE)
644 return -ENODATA;
645 659
646 zcore_dbf = debug_register("zcore", 4, 1, 4 * sizeof(long)); 660 zcore_dbf = debug_register("zcore", 4, 1, 4 * sizeof(long));
647 debug_register_view(zcore_dbf, &debug_sprintf_view); 661 debug_register_view(zcore_dbf, &debug_sprintf_view);