diff options
author | Jiri Slaby <jslaby@suse.cz> | 2012-04-02 07:54:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-09 14:28:17 -0400 |
commit | ba186e7d17ea874f2a56385806e0ef213f58a1dd (patch) | |
tree | 02d5ab7bd13f43fbe12c6d7c7c8452e8788665a5 /drivers/s390 | |
parent | 20acdfa85c1c0292ee710335900dc04aa7b634a3 (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.c | 30 | ||||
-rw-r--r-- | drivers/s390/char/keyboard.h | 14 | ||||
-rw-r--r-- | drivers/s390/char/tty3270.c | 48 |
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 | |||
239 | k_fn(struct kbd_data *kbd, unsigned char value) | 239 | k_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 | ||
245 | static void | 245 | static 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 | */ |
259 | static void | 259 | static void |
260 | to_utf8(struct tty_struct *tty, ushort c) | 260 | to_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 | ||
458 | 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) |
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 | ||
23 | struct kbd_data { | 23 | struct 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 | */ |
44 | static inline void | 44 | static inline void |
45 | kbd_put_queue(struct tty_struct *tty, int ch) | 45 | kbd_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 | ||
51 | static inline void | 55 | static inline void |
52 | kbd_puts_queue(struct tty_struct *tty, char *cp) | 56 | kbd_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 | */ |
62 | struct tty3270 { | 62 | struct 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) | |||
449 | static void | 449 | static void |
450 | tty3270_rcl_backward(struct kbd_data *kbd) | 450 | tty3270_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) | |||
477 | static void | 476 | static void |
478 | tty3270_exit_tty(struct kbd_data *kbd) | 477 | tty3270_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) | |||
489 | static void | 487 | static void |
490 | tty3270_scroll_forward(struct kbd_data *kbd) | 488 | tty3270_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) | |||
512 | static void | 509 | static void |
513 | tty3270_scroll_backward(struct kbd_data *kbd) | 510 | tty3270_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 | |||
802 | tty3270_release(struct raw3270_view *view) | 796 | tty3270_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 | } |