Commit ba186e7d authored by Jiri Slaby's avatar Jiri Slaby Committed by Greg Kroah-Hartman

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: default avatarJiri 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: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 20acdfa8
...@@ -199,7 +199,7 @@ handle_diacr(struct kbd_data *kbd, unsigned int ch) ...@@ -199,7 +199,7 @@ handle_diacr(struct kbd_data *kbd, unsigned int ch)
if (ch == ' ' || ch == d) if (ch == ' ' || ch == d)
return d; return d;
kbd_put_queue(kbd->tty, d); kbd_put_queue(kbd->port, d);
return ch; return ch;
} }
...@@ -221,7 +221,7 @@ k_self(struct kbd_data *kbd, unsigned char value) ...@@ -221,7 +221,7 @@ k_self(struct kbd_data *kbd, unsigned char value)
{ {
if (kbd->diacr) if (kbd->diacr)
value = handle_diacr(kbd, value); value = handle_diacr(kbd, value);
kbd_put_queue(kbd->tty, value); kbd_put_queue(kbd->port, value);
} }
/* /*
...@@ -239,7 +239,7 @@ static void ...@@ -239,7 +239,7 @@ static void
k_fn(struct kbd_data *kbd, unsigned char value) k_fn(struct kbd_data *kbd, unsigned char value)
{ {
if (kbd->func_table[value]) if (kbd->func_table[value])
kbd_puts_queue(kbd->tty, kbd->func_table[value]); kbd_puts_queue(kbd->port, kbd->func_table[value]);
} }
static void static void
...@@ -257,20 +257,20 @@ k_spec(struct kbd_data *kbd, unsigned char value) ...@@ -257,20 +257,20 @@ k_spec(struct kbd_data *kbd, unsigned char value)
* but we need only 16 bits here * but we need only 16 bits here
*/ */
static void static void
to_utf8(struct tty_struct *tty, ushort c) to_utf8(struct tty_port *port, ushort c)
{ {
if (c < 0x80) if (c < 0x80)
/* 0******* */ /* 0******* */
kbd_put_queue(tty, c); kbd_put_queue(port, c);
else if (c < 0x800) { else if (c < 0x800) {
/* 110***** 10****** */ /* 110***** 10****** */
kbd_put_queue(tty, 0xc0 | (c >> 6)); kbd_put_queue(port, 0xc0 | (c >> 6));
kbd_put_queue(tty, 0x80 | (c & 0x3f)); kbd_put_queue(port, 0x80 | (c & 0x3f));
} else { } else {
/* 1110**** 10****** 10****** */ /* 1110**** 10****** 10****** */
kbd_put_queue(tty, 0xe0 | (c >> 12)); kbd_put_queue(port, 0xe0 | (c >> 12));
kbd_put_queue(tty, 0x80 | ((c >> 6) & 0x3f)); kbd_put_queue(port, 0x80 | ((c >> 6) & 0x3f));
kbd_put_queue(tty, 0x80 | (c & 0x3f)); kbd_put_queue(port, 0x80 | (c & 0x3f));
} }
} }
...@@ -283,7 +283,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode) ...@@ -283,7 +283,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
unsigned short keysym; unsigned short keysym;
unsigned char type, value; unsigned char type, value;
if (!kbd || !kbd->tty) if (!kbd)
return; return;
if (keycode >= 384) if (keycode >= 384)
...@@ -323,7 +323,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode) ...@@ -323,7 +323,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
#endif #endif
(*k_handler[type])(kbd, value); (*k_handler[type])(kbd, value);
} else } else
to_utf8(kbd->tty, keysym); to_utf8(kbd->port, keysym);
} }
/* /*
...@@ -457,6 +457,7 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs, ...@@ -457,6 +457,7 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs,
int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg) int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
{ {
struct tty_struct *tty;
void __user *argp; void __user *argp;
unsigned int ct; unsigned int ct;
int perm; int perm;
...@@ -467,7 +468,10 @@ int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg) ...@@ -467,7 +468,10 @@ int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
* To have permissions to do most of the vt ioctls, we either have * To have permissions to do most of the vt ioctls, we either have
* to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
*/ */
perm = current->signal->tty == kbd->tty || capable(CAP_SYS_TTY_CONFIG); tty = tty_port_tty_get(kbd->port);
/* FIXME this test is pretty racy */
perm = current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG);
tty_kref_put(tty);
switch (cmd) { switch (cmd) {
case KDGKBTYPE: case KDGKBTYPE:
return put_user(KB_101, (char __user *)argp); return put_user(KB_101, (char __user *)argp);
......
...@@ -21,7 +21,7 @@ typedef void (fn_handler_fn)(struct kbd_data *); ...@@ -21,7 +21,7 @@ typedef void (fn_handler_fn)(struct kbd_data *);
*/ */
struct kbd_data { struct kbd_data {
struct tty_struct *tty; struct tty_port *port;
unsigned short **key_maps; unsigned short **key_maps;
char **func_table; char **func_table;
fn_handler_fn **fn_handler; fn_handler_fn **fn_handler;
...@@ -42,16 +42,24 @@ int kbd_ioctl(struct kbd_data *, unsigned int, unsigned long); ...@@ -42,16 +42,24 @@ int kbd_ioctl(struct kbd_data *, unsigned int, unsigned long);
* Helper Functions. * Helper Functions.
*/ */
static inline void static inline void
kbd_put_queue(struct tty_struct *tty, int ch) kbd_put_queue(struct tty_port *port, int ch)
{ {
struct tty_struct *tty = tty_port_tty_get(port);
if (!tty)
return;
tty_insert_flip_char(tty, ch, 0); tty_insert_flip_char(tty, ch, 0);
tty_schedule_flip(tty); tty_schedule_flip(tty);
tty_kref_put(tty);
} }
static inline void static inline void
kbd_puts_queue(struct tty_struct *tty, char *cp) kbd_puts_queue(struct tty_port *port, char *cp)
{ {
struct tty_struct *tty = tty_port_tty_get(port);
if (!tty)
return;
while (*cp) while (*cp)
tty_insert_flip_char(tty, *cp++, 0); tty_insert_flip_char(tty, *cp++, 0);
tty_schedule_flip(tty); tty_schedule_flip(tty);
tty_kref_put(tty);
} }
...@@ -61,7 +61,7 @@ struct tty3270_line { ...@@ -61,7 +61,7 @@ struct tty3270_line {
*/ */
struct tty3270 { struct tty3270 {
struct raw3270_view view; struct raw3270_view view;
struct tty_struct *tty; /* Pointer to tty structure */ struct tty_port port;
void **freemem_pages; /* Array of pages used for freemem. */ void **freemem_pages; /* Array of pages used for freemem. */
struct list_head freemem; /* List of free memory for strings. */ struct list_head freemem; /* List of free memory for strings. */
...@@ -449,10 +449,9 @@ tty3270_rcl_add(struct tty3270 *tp, char *input, int len) ...@@ -449,10 +449,9 @@ tty3270_rcl_add(struct tty3270 *tp, char *input, int len)
static void static void
tty3270_rcl_backward(struct kbd_data *kbd) tty3270_rcl_backward(struct kbd_data *kbd)
{ {
struct tty3270 *tp; struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
struct string *s; struct string *s;
tp = kbd->tty->driver_data;
spin_lock_bh(&tp->view.lock); spin_lock_bh(&tp->view.lock);
if (tp->inattr == TF_INPUT) { if (tp->inattr == TF_INPUT) {
if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines) if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines)
...@@ -477,9 +476,8 @@ tty3270_rcl_backward(struct kbd_data *kbd) ...@@ -477,9 +476,8 @@ tty3270_rcl_backward(struct kbd_data *kbd)
static void static void
tty3270_exit_tty(struct kbd_data *kbd) tty3270_exit_tty(struct kbd_data *kbd)
{ {
struct tty3270 *tp; struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
tp = kbd->tty->driver_data;
raw3270_deactivate_view(&tp->view); raw3270_deactivate_view(&tp->view);
} }
...@@ -489,10 +487,9 @@ tty3270_exit_tty(struct kbd_data *kbd) ...@@ -489,10 +487,9 @@ tty3270_exit_tty(struct kbd_data *kbd)
static void static void
tty3270_scroll_forward(struct kbd_data *kbd) tty3270_scroll_forward(struct kbd_data *kbd)
{ {
struct tty3270 *tp; struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
int nr_up; int nr_up;
tp = kbd->tty->driver_data;
spin_lock_bh(&tp->view.lock); spin_lock_bh(&tp->view.lock);
nr_up = tp->nr_up - tp->view.rows + 2; nr_up = tp->nr_up - tp->view.rows + 2;
if (nr_up < 0) if (nr_up < 0)
...@@ -512,10 +509,9 @@ tty3270_scroll_forward(struct kbd_data *kbd) ...@@ -512,10 +509,9 @@ tty3270_scroll_forward(struct kbd_data *kbd)
static void static void
tty3270_scroll_backward(struct kbd_data *kbd) tty3270_scroll_backward(struct kbd_data *kbd)
{ {
struct tty3270 *tp; struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
int nr_up; int nr_up;
tp = kbd->tty->driver_data;
spin_lock_bh(&tp->view.lock); spin_lock_bh(&tp->view.lock);
nr_up = tp->nr_up + tp->view.rows - 2; nr_up = tp->nr_up + tp->view.rows - 2;
if (nr_up + tp->view.rows - 2 > tp->nr_lines) if (nr_up + tp->view.rows - 2 > tp->nr_lines)
...@@ -575,13 +571,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq) ...@@ -575,13 +571,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
raw3270_request_add_data(tp->kreset, &kreset_data, 1); raw3270_request_add_data(tp->kreset, &kreset_data, 1);
raw3270_start(&tp->view, tp->kreset); raw3270_start(&tp->view, tp->kreset);
/* Emit input string. */ while (len-- > 0)
if (tp->tty) { kbd_keycode(tp->kbd, *input++);
while (len-- > 0) /* Emit keycode for AID byte. */
kbd_keycode(tp->kbd, *input++); kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
/* Emit keycode for AID byte. */
kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
}
raw3270_request_reset(rrq); raw3270_request_reset(rrq);
xchg(&tp->read, rrq); xchg(&tp->read, rrq);
...@@ -691,6 +684,7 @@ tty3270_alloc_view(void) ...@@ -691,6 +684,7 @@ tty3270_alloc_view(void)
INIT_LIST_HEAD(&tp->update); INIT_LIST_HEAD(&tp->update);
INIT_LIST_HEAD(&tp->rcl_lines); INIT_LIST_HEAD(&tp->rcl_lines);
tp->rcl_max = 20; tp->rcl_max = 20;
tty_port_init(&tp->port);
setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update, setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
(unsigned long) tp); (unsigned long) tp);
tasklet_init(&tp->readlet, tasklet_init(&tp->readlet,
...@@ -802,14 +796,14 @@ static void ...@@ -802,14 +796,14 @@ static void
tty3270_release(struct raw3270_view *view) tty3270_release(struct raw3270_view *view)
{ {
struct tty3270 *tp = container_of(view, struct tty3270, view); struct tty3270 *tp = container_of(view, struct tty3270, view);
struct tty_struct *tty; struct tty_struct *tty = tty_port_tty_get(&tp->port);
tty = tp->tty;
if (tty) { if (tty) {
tty->driver_data = NULL; tty->driver_data = NULL;
tp->tty = tp->kbd->tty = NULL; tty_port_tty_set(&tp->port, NULL);
tty_hangup(tty); tty_hangup(tty);
raw3270_put_view(&tp->view); raw3270_put_view(&tp->view);
tty_kref_put(tty);
} }
} }
...@@ -869,8 +863,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp) ...@@ -869,8 +863,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
tty->winsize.ws_row = tp->view.rows - 2; tty->winsize.ws_row = tp->view.rows - 2;
tty->winsize.ws_col = tp->view.cols; tty->winsize.ws_col = tp->view.cols;
tty->low_latency = 0; tty->low_latency = 0;
tp->tty = tty; /* why to reassign? */
tp->kbd->tty = tty; tty_port_tty_set(&tp->port, tty);
tp->inattr = TF_INPUT; tp->inattr = TF_INPUT;
return 0; return 0;
} }
...@@ -900,7 +894,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp) ...@@ -900,7 +894,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
return rc; return rc;
} }
tp->tty = tty; tty_port_tty_set(&tp->port, tty);
tty->low_latency = 0; tty->low_latency = 0;
tty->driver_data = tp; tty->driver_data = tp;
tty->winsize.ws_row = tp->view.rows - 2; tty->winsize.ws_row = tp->view.rows - 2;
...@@ -914,7 +908,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp) ...@@ -914,7 +908,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
for (i = 0; i < tp->view.rows - 2; i++) for (i = 0; i < tp->view.rows - 2; i++)
tty3270_blank_line(tp); tty3270_blank_line(tp);
tp->kbd->tty = tty; tp->kbd->port = &tp->port;
tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty; tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty;
tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward; tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward;
tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward; tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward;
...@@ -938,7 +932,7 @@ tty3270_close(struct tty_struct *tty, struct file * filp) ...@@ -938,7 +932,7 @@ tty3270_close(struct tty_struct *tty, struct file * filp)
return; return;
if (tp) { if (tp) {
tty->driver_data = NULL; tty->driver_data = NULL;
tp->tty = tp->kbd->tty = NULL; tty_port_tty_set(&tp->port, NULL);
raw3270_put_view(&tp->view); raw3270_put_view(&tp->view);
} }
} }
...@@ -1387,7 +1381,7 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch) ...@@ -1387,7 +1381,7 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
tty3270_lf(tp); tty3270_lf(tp);
break; break;
case 'Z': /* Respond ID. */ case 'Z': /* Respond ID. */
kbd_puts_queue(tp->tty, "\033[?6c"); kbd_puts_queue(&tp->port, "\033[?6c");
break; break;
case '7': /* Save cursor position. */ case '7': /* Save cursor position. */
tp->saved_cx = tp->cx; tp->saved_cx = tp->cx;
...@@ -1433,11 +1427,11 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch) ...@@ -1433,11 +1427,11 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
tp->esc_state = ESnormal; tp->esc_state = ESnormal;
if (ch == 'n' && !tp->esc_ques) { if (ch == 'n' && !tp->esc_ques) {
if (tp->esc_par[0] == 5) /* Status report. */ if (tp->esc_par[0] == 5) /* Status report. */
kbd_puts_queue(tp->tty, "\033[0n"); kbd_puts_queue(&tp->port, "\033[0n");
else if (tp->esc_par[0] == 6) { /* Cursor report. */ else if (tp->esc_par[0] == 6) { /* Cursor report. */
char buf[40]; char buf[40];
sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1); sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1);
kbd_puts_queue(tp->tty, buf); kbd_puts_queue(&tp->port, buf);
} }
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment