Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+17 −13
Original line number Diff line number Diff line
@@ -199,7 +199,7 @@ handle_diacr(struct kbd_data *kbd, unsigned int ch)
	if (ch == ' ' || ch == d)
		return d;

	kbd_put_queue(kbd->tty, d);
	kbd_put_queue(kbd->port, d);
	return ch;
}

@@ -221,7 +221,7 @@ k_self(struct kbd_data *kbd, unsigned char value)
{
	if (kbd->diacr)
		value = handle_diacr(kbd, value);
	kbd_put_queue(kbd->tty, value);
	kbd_put_queue(kbd->port, value);
}

/*
@@ -239,7 +239,7 @@ static void
k_fn(struct kbd_data *kbd, unsigned char 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
@@ -257,20 +257,20 @@ k_spec(struct kbd_data *kbd, unsigned char value)
 * but we need only 16 bits here
 */
static void
to_utf8(struct tty_struct *tty, ushort c) 
to_utf8(struct tty_port *port, ushort c)
{
	if (c < 0x80)
		/*  0******* */
		kbd_put_queue(tty, c);
		kbd_put_queue(port, c);
	else if (c < 0x800) {
		/* 110***** 10****** */
		kbd_put_queue(tty, 0xc0 | (c >> 6));
		kbd_put_queue(tty, 0x80 | (c & 0x3f));
		kbd_put_queue(port, 0xc0 | (c >> 6));
		kbd_put_queue(port, 0x80 | (c & 0x3f));
	} else {
		/* 1110**** 10****** 10****** */
		kbd_put_queue(tty, 0xe0 | (c >> 12));
		kbd_put_queue(tty, 0x80 | ((c >> 6) & 0x3f));
		kbd_put_queue(tty, 0x80 | (c & 0x3f));
		kbd_put_queue(port, 0xe0 | (c >> 12));
		kbd_put_queue(port, 0x80 | ((c >> 6) & 0x3f));
		kbd_put_queue(port, 0x80 | (c & 0x3f));
	}
}

@@ -283,7 +283,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
	unsigned short keysym;
	unsigned char type, value;

	if (!kbd || !kbd->tty)
	if (!kbd)
		return;

	if (keycode >= 384)
@@ -323,7 +323,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
#endif
		(*k_handler[type])(kbd, value);
	} 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,

