From cc4f02486c09977ccbe3ce2276aca5608a44ca00 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 11 Mar 2013 10:03:42 +0100 Subject: um: Use tty_port_operations->destruct As we setup the SIGWINCH handler in tty_port_operations->activate it makes sense to tear down it in ->destruct. Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index f1b38571f94e..232243aec70c 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -315,8 +315,22 @@ static int line_activate(struct tty_port *port, struct tty_struct *tty) return 0; } +static void unregister_winch(struct tty_struct *tty); + +static void line_destruct(struct tty_port *port) +{ + struct tty_struct *tty = tty_port_tty_get(port); + struct line *line = tty->driver_data; + + if (line->sigio) { + unregister_winch(tty); + line->sigio = 0; + } +} + static const struct tty_port_operations line_port_ops = { .activate = line_activate, + .destruct = line_destruct, }; int line_open(struct tty_struct *tty, struct file *filp) @@ -340,18 +354,6 @@ int line_install(struct tty_driver *driver, struct tty_struct *tty, return 0; } -static void unregister_winch(struct tty_struct *tty); - -void line_cleanup(struct tty_struct *tty) -{ - struct line *line = tty->driver_data; - - if (line->sigio) { - unregister_winch(tty); - line->sigio = 0; - } -} - void line_close(struct tty_struct *tty, struct file * filp) { struct line *line = tty->driver_data; -- cgit v1.2.3 From 2116bda6ad937d7acb6e2316fd9e65ad6ca01d42 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 11 Mar 2013 10:05:45 +0100 Subject: um: Use tty_port in SIGWINCH handler The tty below tty_port might get destroyed by the tty layer while we hold a reference to it. So we have to carry tty_port around... Signed-off-by: Richard Weinberger --- arch/um/drivers/chan.h | 2 +- arch/um/drivers/chan_kern.c | 4 ++-- arch/um/drivers/chan_user.c | 12 ++++++------ arch/um/drivers/chan_user.h | 6 +++--- arch/um/drivers/line.c | 16 ++++++++++------ 5 files changed, 22 insertions(+), 18 deletions(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/chan.h b/arch/um/drivers/chan.h index 78f1b8999964..c512b0306dd4 100644 --- a/arch/um/drivers/chan.h +++ b/arch/um/drivers/chan.h @@ -37,7 +37,7 @@ extern int console_write_chan(struct chan *chan, const char *buf, extern int console_open_chan(struct line *line, struct console *co); extern void deactivate_chan(struct chan *chan, int irq); extern void reactivate_chan(struct chan *chan, int irq); -extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty); +extern void chan_enable_winch(struct chan *chan, struct tty_port *port); extern int enable_chan(struct line *line); extern void close_chan(struct line *line); extern int chan_window_size(struct line *line, diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 15c553c239a1..80b47cb71e0a 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -122,10 +122,10 @@ static int open_chan(struct list_head *chans) return err; } -void chan_enable_winch(struct chan *chan, struct tty_struct *tty) +void chan_enable_winch(struct chan *chan, struct tty_port *port) { if (chan && chan->primary && chan->ops->winch) - register_winch(chan->fd, tty); + register_winch(chan->fd, port); } static void line_timer_cb(struct work_struct *work) diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 9be670ad23b5..3fd7c3efdb18 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -216,7 +216,7 @@ static int winch_thread(void *arg) } } -static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, +static int winch_tramp(int fd, struct tty_port *port, int *fd_out, unsigned long *stack_out) { struct winch_data data; @@ -271,7 +271,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, return err; } -void register_winch(int fd, struct tty_struct *tty) +void register_winch(int fd, struct tty_port *port) { unsigned long stack; int pid, thread, count, thread_fd = -1; @@ -281,17 +281,17 @@ void register_winch(int fd, struct tty_struct *tty) return; pid = tcgetpgrp(fd); - if (is_skas_winch(pid, fd, tty)) { - register_winch_irq(-1, fd, -1, tty, 0); + if (is_skas_winch(pid, fd, port)) { + register_winch_irq(-1, fd, -1, port, 0); return; } if (pid == -1) { - thread = winch_tramp(fd, tty, &thread_fd, &stack); + thread = winch_tramp(fd, port, &thread_fd, &stack); if (thread < 0) return; - register_winch_irq(thread_fd, fd, thread, tty, stack); + register_winch_irq(thread_fd, fd, thread, port, stack); count = write(thread_fd, &c, sizeof(c)); if (count != sizeof(c)) diff --git a/arch/um/drivers/chan_user.h b/arch/um/drivers/chan_user.h index dc693298eb8f..03f1b565c5f9 100644 --- a/arch/um/drivers/chan_user.h +++ b/arch/um/drivers/chan_user.h @@ -38,10 +38,10 @@ extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, unsigned short *cols_out); extern void generic_free(void *data); -struct tty_struct; -extern void register_winch(int fd, struct tty_struct *tty); +struct tty_port; +extern void register_winch(int fd, struct tty_port *port); extern void register_winch_irq(int fd, int tty_fd, int pid, - struct tty_struct *tty, unsigned long stack); + struct tty_port *port, unsigned long stack); #define __channel_help(fn, prefix) \ __uml_help(fn, prefix "[0-9]*=\n" \ diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 232243aec70c..be541cf69fd2 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -305,7 +305,7 @@ static int line_activate(struct tty_port *port, struct tty_struct *tty) return ret; if (!line->sigio) { - chan_enable_winch(line->chan_out, tty); + chan_enable_winch(line->chan_out, port); line->sigio = 1; } @@ -603,7 +603,7 @@ struct winch { int fd; int tty_fd; int pid; - struct tty_struct *tty; + struct tty_port *port; unsigned long stack; struct work_struct work; }; @@ -657,7 +657,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) goto out; } } - tty = winch->tty; + tty = tty_port_tty_get(winch->port); if (tty != NULL) { line = tty->driver_data; if (line != NULL) { @@ -665,6 +665,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) &tty->winsize.ws_col); kill_pgrp(tty->pgrp, SIGWINCH, 1); } + tty_kref_put(tty); } out: if (winch->fd != -1) @@ -672,7 +673,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) return IRQ_HANDLED; } -void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, +void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port, unsigned long stack) { struct winch *winch; @@ -687,7 +688,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, .fd = fd, .tty_fd = tty_fd, .pid = pid, - .tty = tty, + .port = port, .stack = stack }); if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, @@ -716,15 +717,18 @@ static void unregister_winch(struct tty_struct *tty) { struct list_head *ele, *next; struct winch *winch; + struct tty_struct *wtty; spin_lock(&winch_handler_lock); list_for_each_safe(ele, next, &winch_handlers) { winch = list_entry(ele, struct winch, list); - if (winch->tty == tty) { + wtty = tty_port_tty_get(winch->port); + if (wtty == tty) { free_winch(winch); break; } + tty_kref_put(wtty); } spin_unlock(&winch_handler_lock); } -- cgit v1.2.3