Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/3270: asynchronous size sensing

Convert the synchronous size sense code to an interrupt driven
approach. This allows to set the device online even if the
terminal is not connected. With the new code views can be
registered without a connected terminal, the tty can be opened
as soon as the device is online. After the terminal has been
connected and the size has been determined the tty is resized
to match the device characteristics..

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

+332 -314
+246 -289
drivers/s390/char/raw3270.c
··· 37 37 int minor; 38 38 39 39 short model, rows, cols; 40 + unsigned int state; 40 41 unsigned long flags; 41 42 42 43 struct list_head req_queue; /* Request queue. */ ··· 48 47 49 48 unsigned char *ascebc; /* ascii -> ebcdic table */ 50 49 51 - struct raw3270_request init_request; 50 + struct raw3270_view init_view; 51 + struct raw3270_request init_reset; 52 + struct raw3270_request init_readpart; 53 + struct raw3270_request init_readmod; 52 54 unsigned char init_data[256]; 53 55 }; 56 + 57 + /* raw3270->state */ 58 + #define RAW3270_STATE_INIT 0 /* Initial state */ 59 + #define RAW3270_STATE_RESET 1 /* Reset command is pending */ 60 + #define RAW3270_STATE_W4ATTN 2 /* Wait for attention interrupt */ 61 + #define RAW3270_STATE_READMOD 3 /* Read partition is pending */ 62 + #define RAW3270_STATE_READY 4 /* Device is usable by views */ 54 63 55 64 /* raw3270->flags */ 56 65 #define RAW3270_FLAGS_14BITADDR 0 /* 14-bit buffer addresses */ 57 66 #define RAW3270_FLAGS_BUSY 1 /* Device busy, leave it alone */ 58 - #define RAW3270_FLAGS_ATTN 2 /* Device sent an ATTN interrupt */ 59 - #define RAW3270_FLAGS_READY 4 /* Device is useable by views */ 60 - #define RAW3270_FLAGS_CONSOLE 8 /* Device is the console. */ 61 - #define RAW3270_FLAGS_FROZEN 16 /* set if 3270 is frozen for suspend */ 67 + #define RAW3270_FLAGS_CONSOLE 2 /* Device is the console. */ 68 + #define RAW3270_FLAGS_FROZEN 3 /* set if 3270 is frozen for suspend */ 62 69 63 70 /* Semaphore to protect global data of raw3270 (devices, views, etc). */ 64 71 static DEFINE_MUTEX(raw3270_mutex); ··· 103 94 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 104 95 0xf8, 0xf9, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f 105 96 }; 97 + 98 + static inline int raw3270_state_ready(struct raw3270 *rp) 99 + { 100 + return rp->state == RAW3270_STATE_READY; 101 + } 102 + 103 + static inline int raw3270_state_final(struct raw3270 *rp) 104 + { 105 + return rp->state == RAW3270_STATE_INIT || 106 + rp->state == RAW3270_STATE_READY; 107 + } 106 108 107 109 void 108 110 raw3270_buffer_address(struct raw3270 *rp, char *cp, unsigned short addr) ··· 232 212 * Stop running ccw. 233 213 */ 234 214 static int 235 - raw3270_halt_io_nolock(struct raw3270 *rp, struct raw3270_request *rq) 215 + __raw3270_halt_io(struct raw3270 *rp, struct raw3270_request *rq) 236 216 { 237 217 int retries; 238 218 int rc; ··· 248 228 if (rc == 0) 249 229 break; /* termination successful */ 250 230 } 251 - return rc; 252 - } 253 - 254 - static int 255 - raw3270_halt_io(struct raw3270 *rp, struct raw3270_request *rq) 256 - { 257 - unsigned long flags; 258 - int rc; 259 - 260 - spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); 261 - rc = raw3270_halt_io_nolock(rp, rq); 262 - spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); 263 231 return rc; 264 232 } 265 233 ··· 287 279 if (!rp || rp->view != view || 288 280 test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) 289 281 rc = -EACCES; 290 - else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) 291 - rc = -ENODEV; 282 + else if (!raw3270_state_ready(rp)) 283 + rc = -EBUSY; 292 284 else 293 285 rc = __raw3270_start(rp, view, rq); 294 286 spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags); ··· 305 297 if (!rp || rp->view != view || 306 298 test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) 307 299 rc = -EACCES; 308 - else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) 309 - rc = -ENODEV; 300 + else if (!raw3270_state_ready(rp)) 301 + rc = -EBUSY; 310 302 else 311 303 rc = __raw3270_start(rp, view, rq); 312 304 return rc; ··· 384 376 case RAW3270_IO_STOP: 385 377 if (!rq) 386 378 break; 387 - raw3270_halt_io_nolock(rp, rq); 379 + __raw3270_halt_io(rp, rq); 388 380 rq->rc = -EIO; 389 381 break; 390 382 default: ··· 419 411 } 420 412 421 413 /* 422 - * Size sensing. 414 + * To determine the size of the 3270 device we need to do: 415 + * 1) send a 'read partition' data stream to the device 416 + * 2) wait for the attn interrupt that precedes the query reply 417 + * 3) do a read modified to get the query reply 418 + * To make things worse we have to cope with intervention 419 + * required (3270 device switched to 'stand-by') and command 420 + * rejects (old devices that can't do 'read partition'). 423 421 */ 424 - 425 422 struct raw3270_ua { /* Query Reply structure for Usable Area */ 426 423 struct { /* Usable Area Query Reply Base */ 427 424 short l; /* Length of this structured field */ ··· 462 449 } __attribute__ ((packed)) aua; 463 450 } __attribute__ ((packed)); 464 451 465 - static struct diag210 raw3270_init_diag210; 466 - static DEFINE_MUTEX(raw3270_init_mutex); 467 - 468 - static int 469 - raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq, 470 - struct irb *irb) 471 - { 472 - /* 473 - * Unit-Check Processing: 474 - * Expect Command Reject or Intervention Required. 475 - */ 476 - if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) { 477 - /* Request finished abnormally. */ 478 - if (irb->ecw[0] & SNS0_INTERVENTION_REQ) { 479 - set_bit(RAW3270_FLAGS_BUSY, &view->dev->flags); 480 - return RAW3270_IO_BUSY; 481 - } 482 - } 483 - if (rq) { 484 - if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) { 485 - if (irb->ecw[0] & SNS0_CMD_REJECT) 486 - rq->rc = -EOPNOTSUPP; 487 - else 488 - rq->rc = -EIO; 489 - } else 490 - /* Request finished normally. Copy residual count. */ 491 - rq->rescnt = irb->scsw.cmd.count; 492 - } 493 - if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) { 494 - set_bit(RAW3270_FLAGS_ATTN, &view->dev->flags); 495 - wake_up(&raw3270_wait_queue); 496 - } 497 - return RAW3270_IO_DONE; 498 - } 499 - 500 - static struct raw3270_fn raw3270_init_fn = { 501 - .intv = raw3270_init_irq 502 - }; 503 - 504 - static struct raw3270_view raw3270_init_view = { 505 - .fn = &raw3270_init_fn 506 - }; 507 - 508 - /* 509 - * raw3270_wait/raw3270_wait_interruptible/__raw3270_wakeup 510 - * Wait for end of request. The request must have been started 511 - * with raw3270_start, rc = 0. The device lock may NOT have been 512 - * released between calling raw3270_start and raw3270_wait. 513 - */ 514 452 static void 515 - raw3270_wake_init(struct raw3270_request *rq, void *data) 516 - { 517 - wake_up((wait_queue_head_t *) data); 518 - } 519 - 520 - /* 521 - * Special wait function that can cope with console initialization. 522 - */ 523 - static int 524 - raw3270_start_init(struct raw3270 *rp, struct raw3270_view *view, 525 - struct raw3270_request *rq) 526 - { 527 - unsigned long flags; 528 - int rc; 529 - 530 - #ifdef CONFIG_TN3270_CONSOLE 531 - if (raw3270_registered == 0) { 532 - spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags); 533 - rq->callback = NULL; 534 - rc = __raw3270_start(rp, view, rq); 535 - if (rc == 0) 536 - while (!raw3270_request_final(rq)) { 537 - wait_cons_dev(); 538 - barrier(); 539 - } 540 - spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags); 541 - return rq->rc; 542 - } 543 - #endif 544 - rq->callback = raw3270_wake_init; 545 - rq->callback_data = &raw3270_wait_queue; 546 - spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags); 547 - rc = __raw3270_start(rp, view, rq); 548 - spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags); 549 - if (rc) 550 - return rc; 551 - /* Now wait for the completion. */ 552 - rc = wait_event_interruptible(raw3270_wait_queue, 553 - raw3270_request_final(rq)); 554 - if (rc == -ERESTARTSYS) { /* Interrupted by a signal. */ 555 - raw3270_halt_io(view->dev, rq); 556 - /* No wait for the halt to complete. */ 557 - wait_event(raw3270_wait_queue, raw3270_request_final(rq)); 558 - return -ERESTARTSYS; 559 - } 560 - return rq->rc; 561 - } 562 - 563 - static int 564 - __raw3270_size_device_vm(struct raw3270 *rp) 453 + raw3270_size_device_vm(struct raw3270 *rp) 565 454 { 566 455 int rc, model; 567 456 struct ccw_dev_id dev_id; 457 + struct diag210 diag_data; 568 458 569 459 ccw_device_get_id(rp->cdev, &dev_id); 570 - raw3270_init_diag210.vrdcdvno = dev_id.devno; 571 - raw3270_init_diag210.vrdclen = sizeof(struct diag210); 572 - rc = diag210(&raw3270_init_diag210); 573 - if (rc) 574 - return rc; 575 - model = raw3270_init_diag210.vrdccrmd; 460 + diag_data.vrdcdvno = dev_id.devno; 461 + diag_data.vrdclen = sizeof(struct diag210); 462 + rc = diag210(&diag_data); 463 + model = diag_data.vrdccrmd; 464 + /* Use default model 2 if the size could not be detected */ 465 + if (rc || model < 2 || model > 5) 466 + model = 2; 576 467 switch (model) { 577 468 case 2: 578 469 rp->model = model; ··· 498 581 rp->rows = 27; 499 582 rp->cols = 132; 500 583 break; 501 - default: 502 - rc = -EOPNOTSUPP; 503 - break; 504 584 } 505 - return rc; 506 585 } 507 586 508 - static int 509 - __raw3270_size_device(struct raw3270 *rp) 587 + static void 588 + raw3270_size_device(struct raw3270 *rp) 510 589 { 511 - static const unsigned char wbuf[] = 512 - { 0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81 }; 513 590 struct raw3270_ua *uap; 514 - int rc; 515 591 516 - /* 517 - * To determine the size of the 3270 device we need to do: 518 - * 1) send a 'read partition' data stream to the device 519 - * 2) wait for the attn interrupt that precedes the query reply 520 - * 3) do a read modified to get the query reply 521 - * To make things worse we have to cope with intervention 522 - * required (3270 device switched to 'stand-by') and command 523 - * rejects (old devices that can't do 'read partition'). 524 - */ 525 - memset(&rp->init_request, 0, sizeof(rp->init_request)); 526 - memset(&rp->init_data, 0, 256); 527 - /* Store 'read partition' data stream to init_data */ 528 - memcpy(&rp->init_data, wbuf, sizeof(wbuf)); 529 - INIT_LIST_HEAD(&rp->init_request.list); 530 - rp->init_request.ccw.cmd_code = TC_WRITESF; 531 - rp->init_request.ccw.flags = CCW_FLAG_SLI; 532 - rp->init_request.ccw.count = sizeof(wbuf); 533 - rp->init_request.ccw.cda = (__u32) __pa(&rp->init_data); 534 - 535 - rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request); 536 - if (rc) 537 - /* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */ 538 - return rc; 539 - 540 - /* Wait for attention interrupt. */ 541 - #ifdef CONFIG_TN3270_CONSOLE 542 - if (raw3270_registered == 0) { 543 - unsigned long flags; 544 - 545 - spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); 546 - while (!test_and_clear_bit(RAW3270_FLAGS_ATTN, &rp->flags)) 547 - wait_cons_dev(); 548 - spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); 549 - } else 550 - #endif 551 - rc = wait_event_interruptible(raw3270_wait_queue, 552 - test_and_clear_bit(RAW3270_FLAGS_ATTN, &rp->flags)); 553 - if (rc) 554 - return rc; 555 - 556 - /* 557 - * The device accepted the 'read partition' command. Now 558 - * set up a read ccw and issue it. 559 - */ 560 - rp->init_request.ccw.cmd_code = TC_READMOD; 561 - rp->init_request.ccw.flags = CCW_FLAG_SLI; 562 - rp->init_request.ccw.count = sizeof(rp->init_data); 563 - rp->init_request.ccw.cda = (__u32) __pa(rp->init_data); 564 - rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request); 565 - if (rc) 566 - return rc; 567 592 /* Got a Query Reply */ 568 593 uap = (struct raw3270_ua *) (rp->init_data + 1); 569 594 /* Paranoia check. */ 570 - if (rp->init_data[0] != 0x88 || uap->uab.qcode != 0x81) 571 - return -EOPNOTSUPP; 595 + if (rp->init_readmod.rc || rp->init_data[0] != 0x88 || 596 + uap->uab.qcode != 0x81) { 597 + /* Couldn't detect size. Use default model 2. */ 598 + rp->model = 2; 599 + rp->rows = 24; 600 + rp->cols = 80; 601 + return; 602 + } 572 603 /* Copy rows/columns of default Usable Area */ 573 604 rp->rows = uap->uab.h; 574 605 rp->cols = uap->uab.w; ··· 529 664 rp->rows = uap->aua.hauai; 530 665 rp->cols = uap->aua.wauai; 531 666 } 532 - return 0; 667 + /* Try to find a model. */ 668 + rp->model = 0; 669 + if (rp->rows == 24 && rp->cols == 80) 670 + rp->model = 2; 671 + if (rp->rows == 32 && rp->cols == 80) 672 + rp->model = 3; 673 + if (rp->rows == 43 && rp->cols == 80) 674 + rp->model = 4; 675 + if (rp->rows == 27 && rp->cols == 132) 676 + rp->model = 5; 677 + } 678 + 679 + static void 680 + raw3270_size_device_done(struct raw3270 *rp) 681 + { 682 + struct raw3270_view *view; 683 + 684 + rp->view = NULL; 685 + rp->state = RAW3270_STATE_READY; 686 + /* Notify views about new size */ 687 + list_for_each_entry(view, &rp->view_list, list) 688 + if (view->fn->resize) 689 + view->fn->resize(view, rp->model, rp->rows, rp->cols); 690 + /* Setup processing done, now activate a view */ 691 + list_for_each_entry(view, &rp->view_list, list) { 692 + rp->view = view; 693 + if (view->fn->activate(view) == 0) 694 + break; 695 + rp->view = NULL; 696 + } 697 + } 698 + 699 + static void 700 + raw3270_read_modified_cb(struct raw3270_request *rq, void *data) 701 + { 702 + struct raw3270 *rp = rq->view->dev; 703 + 704 + raw3270_size_device(rp); 705 + raw3270_size_device_done(rp); 706 + } 707 + 708 + static void 709 + raw3270_read_modified(struct raw3270 *rp) 710 + { 711 + if (rp->state != RAW3270_STATE_W4ATTN) 712 + return; 713 + /* Use 'read modified' to get the result of a read partition. */ 714 + memset(&rp->init_readmod, 0, sizeof(rp->init_readmod)); 715 + memset(&rp->init_data, 0, sizeof(rp->init_data)); 716 + rp->init_readmod.ccw.cmd_code = TC_READMOD; 717 + rp->init_readmod.ccw.flags = CCW_FLAG_SLI; 718 + rp->init_readmod.ccw.count = sizeof(rp->init_data); 719 + rp->init_readmod.ccw.cda = (__u32) __pa(rp->init_data); 720 + rp->init_readmod.callback = raw3270_read_modified_cb; 721 + rp->state = RAW3270_STATE_READMOD; 722 + raw3270_start_irq(&rp->init_view, &rp->init_readmod); 723 + } 724 + 725 + static void 726 + raw3270_writesf_readpart(struct raw3270 *rp) 727 + { 728 + static const unsigned char wbuf[] = 729 + { 0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81 }; 730 + 731 + /* Store 'read partition' data stream to init_data */ 732 + memset(&rp->init_readpart, 0, sizeof(rp->init_readpart)); 733 + memset(&rp->init_data, 0, sizeof(rp->init_data)); 734 + memcpy(&rp->init_data, wbuf, sizeof(wbuf)); 735 + rp->init_readpart.ccw.cmd_code = TC_WRITESF; 736 + rp->init_readpart.ccw.flags = CCW_FLAG_SLI; 737 + rp->init_readpart.ccw.count = sizeof(wbuf); 738 + rp->init_readpart.ccw.cda = (__u32) __pa(&rp->init_data); 739 + rp->state = RAW3270_STATE_W4ATTN; 740 + raw3270_start_irq(&rp->init_view, &rp->init_readpart); 741 + } 742 + 743 + /* 744 + * Device reset 745 + */ 746 + static void 747 + raw3270_reset_device_cb(struct raw3270_request *rq, void *data) 748 + { 749 + struct raw3270 *rp = rq->view->dev; 750 + 751 + if (rp->state != RAW3270_STATE_RESET) 752 + return; 753 + if (rq && rq->rc) { 754 + /* Reset command failed. */ 755 + rp->state = RAW3270_STATE_INIT; 756 + } else if (0 && MACHINE_IS_VM) { 757 + raw3270_size_device_vm(rp); 758 + raw3270_size_device_done(rp); 759 + } else 760 + raw3270_writesf_readpart(rp); 533 761 } 534 762 535 763 static int 536 - raw3270_size_device(struct raw3270 *rp) 764 + __raw3270_reset_device(struct raw3270 *rp) 537 765 { 538 766 int rc; 539 767 540 - mutex_lock(&raw3270_init_mutex); 541 - rp->view = &raw3270_init_view; 542 - raw3270_init_view.dev = rp; 543 - if (MACHINE_IS_VM) 544 - rc = __raw3270_size_device_vm(rp); 545 - else 546 - rc = __raw3270_size_device(rp); 547 - raw3270_init_view.dev = NULL; 548 - rp->view = NULL; 549 - mutex_unlock(&raw3270_init_mutex); 550 - if (rc == 0) { /* Found something. */ 551 - /* Try to find a model. */ 552 - rp->model = 0; 553 - if (rp->rows == 24 && rp->cols == 80) 554 - rp->model = 2; 555 - if (rp->rows == 32 && rp->cols == 80) 556 - rp->model = 3; 557 - if (rp->rows == 43 && rp->cols == 80) 558 - rp->model = 4; 559 - if (rp->rows == 27 && rp->cols == 132) 560 - rp->model = 5; 561 - } else { 562 - /* Couldn't detect size. Use default model 2. */ 563 - rp->model = 2; 564 - rp->rows = 24; 565 - rp->cols = 80; 566 - return 0; 567 - } 768 + /* Store reset data stream to init_data/init_reset */ 769 + memset(&rp->init_reset, 0, sizeof(rp->init_reset)); 770 + memset(&rp->init_data, 0, sizeof(rp->init_data)); 771 + rp->init_data[0] = TW_KR; 772 + rp->init_reset.ccw.cmd_code = TC_EWRITEA; 773 + rp->init_reset.ccw.flags = CCW_FLAG_SLI; 774 + rp->init_reset.ccw.count = 1; 775 + rp->init_reset.ccw.cda = (__u32) __pa(rp->init_data); 776 + rp->init_reset.callback = raw3270_reset_device_cb; 777 + rc = __raw3270_start(rp, &rp->init_view, &rp->init_reset); 778 + if (rc == 0 && rp->state == RAW3270_STATE_INIT) 779 + rp->state = RAW3270_STATE_RESET; 568 780 return rc; 569 781 } 570 782 571 783 static int 572 784 raw3270_reset_device(struct raw3270 *rp) 573 785 { 786 + unsigned long flags; 574 787 int rc; 575 788 576 - mutex_lock(&raw3270_init_mutex); 577 - memset(&rp->init_request, 0, sizeof(rp->init_request)); 578 - memset(&rp->init_data, 0, sizeof(rp->init_data)); 579 - /* Store reset data stream to init_data/init_request */ 580 - rp->init_data[0] = TW_KR; 581 - INIT_LIST_HEAD(&rp->init_request.list); 582 - rp->init_request.ccw.cmd_code = TC_EWRITEA; 583 - rp->init_request.ccw.flags = CCW_FLAG_SLI; 584 - rp->init_request.ccw.count = 1; 585 - rp->init_request.ccw.cda = (__u32) __pa(rp->init_data); 586 - rp->view = &raw3270_init_view; 587 - raw3270_init_view.dev = rp; 588 - rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request); 589 - raw3270_init_view.dev = NULL; 590 - rp->view = NULL; 591 - mutex_unlock(&raw3270_init_mutex); 789 + spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); 790 + rc = __raw3270_reset_device(rp); 791 + spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); 592 792 return rc; 593 793 } 594 794 ··· 667 737 if (!rp || rp->view != view || 668 738 test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) 669 739 rc = -EACCES; 670 - else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) 671 - rc = -ENODEV; 740 + else if (!raw3270_state_ready(rp)) 741 + rc = -EBUSY; 672 742 else 673 743 rc = raw3270_reset_device(view->dev); 674 744 return rc; 675 745 } 746 + 747 + static int 748 + raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq, 749 + struct irb *irb) 750 + { 751 + struct raw3270 *rp; 752 + 753 + /* 754 + * Unit-Check Processing: 755 + * Expect Command Reject or Intervention Required. 756 + */ 757 + if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) { 758 + /* Request finished abnormally. */ 759 + if (irb->ecw[0] & SNS0_INTERVENTION_REQ) { 760 + set_bit(RAW3270_FLAGS_BUSY, &view->dev->flags); 761 + return RAW3270_IO_BUSY; 762 + } 763 + } 764 + if (rq) { 765 + if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) { 766 + if (irb->ecw[0] & SNS0_CMD_REJECT) 767 + rq->rc = -EOPNOTSUPP; 768 + else 769 + rq->rc = -EIO; 770 + } 771 + } 772 + if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) { 773 + /* Queue read modified after attention interrupt */ 774 + rp = view->dev; 775 + raw3270_read_modified(rp); 776 + } 777 + return RAW3270_IO_DONE; 778 + } 779 + 780 + static struct raw3270_fn raw3270_init_fn = { 781 + .intv = raw3270_init_irq 782 + }; 676 783 677 784 /* 678 785 * Setup new 3270 device. ··· 738 771 739 772 INIT_LIST_HEAD(&rp->req_queue); 740 773 INIT_LIST_HEAD(&rp->view_list); 774 + 775 + rp->init_view.dev = rp; 776 + rp->init_view.fn = &raw3270_init_fn; 777 + rp->view = &rp->init_view; 741 778 742 779 /* 743 780 * Add device to list and find the smallest unused minor ··· 781 810 */ 782 811 struct raw3270 __init *raw3270_setup_console(struct ccw_device *cdev) 783 812 { 813 + unsigned long flags; 784 814 struct raw3270 *rp; 785 815 char *ascebc; 786 816 int rc; ··· 792 820 if (rc) 793 821 return ERR_PTR(rc); 794 822 set_bit(RAW3270_FLAGS_CONSOLE, &rp->flags); 795 - rc = raw3270_reset_device(rp); 796 - if (rc) 797 - return ERR_PTR(rc); 798 - rc = raw3270_size_device(rp); 799 - if (rc) 800 - return ERR_PTR(rc); 801 - rc = raw3270_reset_device(rp); 802 - if (rc) 803 - return ERR_PTR(rc); 804 - set_bit(RAW3270_FLAGS_READY, &rp->flags); 823 + spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); 824 + do { 825 + __raw3270_reset_device(rp); 826 + while (!raw3270_state_final(rp)) { 827 + wait_cons_dev(); 828 + barrier(); 829 + } 830 + } while (rp->state != RAW3270_STATE_READY); 831 + spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); 805 832 return rp; 806 833 } 807 834 ··· 862 891 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); 863 892 if (rp->view == view) 864 893 rc = 0; 865 - else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) 866 - rc = -ENODEV; 894 + else if (!raw3270_state_ready(rp)) 895 + rc = -EBUSY; 867 896 else if (test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) 868 897 rc = -EACCES; 869 898 else { 870 899 oldview = NULL; 871 - if (rp->view) { 900 + if (rp->view && rp->view->fn->deactivate) { 872 901 oldview = rp->view; 873 902 oldview->fn->deactivate(oldview); 874 903 } ··· 913 942 list_del_init(&view->list); 914 943 list_add_tail(&view->list, &rp->view_list); 915 944 /* Try to activate another view. */ 916 - if (test_bit(RAW3270_FLAGS_READY, &rp->flags) && 945 + if (raw3270_state_ready(rp) && 917 946 !test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) { 918 947 list_for_each_entry(view, &rp->view_list, list) { 919 948 rp->view = view; ··· 944 973 if (rp->minor != minor) 945 974 continue; 946 975 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); 947 - if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) { 948 - atomic_set(&view->ref_count, 2); 949 - view->dev = rp; 950 - view->fn = fn; 951 - view->model = rp->model; 952 - view->rows = rp->rows; 953 - view->cols = rp->cols; 954 - view->ascebc = rp->ascebc; 955 - spin_lock_init(&view->lock); 956 - list_add(&view->list, &rp->view_list); 957 - rc = 0; 958 - } 976 + atomic_set(&view->ref_count, 2); 977 + view->dev = rp; 978 + view->fn = fn; 979 + view->model = rp->model; 980 + view->rows = rp->rows; 981 + view->cols = rp->cols; 982 + view->ascebc = rp->ascebc; 983 + spin_lock_init(&view->lock); 984 + list_add(&view->list, &rp->view_list); 985 + rc = 0; 959 986 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); 960 987 break; 961 988 } ··· 977 1008 if (rp->minor != minor) 978 1009 continue; 979 1010 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); 980 - if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) { 981 - view = ERR_PTR(-ENOENT); 982 - list_for_each_entry(tmp, &rp->view_list, list) { 983 - if (tmp->fn == fn) { 984 - raw3270_get_view(tmp); 985 - view = tmp; 986 - break; 987 - } 1011 + list_for_each_entry(tmp, &rp->view_list, list) { 1012 + if (tmp->fn == fn) { 1013 + raw3270_get_view(tmp); 1014 + view = tmp; 1015 + break; 988 1016 } 989 1017 } 990 1018 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); ··· 1008 1042 rp->view = NULL; 1009 1043 } 1010 1044 list_del_init(&view->list); 1011 - if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags) && 1045 + if (!rp->view && raw3270_state_ready(rp) && 1012 1046 !test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) { 1013 1047 /* Try to activate another view. */ 1014 1048 list_for_each_entry(nv, &rp->view_list, list) { ··· 1143 1177 rp = raw3270_create_device(cdev); 1144 1178 if (IS_ERR(rp)) 1145 1179 return PTR_ERR(rp); 1146 - rc = raw3270_reset_device(rp); 1147 - if (rc) 1148 - goto failure; 1149 - rc = raw3270_size_device(rp); 1150 - if (rc) 1151 - goto failure; 1152 - rc = raw3270_reset_device(rp); 1153 - if (rc) 1154 - goto failure; 1155 1180 rc = raw3270_create_attributes(rp); 1156 1181 if (rc) 1157 1182 goto failure; 1158 - set_bit(RAW3270_FLAGS_READY, &rp->flags); 1183 + raw3270_reset_device(rp); 1159 1184 mutex_lock(&raw3270_mutex); 1160 1185 list_for_each_entry(np, &raw3270_notifier, list) 1161 1186 np->create(rp->minor); ··· 1178 1221 */ 1179 1222 if (rp == NULL) 1180 1223 return; 1181 - clear_bit(RAW3270_FLAGS_READY, &rp->flags); 1182 1224 1183 1225 sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group); 1184 1226 1185 1227 /* Deactivate current view and remove all views. */ 1186 1228 spin_lock_irqsave(get_ccwdev_lock(cdev), flags); 1187 1229 if (rp->view) { 1188 - rp->view->fn->deactivate(rp->view); 1230 + if (rp->view->fn->deactivate) 1231 + rp->view->fn->deactivate(rp->view); 1189 1232 rp->view = NULL; 1190 1233 } 1191 1234 while (!list_empty(&rp->view_list)) { ··· 1234 1277 if (!rp) 1235 1278 return 0; 1236 1279 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); 1237 - if (rp->view) 1280 + if (rp->view && rp->view->fn->deactivate) 1238 1281 rp->view->fn->deactivate(rp->view); 1239 1282 if (!test_bit(RAW3270_FLAGS_CONSOLE, &rp->flags)) { 1240 1283 /* ··· 1261 1304 return 0; 1262 1305 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); 1263 1306 clear_bit(RAW3270_FLAGS_FROZEN, &rp->flags); 1264 - if (rp->view) 1307 + if (rp->view && rp->view->fn->activate) 1265 1308 rp->view->fn->activate(rp->view); 1266 1309 spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); 1267 1310 return 0;
+1
drivers/s390/char/raw3270.h
··· 141 141 struct raw3270_request *, struct irb *); 142 142 void (*release)(struct raw3270_view *); 143 143 void (*free)(struct raw3270_view *); 144 + void (*resize)(struct raw3270_view *, int, int, int); 144 145 }; 145 146 146 147 /*
+84 -25
drivers/s390/char/tty3270.c
··· 15 15 #include <linux/init.h> 16 16 #include <linux/console.h> 17 17 #include <linux/interrupt.h> 18 + #include <linux/workqueue.h> 18 19 19 20 #include <linux/slab.h> 20 21 #include <linux/bootmem.h> ··· 81 80 unsigned int highlight; /* Blink/reverse/underscore */ 82 81 unsigned int f_color; /* Foreground color */ 83 82 struct tty3270_line *screen; 83 + unsigned int n_model, n_cols, n_rows; /* New model & size */ 84 + struct work_struct resize_work; 84 85 85 86 /* Input stuff. */ 86 87 struct string *prompt; /* Output string for input area. */ ··· 118 115 #define TTY_UPDATE_ALL 16 /* Recreate screen. */ 119 116 120 117 static void tty3270_update(struct tty3270 *); 118 + static void tty3270_resize_work(struct work_struct *work); 121 119 122 120 /* 123 121 * Setup timeout for a device. On timeout trigger an update. ··· 715 711 tasklet_init(&tp->readlet, 716 712 (void (*)(unsigned long)) tty3270_read_tasklet, 717 713 (unsigned long) tp->read); 714 + INIT_WORK(&tp->resize_work, tty3270_resize_work); 718 715 719 716 return tp; 720 717 ··· 759 754 /* 760 755 * Allocate tty3270 screen. 761 756 */ 762 - static int 763 - tty3270_alloc_screen(struct tty3270 *tp) 757 + static struct tty3270_line * 758 + tty3270_alloc_screen(unsigned int rows, unsigned int cols) 764 759 { 760 + struct tty3270_line *screen; 765 761 unsigned long size; 766 762 int lines; 767 763 768 - size = sizeof(struct tty3270_line) * (tp->view.rows - 2); 769 - tp->screen = kzalloc(size, GFP_KERNEL); 770 - if (!tp->screen) 764 + size = sizeof(struct tty3270_line) * (rows - 2); 765 + screen = kzalloc(size, GFP_KERNEL); 766 + if (!screen) 771 767 goto out_err; 772 - for (lines = 0; lines < tp->view.rows - 2; lines++) { 773 - size = sizeof(struct tty3270_cell) * tp->view.cols; 774 - tp->screen[lines].cells = kzalloc(size, GFP_KERNEL); 775 - if (!tp->screen[lines].cells) 768 + for (lines = 0; lines < rows - 2; lines++) { 769 + size = sizeof(struct tty3270_cell) * cols; 770 + screen[lines].cells = kzalloc(size, GFP_KERNEL); 771 + if (!screen[lines].cells) 776 772 goto out_screen; 777 773 } 778 - return 0; 774 + return screen; 779 775 out_screen: 780 776 while (lines--) 781 - kfree(tp->screen[lines].cells); 782 - kfree(tp->screen); 777 + kfree(screen[lines].cells); 778 + kfree(screen); 783 779 out_err: 784 - return -ENOMEM; 780 + return ERR_PTR(-ENOMEM); 785 781 } 786 782 787 783 /* 788 784 * Free tty3270 screen. 789 785 */ 790 786 static void 791 - tty3270_free_screen(struct tty3270 *tp) 787 + tty3270_free_screen(struct tty3270_line *screen, unsigned int rows) 792 788 { 793 789 int lines; 794 790 795 - for (lines = 0; lines < tp->view.rows - 2; lines++) 796 - kfree(tp->screen[lines].cells); 797 - kfree(tp->screen); 791 + for (lines = 0; lines < rows - 2; lines++) 792 + kfree(screen[lines].cells); 793 + kfree(screen); 794 + } 795 + 796 + /* 797 + * Resize tty3270 screen 798 + */ 799 + static void tty3270_resize_work(struct work_struct *work) 800 + { 801 + struct tty3270 *tp = container_of(work, struct tty3270, resize_work); 802 + struct tty3270_line *screen, *oscreen; 803 + struct tty_struct *tty; 804 + unsigned int orows; 805 + struct winsize ws; 806 + 807 + screen = tty3270_alloc_screen(tp->n_rows, tp->n_cols); 808 + if (!screen) 809 + return; 810 + /* Switch to new output size */ 811 + spin_lock_bh(&tp->view.lock); 812 + oscreen = tp->screen; 813 + orows = tp->view.rows; 814 + tp->view.model = tp->n_model; 815 + tp->view.rows = tp->n_rows; 816 + tp->view.cols = tp->n_cols; 817 + tp->screen = screen; 818 + free_string(&tp->freemem, tp->prompt); 819 + free_string(&tp->freemem, tp->status); 820 + tty3270_create_prompt(tp); 821 + tty3270_create_status(tp); 822 + tp->nr_up = 0; 823 + while (tp->nr_lines < tp->view.rows - 2) 824 + tty3270_blank_line(tp); 825 + tp->update_flags = TTY_UPDATE_ALL; 826 + spin_unlock_bh(&tp->view.lock); 827 + tty3270_free_screen(oscreen, orows); 828 + tty3270_set_timer(tp, 1); 829 + /* Informat tty layer about new size */ 830 + tty = tty_port_tty_get(&tp->port); 831 + if (!tty) 832 + return; 833 + ws.ws_row = tp->view.rows - 2; 834 + ws.ws_col = tp->view.cols; 835 + tty_do_resize(tty, &ws); 836 + } 837 + 838 + static void 839 + tty3270_resize(struct raw3270_view *view, int model, int rows, int cols) 840 + { 841 + struct tty3270 *tp = container_of(view, struct tty3270, view); 842 + 843 + tp->n_model = model; 844 + tp->n_rows = rows; 845 + tp->n_cols = cols; 846 + schedule_work(&tp->resize_work); 798 847 } 799 848 800 849 /* ··· 876 817 tty3270_free(struct raw3270_view *view) 877 818 { 878 819 struct tty3270 *tp = container_of(view, struct tty3270, view); 879 - tty3270_free_screen(tp); 820 + 821 + tty3270_free_screen(tp->screen, tp->view.rows); 880 822 tty3270_free_view(tp); 881 823 } 882 824 ··· 901 841 .deactivate = tty3270_deactivate, 902 842 .intv = (void *) tty3270_irq, 903 843 .release = tty3270_release, 904 - .free = tty3270_free 844 + .free = tty3270_free, 845 + .resize = tty3270_resize 905 846 }; 906 847 907 848 /* ··· 930 869 if (tty3270_max_index < tty->index) 931 870 tty3270_max_index = tty->index; 932 871 933 - /* Quick exit if there is no device for tty->index. */ 934 - if (PTR_ERR(view) == -ENODEV) 935 - return -ENODEV; 936 - 937 872 /* Allocate tty3270 structure on first open. */ 938 873 tp = tty3270_alloc_view(); 939 874 if (IS_ERR(tp)) ··· 941 884 return rc; 942 885 } 943 886 944 - rc = tty3270_alloc_screen(tp); 945 - if (rc) { 887 + tp->screen = tty3270_alloc_screen(tp->view.cols, tp->view.rows); 888 + if (IS_ERR(tp->screen)) { 889 + rc = PTR_ERR(tp->screen); 946 890 raw3270_put_view(&tp->view); 947 891 raw3270_del_view(&tp->view); 892 + tty3270_free_view(tp); 948 893 return rc; 949 894 } 950 895
+1
drivers/tty/tty_io.c
··· 2203 2203 mutex_unlock(&tty->termios_mutex); 2204 2204 return 0; 2205 2205 } 2206 + EXPORT_SYMBOL(tty_do_resize); 2206 2207 2207 2208 /** 2208 2209 * tiocswinsz - implement window size set ioctl