aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2012-04-02 07:54:18 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-09 14:28:17 -0400
commitba186e7d17ea874f2a56385806e0ef213f58a1dd (patch)
tree02d5ab7bd13f43fbe12c6d7c7c8452e8788665a5 /drivers/s390
parent20acdfa85c1c0292ee710335900dc04aa7b634a3 (diff)
TTY: tty3270, add tty_port
And use tty from that. This means, we convert most of the users to accept tty_port instead. This is not racy and ensures the tty to be properly refcounted. Signed-off-by: Jiri Slaby <jslaby@suse.cz> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/char/keyboard.c30
-rw-r--r--drivers/s390/char/keyboard.h14
-rw-r--r--drivers/s390/char/tty3270.c48
3 files changed, 49 insertions, 43 deletions
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 806588192483..7ef9cfdc17d8 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -199,7 +199,7 @@ handle_diacr(struct kbd_data *kbd, unsigned int ch)
199 if (ch == ' ' || ch == d) 199 if (ch == ' ' || ch == d)
200 return d; 200 return d;
201 201
202 kbd_put_queue(kbd->tty, d); 202 kbd_put_queue(kbd->port, d);
203 return ch; 203 return ch;
204} 204}
205 205
@@ -221,7 +221,7 @@ k_self(struct kbd_data *kbd, unsigned char value)
221{ 221{
222 if (kbd->diacr) 222 if (kbd->diacr)
223 value = handle_diacr(kbd, value); 223 value = handle_diacr(kbd, value);
224 kbd_put_queue(kbd->tty, value); 224 kbd_put_queue(kbd->port, value);
225} 225}
226 226
227/* 227/*
@@ -239,7 +239,7 @@ static void
239k_fn(struct kbd_data *kbd, unsigned char value) 239k_fn(struct kbd_data *kbd, unsigned char value)
240{ 240{
241 if (kbd->func_table[value]) 241 if (kbd->func_table[value])
242 kbd_puts_queue(kbd->tty, kbd->func_table[value]); 242 kbd_puts_queue(kbd->port, kbd->func_table[value]);
243} 243}
244 244
245static void 245static void
@@ -257,20 +257,20 @@ k_spec(struct kbd_data *kbd, unsigned char value)
257 * but we need only 16 bits here 257 * but we need only 16 bits here
258 */ 258 */
259static void 259static void
260to_utf8(struct tty_struct *tty, ushort c) 260to_utf8(struct tty_port *port, ushort c)
261{ 261{
262 if (c < 0x80) 262 if (c < 0x80)
263 /* 0******* */ 263 /* 0******* */
264 kbd_put_queue(tty, c); 264 kbd_put_queue(port, c);
265 else if (c < 0x800) { 265 else if (c < 0x800) {
266 /* 110***** 10****** */ 266 /* 110***** 10****** */
267 kbd_put_queue(tty, 0xc0 | (c >> 6)); 267 kbd_put_queue(port, 0xc0 | (c >> 6));
268 kbd_put_queue(tty, 0x80 | (c & 0x3f)); 268 kbd_put_queue(port, 0x80 | (c & 0x3f));
269 } else { 269 } else {
270 /* 1110**** 10****** 10****** */ 270 /* 1110**** 10****** 10****** */
271 kbd_put_queue(tty, 0xe0 | (c >> 12)); 271 kbd_put_queue(port, 0xe0 | (c >> 12));
272 kbd_put_queue(tty, 0x80 | ((c >> 6) & 0x3f)); 272 kbd_put_queue(port, 0x80 | ((c >> 6) & 0x3f));
273 kbd_put_queue(tty, 0x80 | (c & 0x3f)); 273 kbd_put_queue(port, 0x80 | (c & 0x3f));
274 } 274 }
275} 275}
276 276
@@ -283,7 +283,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
283 unsigned short keysym; 283 unsigned short keysym;
284 unsigned char type, value; 284 unsigned char type, value;
285 285
286 if (!kbd || !kbd->tty) 286 if (!kbd)
287 return; 287 return;
288 288
289 if (keycode >= 384) 289 if (keycode >= 384)
@@ -323,7 +323,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
323#endif 323#endif
324 (*k_handler[type])(kbd, value); 324 (*k_handler[type])(kbd, value);
325 } else 325 } else
326 to_utf8(kbd->tty, keysym); 326 to_utf8(kbd->port, keysym);
327} 327}
328 328
329/* 329/*
@@ -457,6 +457,7 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs,
457 457
458int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg) 458int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
459{ 459{
460 struct tty_struct *tty;
460 void __user *argp; 461 void __user *argp;
461 unsigned int ct; 462 unsigned int ct;
462 int perm; 463 int perm;
@@ -467,7 +468,10 @@ 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 468 * 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. 469 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
469 */ 470 */
470 perm = current->signal->tty == kbd->tty || capable(CAP_SYS_TTY_CONFIG); 471 tty = tty_port_tty_get(kbd->port);
472 /* FIXME this test is pretty racy */
473 perm = current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG);
474 tty_kref_put(tty);
471 switch (cmd) { 475 switch (cmd) {
472 case KDGKBTYPE: 476 case KDGKBTYPE:
473 return put_user(KB_101, (char __user *)argp); 477 return put_user(KB_101, (char __user *)argp);
diff --git a/drivers/s390/char/keyboard.h b/drivers/s390/char/keyboard.h
index 7e736aaeae6e..f682f4e49680 100644
--- a/drivers/s390/char/keyboard.h
+++ b/drivers/s390/char/keyboard.h
@@ -21,7 +21,7 @@ typedef void (fn_handler_fn)(struct kbd_data *);
21 */ 21 */
22 22
23struct kbd_data { 23struct kbd_data {
24 struct tty_struct *tty; 24 struct tty_port *port;
25 unsigned short **key_maps; 25 unsigned short **key_maps;
26 char **func_table; 26 char **func_table;
27 fn_handler_fn **fn_handler; 27 fn_handler_fn **fn_handler;
@@ -42,16 +42,24 @@ int kbd_ioctl(struct kbd_data *, unsigned int, unsigned long);
42 * Helper Functions. 42 * Helper Functions.
43 */ 43 */
44static inline void 44static inline void
45kbd_put_queue(struct tty_struct *tty, int ch) 45kbd_put_queue(struct tty_port *port, int ch)
46{ 46{
47 struct tty_struct *tty = tty_port_tty_get(port);
48 if (!tty)
49 return;
47 tty_insert_flip_char(tty, ch, 0); 50 tty_insert_flip_char(tty, ch, 0);
48 tty_schedule_flip(tty); 51 tty_schedule_flip(tty);
52 tty_kref_put(tty);
49} 53}
50 54
51static inline void 55static inline void
52kbd_puts_queue(struct tty_struct *tty, char *cp) 56kbd_puts_queue(struct tty_port *port, char *cp)
53{ 57{
58 struct tty_struct *tty = tty_port_tty_get(port);
59 if (!tty)
60 return;
54 while (*cp) 61 while (*cp)
55 tty_insert_flip_char(tty, *cp++, 0); 62 tty_insert_flip_char(tty, *cp++, 0);
56 tty_schedule_flip(tty); 63 tty_schedule_flip(tty);
64 tty_kref_put(tty);
57} 65}
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 1f4aff78eaca..10ec690197cb 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -61,7 +61,7 @@ struct tty3270_line {
61 */ 61 */
62struct tty3270 { 62struct tty3270 {
63 struct raw3270_view view; 63 struct raw3270_view view;
64 struct tty_struct *tty; /* Pointer to tty structure */ 64 struct tty_port port;
65 void **freemem_pages; /* Array of pages used for freemem. */ 65 void **freemem_pages; /* Array of pages used for freemem. */
66 struct list_head freemem; /* List of free memory for strings. */ 66 struct list_head freemem; /* List of free memory for strings. */
67 67
@@ -449,10 +449,9 @@ tty3270_rcl_add(struct tty3270 *tp, char *input, int len)
449static void 449static void
450tty3270_rcl_backward(struct kbd_data *kbd) 450tty3270_rcl_backward(struct kbd_data *kbd)
451{ 451{
452 struct tty3270 *tp; 452 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
453 struct string *s; 453 struct string *s;
454 454
455 tp = kbd->tty->driver_data;
456 spin_lock_bh(&tp->view.lock); 455 spin_lock_bh(&tp->view.lock);
457 if (tp->inattr == TF_INPUT) { 456 if (tp->inattr == TF_INPUT) {
458 if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines) 457 if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines)
@@ -477,9 +476,8 @@ tty3270_rcl_backward(struct kbd_data *kbd)
477static void 476static void
478tty3270_exit_tty(struct kbd_data *kbd) 477tty3270_exit_tty(struct kbd_data *kbd)
479{ 478{
480 struct tty3270 *tp; 479 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
481 480
482 tp = kbd->tty->driver_data;
483 raw3270_deactivate_view(&tp->view); 481 raw3270_deactivate_view(&tp->view);
484} 482}
485 483
@@ -489,10 +487,9 @@ tty3270_exit_tty(struct kbd_data *kbd)
489static void 487static void
490tty3270_scroll_forward(struct kbd_data *kbd) 488tty3270_scroll_forward(struct kbd_data *kbd)
491{ 489{
492 struct tty3270 *tp; 490 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
493 int nr_up; 491 int nr_up;
494 492
495 tp = kbd->tty->driver_data;
496 spin_lock_bh(&tp->view.lock); 493 spin_lock_bh(&tp->view.lock);
497 nr_up = tp->nr_up - tp->view.rows + 2; 494 nr_up = tp->nr_up - tp->view.rows + 2;
498 if (nr_up < 0) 495 if (nr_up < 0)
@@ -512,10 +509,9 @@ tty3270_scroll_forward(struct kbd_data *kbd)
512static void 509static void
513tty3270_scroll_backward(struct kbd_data *kbd) 510tty3270_scroll_backward(struct kbd_data *kbd)
514{ 511{
515 struct tty3270 *tp; 512 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
516 int nr_up; 513 int nr_up;
517 514
518 tp = kbd->tty->driver_data;
519 spin_lock_bh(&tp->view.lock); 515 spin_lock_bh(&tp->view.lock);
520 nr_up = tp->nr_up + tp->view.rows - 2; 516 nr_up = tp->nr_up + tp->view.rows - 2;
521 if (nr_up + tp->view.rows - 2 > tp->nr_lines) 517 if (nr_up + tp->view.rows - 2 > tp->nr_lines)
@@ -575,13 +571,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
575 raw3270_request_add_data(tp->kreset, &kreset_data, 1); 571 raw3270_request_add_data(tp->kreset, &kreset_data, 1);
576 raw3270_start(&tp->view, tp->kreset); 572 raw3270_start(&tp->view, tp->kreset);
577 573
578 /* Emit input string. */ 574 while (len-- > 0)
579 if (tp->tty) { 575 kbd_keycode(tp->kbd, *input++);
580 while (len-- > 0) 576 /* Emit keycode for AID byte. */
581 kbd_keycode(tp->kbd, *input++); 577 kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
582 /* Emit keycode for AID byte. */
583 kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
584 }
585 578
586 raw3270_request_reset(rrq); 579 raw3270_request_reset(rrq);
587 xchg(&tp->read, rrq); 580 xchg(&tp->read, rrq);
@@ -691,6 +684,7 @@ tty3270_alloc_view(void)
691 INIT_LIST_HEAD(&tp->update); 684 INIT_LIST_HEAD(&tp->update);
692 INIT_LIST_HEAD(&tp->rcl_lines); 685 INIT_LIST_HEAD(&tp->rcl_lines);
693 tp->rcl_max = 20; 686 tp->rcl_max = 20;
687 tty_port_init(&tp->port);
694 setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update, 688 setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
695 (unsigned long) tp); 689 (unsigned long) tp);
696 tasklet_init(&tp->readlet, 690 tasklet_init(&tp->readlet,
@@ -802,14 +796,14 @@ static void
802tty3270_release(struct raw3270_view *view) 796tty3270_release(struct raw3270_view *view)
803{ 797{
804 struct tty3270 *tp = container_of(view, struct tty3270, view); 798 struct tty3270 *tp = container_of(view, struct tty3270, view);
805 struct tty_struct *tty; 799 struct tty_struct *tty = tty_port_tty_get(&tp->port);
806 800
807 tty = tp->tty;
808 if (tty) { 801 if (tty) {
809 tty->driver_data = NULL; 802 tty->driver_data = NULL;
810 tp->tty = tp->kbd->tty = NULL; 803 tty_port_tty_set(&tp->port, NULL);
811 tty_hangup(tty); 804 tty_hangup(tty);
812 raw3270_put_view(&tp->view); 805 raw3270_put_view(&tp->view);
806 tty_kref_put(tty);
813 } 807 }
814} 808}
815 809
@@ -869,8 +863,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
869 tty->winsize.ws_row = tp->view.rows - 2; 863 tty->winsize.ws_row = tp->view.rows - 2;
870 tty->winsize.ws_col = tp->view.cols; 864 tty->winsize.ws_col = tp->view.cols;
871 tty->low_latency = 0; 865 tty->low_latency = 0;
872 tp->tty = tty; 866 /* why to reassign? */
873 tp->kbd->tty = tty; 867 tty_port_tty_set(&tp->port, tty);
874 tp->inattr = TF_INPUT; 868 tp->inattr = TF_INPUT;
875 return 0; 869 return 0;
876 } 870 }
@@ -900,7 +894,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
900 return rc; 894 return rc;
901 } 895 }
902 896
903 tp->tty = tty; 897 tty_port_tty_set(&tp->port, tty);
904 tty->low_latency = 0; 898 tty->low_latency = 0;
905 tty->driver_data = tp; 899 tty->driver_data = tp;
906 tty->winsize.ws_row = tp->view.rows - 2; 900 tty->winsize.ws_row = tp->view.rows - 2;
@@ -914,7 +908,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
914 for (i = 0; i < tp->view.rows - 2; i++) 908 for (i = 0; i < tp->view.rows - 2; i++)
915 tty3270_blank_line(tp); 909 tty3270_blank_line(tp);
916 910
917 tp->kbd->tty = tty; 911 tp->kbd->port = &tp->port;
918 tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty; 912 tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty;
919 tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward; 913 tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward;
920 tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward; 914 tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward;
@@ -938,7 +932,7 @@ tty3270_close(struct tty_struct *tty, struct file * filp)
938 return; 932 return;
939 if (tp) { 933 if (tp) {
940 tty->driver_data = NULL; 934 tty->driver_data = NULL;
941 tp->tty = tp->kbd->tty = NULL; 935 tty_port_tty_set(&tp->port, NULL);
942 raw3270_put_view(&tp->view); 936 raw3270_put_view(&tp->view);
943 } 937 }
944} 938}
@@ -1387,7 +1381,7 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
1387 tty3270_lf(tp); 1381 tty3270_lf(tp);
1388 break; 1382 break;
1389 case 'Z': /* Respond ID. */ 1383 case 'Z': /* Respond ID. */
1390 kbd_puts_queue(tp->tty, "\033[?6c"); 1384 kbd_puts_queue(&tp->port, "\033[?6c");
1391 break; 1385 break;
1392 case '7': /* Save cursor position. */ 1386 case '7': /* Save cursor position. */
1393 tp->saved_cx = tp->cx; 1387 tp->saved_cx = tp->cx;
@@ -1433,11 +1427,11 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
1433 tp->esc_state = ESnormal; 1427 tp->esc_state = ESnormal;
1434 if (ch == 'n' && !tp->esc_ques) { 1428 if (ch == 'n' && !tp->esc_ques) {
1435 if (tp->esc_par[0] == 5) /* Status report. */ 1429 if (tp->esc_par[0] == 5) /* Status report. */
1436 kbd_puts_queue(tp->tty, "\033[0n"); 1430 kbd_puts_queue(&tp->port, "\033[0n");
1437 else if (tp->esc_par[0] == 6) { /* Cursor report. */ 1431 else if (tp->esc_par[0] == 6) { /* Cursor report. */
1438 char buf[40]; 1432 char buf[40];
1439 sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1); 1433 sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1);
1440 kbd_puts_queue(tp->tty, buf); 1434 kbd_puts_queue(&tp->port, buf);
1441 } 1435 }
1442 return; 1436 return;
1443 } 1437 }