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>
This commit is contained in:
Jiri Slaby 2012-04-02 13:54:18 +02:00 committed by Greg Kroah-Hartman
parent 20acdfa85c
commit ba186e7d17
3 changed files with 49 additions and 43 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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]);
}
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;
}