int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
{
	struct tty_struct *tty;
	void __user *argp;
	unsigned int ct;
	int perm;
@@ -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 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) {
	case KDGKBTYPE:
		return put_user(KB_101, (char __user *)argp);
+11 −3
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ typedef void (fn_handler_fn)(struct kbd_data *);
 */

struct kbd_data {
	struct tty_struct *tty;
	struct tty_port *port;
	unsigned short **key_maps;
	char **func_table;
	fn_handler_fn **fn_handler;
@@ -42,16 +42,24 @@ int kbd_ioctl(struct kbd_data *, unsigned int, unsigned long);
 * Helper Functions.
 */
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_schedule_flip(tty);
	tty_kref_put(tty);
}

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)
		tty_insert_flip_char(tty, *cp++, 0);
	tty_schedule_flip(tty);
	tty_kref_put(tty);
}
+21 −27
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ struct tty3270_line {
 */
struct tty3270 {
	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. */
	struct list_head freemem;	/* List of free memory for strings. */

@@ -449,10 +449,9 @@ tty3270_rcl_add(struct tty3270 *tp, char *input, int len)
static void
tty3270_rcl_backward(struct kbd_data *kbd)
{
	struct tty3270 *tp;
	struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
	struct string *s;

	tp = kbd->tty->driver_data;
	spin_lock_bh(&tp->view.lock);
	if (tp->inattr == TF_INPUT) {
		if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines)
@@ -477,9 +476,8 @@ tty3270_rcl_backward(struct kbd_data *kbd)
static void
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);
}

@@ -489,10 +487,9 @@ tty3270_exit_tty(struct kbd_data *kbd)
static void
tty3270_scroll_forward(struct kbd_data *kbd)
{
	struct tty3270 *tp;
	struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
	int nr_up;

	tp = kbd->tty->driver_data;
	spin_lock_bh(&tp->view.lock);
	nr_up = tp->nr_up - tp->view.rows + 2;
	if (nr_up < 0)
@@ -512,10 +509,9 @@ tty3270_scroll_forward(struct kbd_data *kbd)
static void
tty3270_scroll_backward(struct kbd_data *kbd)
{
	struct tty3270 *tp;
	struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
	int nr_up;

	tp = kbd->tty->driver_data;
	spin_lock_bh(&tp->view.lock);
	nr_up = tp->nr_up + tp->view.rows - 2;
	if (nr_up + tp->view.rows - 2 > tp->nr_lines)
@@ -575,13 +571,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
	raw3270_request_add_data(tp->kreset, &kreset_data, 1);
	raw3270_start(&tp->view, tp->kreset);

	/* Emit input string. */
	if (tp->tty) {
	while (len-- > 0)
		kbd_keycode(tp->kbd, *input++);
	/* Emit keycode for AID byte. */
	kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
	}

	raw3270_request_reset(rrq);
	xchg(&tp->read, rrq);
@@ -691,6 +684,7 @@ tty3270_alloc_view(void)
	INIT_LIST_HEAD(&tp->update);
	INIT_LIST_HEAD(&tp->rcl_lines);
	tp->rcl_max = 20;
	tty_port_init(&tp->port);
	setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
		    (unsigned long) tp);
	tasklet_init(&tp->readlet,
@@ -802,14 +796,14 @@ static void
tty3270_release(struct raw3270_view *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) {
		tty->driver_data = NULL;
		tp->tty = tp->kbd->tty = NULL;
		tty_port_tty_set(&tp->port, NULL);
		tty_hangup(tty);
		raw3270_put_view(&tp->view);
		tty_kref_put(tty);
	}
}

@@ -869,8 +863,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
		tty->winsize.ws_row = tp->view.rows - 2;
		tty->winsize.ws_col = tp->view.cols;
		tty->low_latency = 0;
		tp->tty = tty;
		tp->kbd->tty = tty;
		/* why to reassign? */
		tty_port_tty_set(&tp->port, tty);
		tp->inattr = TF_INPUT;
		return 0;
	}
@@ -900,7 +894,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
		return rc;
	}

	tp->tty = tty;
	tty_port_tty_set(&tp->port, tty);
	tty->low_latency = 0;
	tty->driver_data = tp;
	tty->winsize.ws_row = tp->view.rows - 2;
@@ -914,7 +908,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
	for (i = 0; i < tp->view.rows - 2; i++)
		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_SCROLLBACK)] = tty3270_scroll_backward;
	tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward;
@@ -938,7 +932,7 @@ tty3270_close(struct tty_struct *tty, struct file * filp)
		return;
	if (tp) {
		tty->driver_data = NULL;
		tp->tty = tp->kbd->tty = NULL;
		tty_port_tty_set(&tp->port, NULL);
		raw3270_put_view(&tp->view);
	}
}
@@ -1387,7 +1381,7 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
			tty3270_lf(tp);
			break;
		case 'Z':		/* Respond ID. */
			kbd_puts_queue(tp->tty, "\033[?6c");
			kbd_puts_queue(&tp->port, "\033[?6c");
			break;
		case '7':		/* Save cursor position. */
			tp->saved_cx = tp->cx;
@@ -1433,11 +1427,11 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
	tp->esc_state = ESnormal;
	if (ch == 'n' && !tp->esc_ques) {
		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. */
			char buf[40];
			sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1);
			kbd_puts_queue(tp->tty, buf);
			kbd_puts_queue(&tp->port, buf);
		}
		return;
	}