diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
| commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
| tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/s390/char | |
| parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) | |
Patched in Tegra support.
Diffstat (limited to 'drivers/s390/char')
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 | ||
| 76 | struct raw3215_info { | 79 | struct 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 | */ |
| 308 | static inline void raw3215_try_io(struct raw3215_info *raw) | 310 | static 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 | */ |
| 336 | static void raw3215_wakeup(unsigned long data) | 340 | static 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 | */ | ||
| 351 | static 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 | } |
| 458 | put_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 | ||
| 655 | static 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 | |||
| 678 | static 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 | |||
| 686 | static int raw3215_probe (struct ccw_device *cdev) | 648 | static 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 | ||
| 719 | static void raw3215_remove (struct ccw_device *cdev) | 694 | static 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) | |||
| 945 | console_initcall(con3215_init); | 919 | console_initcall(con3215_init); |
| 946 | #endif | 920 | #endif |
| 947 | 921 | ||
| 948 | static 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 | */ |
| 966 | static int tty3215_open(struct tty_struct *tty, struct file * filp) | 927 | static 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 | ||
| 1130 | static const struct tty_operations tty3215_ops = { | 1099 | static 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 | */ |
| 36 | struct con3270 { | 36 | struct 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 | |||
| 238 | k_fn(struct kbd_data *kbd, unsigned char value) | 239 | k_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 | ||
| 244 | static void | 245 | static 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 | */ |
| 258 | static void | 259 | static void |
| 259 | to_utf8(struct tty_port *port, ushort c) | 260 | to_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 | ||
| 457 | int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg) | 458 | int 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 | ||
| 22 | struct kbd_data { | 23 | struct 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 | */ |
| 43 | static inline void | 44 | static inline void |
| 44 | kbd_put_queue(struct tty_port *port, int ch) | 45 | kbd_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 | ||
| 54 | static inline void | 51 | static inline void |
| 55 | kbd_puts_queue(struct tty_port *port, char *cp) | 52 | kbd_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); | |||
| 75 | static int raw3270_registered; | 76 | static int raw3270_registered; |
| 76 | 77 | ||
| 77 | /* Module parameters */ | 78 | /* Module parameters */ |
| 78 | static bool tubxcorrect = 0; | 79 | static int tubxcorrect = 0; |
| 79 | module_param(tubxcorrect, bool, 0); | 80 | module_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 | ||
| 1402 | static int | 1403 | static 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. */ |
| 396 | static void sclp_interrupt_handler(struct ext_code ext_code, | 396 | static 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 | ||
| 655 | EXPORT_SYMBOL(sclp_remove_processed); | 655 | EXPORT_SYMBOL(sclp_remove_processed); |
| 656 | 656 | ||
| 657 | struct 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. */ |
| 658 | static inline void | 668 | static 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. */ |
| 811 | static void sclp_check_handler(struct ext_code ext_code, | 821 | static 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 | ||
| 91 | struct 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 | |||
| 101 | extern u64 sclp_facilities; | 91 | extern 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 | ||
| 109 | struct gds_subvector { | 98 | struct 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 | ||
| 53 | static struct init_sccb __initdata early_event_mask_sccb __aligned(PAGE_SIZE); | ||
| 54 | static struct read_info_sccb __initdata early_read_info_sccb; | 48 | static struct read_info_sccb __initdata early_read_info_sccb; |
| 55 | static int __initdata early_read_info_sccb_valid; | 49 | static int __initdata early_read_info_sccb_valid; |
| 56 | 50 | ||
| 57 | u64 sclp_facilities; | 51 | u64 sclp_facilities; |
| 58 | static u8 sclp_fac84; | 52 | static u8 sclp_fac84; |
| 59 | static u8 sclp_fac85; | ||
| 60 | static unsigned long long rzm; | 53 | static unsigned long long rzm; |
| 61 | static unsigned long long rnmax; | 54 | static 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(); |
| 74 | out: | 67 | out: |
| 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 | ||
| 110 | static 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 | |||
| 123 | void __init sclp_facilities_detect(void) | 103 | void __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 | |||
| 142 | bool __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 | |||
| 153 | bool __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 | ||
| 164 | unsigned long long sclp_get_rnmax(void) | 119 | unsigned 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 | ||
| 174 | u8 sclp_get_fac85(void) | ||
| 175 | { | ||
| 176 | return sclp_fac85; | ||
| 177 | } | ||
| 178 | EXPORT_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 | ||
| 403 | static int sclp_assign_storage(u16 rn) | 352 | static 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 | ||
| 416 | static int sclp_unassign_storage(u16 rn) | 357 | static 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 | |||
| 712 | struct 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 | |||
| 720 | static 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 | } | ||
| 748 | out: | ||
| 749 | free_page((unsigned long) sccb); | ||
| 750 | return rc; | ||
| 751 | } | ||
| 752 | |||
| 753 | int sclp_pci_configure(u32 fid) | ||
| 754 | { | ||
| 755 | return do_pci_configure(SCLP_CMDW_CONFIGURE_PCI, fid); | ||
| 756 | } | ||
| 757 | EXPORT_SYMBOL(sclp_pci_configure); | ||
| 758 | |||
| 759 | int sclp_pci_deconfigure(u32 fid) | ||
| 760 | { | ||
| 761 | return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI, fid); | ||
| 762 | } | ||
| 763 | EXPORT_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; | |||
| 29 | static void sclp_cpu_capability_notify(struct work_struct *work) | 31 | static 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 | ||
| 65 | static struct sdias_sccb sccb __attribute__((aligned(4096))); | 64 | static struct sdias_sccb sccb __attribute__((aligned(4096))); |
| 66 | static struct sdias_evbuf sdias_evbuf; | ||
| 67 | 65 | ||
| 68 | static DECLARE_COMPLETION(evbuf_accepted); | 66 | static int sclp_req_done; |
| 69 | static DECLARE_COMPLETION(evbuf_done); | 67 | static wait_queue_head_t sdias_wq; |
| 70 | static DEFINE_MUTEX(sdias_mutex); | 68 | static DEFINE_MUTEX(sdias_mutex); |
| 71 | 69 | ||
| 72 | /* | ||
| 73 | * Called by SCLP base when read event data has been completed (async mode only) | ||
| 74 | */ | ||
| 75 | static 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 | */ | ||
| 86 | static void sdias_callback(struct sclp_req *request, void *data) | 70 | static 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 | } |
| 258 | out: | 228 | out: |
| @@ -260,50 +230,19 @@ out: | |||
| 260 | return rc; | 230 | return rc; |
| 261 | } | 231 | } |
| 262 | 232 | ||
| 263 | static int __init sclp_sdias_register_check(void) | 233 | int __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 | |||
| 277 | static 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 | |||
| 285 | static 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 | |||
| 293 | int __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; | ||
| 306 | out: | ||
| 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. */ |
| 48 | static struct timer_list sclp_tty_timer; | 49 | static struct timer_list sclp_tty_timer; |
| 49 | 50 | ||
| 50 | static struct tty_port sclp_port; | 51 | static struct tty_struct *sclp_tty; |
| 51 | static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE]; | 52 | static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE]; |
| 52 | static unsigned short int sclp_tty_chars_count; | 53 | static unsigned short int sclp_tty_chars_count; |
| 53 | 54 | ||
| @@ -63,7 +64,7 @@ static int sclp_tty_columns = 80; | |||
| 63 | static int | 64 | static int |
| 64 | sclp_tty_open(struct tty_struct *tty, struct file *filp) | 65 | sclp_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) | |||
| 107 | static void | 108 | static void |
| 108 | sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc) | 109 | sclp_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) | |||
| 328 | static void | 326 | static void |
| 329 | sclp_tty_input(unsigned char* buf, unsigned int count) | 327 | sclp_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 */ |
| 39 | struct sclp_vt220_request { | 40 | struct 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 */ |
| 56 | static struct tty_driver *sclp_vt220_driver; | 57 | static struct tty_driver *sclp_vt220_driver; |
| 57 | 58 | ||
| 58 | static struct tty_port sclp_vt220_port; | 59 | /* The tty_struct that the kernel associated with us */ |
| 60 | static 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 */ |
| 61 | static spinlock_t sclp_vt220_lock; | 63 | static spinlock_t sclp_vt220_lock; |
| @@ -114,7 +116,6 @@ static struct sclp_register sclp_vt220_register = { | |||
| 114 | static void | 116 | static void |
| 115 | sclp_vt220_process_queue(struct sclp_vt220_request *request) | 117 | sclp_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) | |||
| 461 | static void | 460 | static void |
| 462 | sclp_vt220_receiver_fn(struct evbuf_header *evbuf) | 461 | sclp_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 | |||
| 494 | sclp_vt220_open(struct tty_struct *tty, struct file *filp) | 491 | sclp_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) | |||
| 510 | static void | 510 | static void |
| 511 | sclp_vt220_close(struct tty_struct *tty, struct file *filp) | 511 | sclp_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 */ | ||
| 187 | struct 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 */ |
| 178 | struct tape_device { | 206 | struct 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); | |||
| 281 | extern int tapechar_setup_device(struct tape_device *); | 313 | extern int tapechar_setup_device(struct tape_device *); |
| 282 | extern void tapechar_cleanup_device(struct tape_device *); | 314 | extern void tapechar_cleanup_device(struct tape_device *); |
| 283 | 315 | ||
| 316 | /* Externals from tape_block.c */ | ||
| 317 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
| 318 | extern int tapeblock_init (void); | ||
| 319 | extern void tapeblock_exit(void); | ||
| 320 | extern int tapeblock_setup_device(struct tape_device *); | ||
| 321 | extern void tapeblock_cleanup_device(struct tape_device *); | ||
| 322 | #else | ||
| 323 | static inline int tapeblock_init (void) {return 0;} | ||
| 324 | static inline void tapeblock_exit (void) {;} | ||
| 325 | static inline int tapeblock_setup_device(struct tape_device *t) {return 0;} | ||
| 326 | static 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 |
| 286 | extern void tape_proc_init (void); | 331 | extern 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 | */ | ||
| 1136 | static struct tape_request * | ||
| 1137 | tape_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 | |||
| 1196 | static void | ||
| 1197 | tape_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 | */ | ||
| 1227 | static void | ||
| 1228 | tape_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 | ||
| 1199 | static int | 1335 | static 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 | */ | ||
| 677 | static struct tape_request * | ||
| 678 | tape_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 | |||
| 727 | static void | ||
| 728 | tape_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 | */ | ||
| 745 | static void | ||
| 746 | tape_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 | |||
| 672 | static void tape_3590_med_state_set(struct tape_device *device, | 759 | static 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 | ||
| 17 | MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>"); | 18 | MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>"); |
| 18 | MODULE_DESCRIPTION( | 19 | MODULE_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 | ); |
| 22 | MODULE_LICENSE("GPL"); | 23 | MODULE_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 | ||
| 415 | out_char: | ||
| 416 | tapechar_cleanup_device(device); | ||
| 410 | out_minor: | 417 | out_minor: |
| 411 | tape_remove_minor(device); | 418 | tape_remove_minor(device); |
| 412 | out_discipline: | 419 | out_discipline: |
| @@ -420,6 +427,7 @@ out: | |||
| 420 | static void | 427 | static void |
| 421 | tape_cleanup_device(struct tape_device *device) | 428 | tape_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 | */ |
| 1247 | int | 1260 | int |
| 1248 | tape_open(struct tape_device *device) | 1261 | tape_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 | */ |
| 1277 | int | 1290 | int |
| 1278 | tape_release(struct tape_device *device) | 1291 | tape_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); | |||
| 100 | void tape_std_read_backward(struct tape_device *device, | 101 | void tape_std_read_backward(struct tape_device *device, |
| 101 | struct tape_request *request); | 102 | struct tape_request *request); |
| 102 | struct tape_request *tape_std_write_block(struct tape_device *, size_t); | 103 | struct tape_request *tape_std_write_block(struct tape_device *, size_t); |
| 104 | struct tape_request *tape_std_bread(struct tape_device *, struct request *); | ||
| 105 | void tape_std_free_bread(struct tape_request *); | ||
| 103 | void tape_std_check_locate(struct tape_device *, struct tape_request *); | 106 | void tape_std_check_locate(struct tape_device *, struct tape_request *); |
| 107 | struct tape_request *tape_std_bwrite(struct request *, | ||
| 108 | struct tape_device *, int); | ||
| 104 | 109 | ||
| 105 | /* Some non-mtop commands. */ | 110 | /* Some non-mtop commands. */ |
| 106 | int tape_std_assign(struct tape_device *); | 111 | int 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 | */ |
| 61 | struct tty3270 { | 62 | struct 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) | |||
| 323 | static void | 324 | static void |
| 324 | tty3270_write_callback(struct raw3270_request *rq, void *data) | 325 | tty3270_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) | |||
| 448 | static void | 450 | static void |
| 449 | tty3270_rcl_backward(struct kbd_data *kbd) | 451 | tty3270_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) | |||
| 475 | static void | 478 | static void |
| 476 | tty3270_exit_tty(struct kbd_data *kbd) | 479 | tty3270_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) | |||
| 486 | static void | 490 | static void |
| 487 | tty3270_scroll_forward(struct kbd_data *kbd) | 491 | tty3270_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) | |||
| 508 | static void | 513 | static void |
| 509 | tty3270_scroll_backward(struct kbd_data *kbd) | 514 | tty3270_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 | |||
| 531 | tty3270_read_tasklet(struct raw3270_request *rrq) | 537 | tty3270_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) | |||
| 586 | static void | 596 | static void |
| 587 | tty3270_read_callback(struct raw3270_request *rq, void *data) | 597 | tty3270_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) | |||
| 626 | static int | 635 | static int |
| 627 | tty3270_activate(struct raw3270_view *view) | 636 | tty3270_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) | |||
| 636 | static void | 646 | static void |
| 637 | tty3270_deactivate(struct raw3270_view *view) | 647 | tty3270_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); | ||
| 726 | out_tp: | 725 | out_tp: |
| 727 | kfree(tp); | 726 | kfree(tp); |
| 728 | out_err: | 727 | out_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) | |||
| 796 | static void | 794 | static void |
| 797 | tty3270_release(struct raw3270_view *view) | 795 | tty3270_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) | |||
| 814 | static void | 813 | static void |
| 815 | tty3270_free(struct raw3270_view *view) | 814 | tty3270_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) | |||
| 825 | static void | 823 | static void |
| 826 | tty3270_del_views(void) | 824 | tty3270_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 | */ |
| 849 | static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty) | 848 | static int |
| 849 | tty3270_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) | |||
| 932 | static void | 935 | static void |
| 933 | tty3270_close(struct tty_struct *tty, struct file * filp) | 936 | tty3270_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 | |||
| 945 | static 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 | */ |
| 1518 | static void | 1515 | static void |
| 1519 | tty3270_do_write(struct tty3270 *tp, struct tty_struct *tty, | 1516 | tty3270_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 | ||
| 1753 | static const struct tty_operations tty3270_ops = { | 1749 | static 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 | |||
| 658 | static DRIVER_ATTR(recording_status, 0444, vmlogrdr_recording_status_show, | 661 | static DRIVER_ATTR(recording_status, 0444, vmlogrdr_recording_status_show, |
| 659 | NULL); | 662 | NULL); |
| 660 | static struct attribute *vmlogrdr_drv_attrs[] = { | ||
| 661 | &driver_attr_recording_status.attr, | ||
| 662 | NULL, | ||
| 663 | }; | ||
| 664 | static struct attribute_group vmlogrdr_drv_attr_group = { | ||
| 665 | .attrs = vmlogrdr_drv_attrs, | ||
| 666 | }; | ||
| 667 | static const struct attribute_group *vmlogrdr_drv_attr_groups[] = { | ||
| 668 | &vmlogrdr_drv_attr_group, | ||
| 669 | NULL, | ||
| 670 | }; | ||
| 671 | 663 | ||
| 672 | static struct attribute *vmlogrdr_attrs[] = { | 664 | static 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 | }; |
| 679 | static struct attribute_group vmlogrdr_attr_group = { | ||
| 680 | .attrs = vmlogrdr_attrs, | ||
| 681 | }; | ||
| 682 | static const struct attribute_group *vmlogrdr_attr_groups[] = { | ||
| 683 | &vmlogrdr_attr_group, | ||
| 684 | NULL, | ||
| 685 | }; | ||
| 686 | 671 | ||
| 687 | static int vmlogrdr_pm_prepare(struct device *dev) | 672 | static 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 | ||
| 695 | static struct attribute_group vmlogrdr_attr_group = { | ||
| 696 | .attrs = vmlogrdr_attrs, | ||
| 697 | }; | ||
| 698 | |||
| 710 | static struct class *vmlogrdr_class; | 699 | static struct class *vmlogrdr_class; |
| 711 | static struct device_driver vmlogrdr_driver = { | 700 | static 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 | |||
| 718 | static int vmlogrdr_register_driver(void) | 707 | static 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 | ||
| 733 | out_attr: | ||
| 734 | driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status); | ||
| 739 | out_driver: | 735 | out_driver: |
| 740 | driver_unregister(&vmlogrdr_driver); | 736 | driver_unregister(&vmlogrdr_driver); |
| 741 | out_iucv: | 737 | out_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 | ||
| 80 | static DEFINE_MUTEX(vmur_mutex); | 79 | static 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 |
| 30 | static char vmwdt_cmd[MAX_CMDLEN] = "IPL"; | 30 | static char vmwdt_cmd[MAX_CMDLEN] = "IPL"; |
| 31 | static bool vmwdt_conceal; | 31 | static int vmwdt_conceal; |
| 32 | 32 | ||
| 33 | static bool vmwdt_nowayout = WATCHDOG_NOWAYOUT; | 33 | static int vmwdt_nowayout = WATCHDOG_NOWAYOUT; |
| 34 | 34 | ||
| 35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
| 36 | MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>"); | 36 | MODULE_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 | ||
| 145 | static 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 | |||
| 145 | static int __init init_cpu_info(enum arch_id arch) | 161 | static 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); |
