aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2013-03-11 05:05:45 -0400
committerRichard Weinberger <richard@nod.at>2013-03-11 05:08:04 -0400
commit2116bda6ad937d7acb6e2316fd9e65ad6ca01d42 (patch)
treedc9b20f4bc76b335e8a395b4248f50ac2d3935dc /arch/um
parentcc4f02486c09977ccbe3ce2276aca5608a44ca00 (diff)
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 <richard@nod.at>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/drivers/chan.h2
-rw-r--r--arch/um/drivers/chan_kern.c4
-rw-r--r--arch/um/drivers/chan_user.c12
-rw-r--r--arch/um/drivers/chan_user.h6
-rw-r--r--arch/um/drivers/line.c16
5 files changed, 22 insertions, 18 deletions
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,
37extern int console_open_chan(struct line *line, struct console *co); 37extern int console_open_chan(struct line *line, struct console *co);
38extern void deactivate_chan(struct chan *chan, int irq); 38extern void deactivate_chan(struct chan *chan, int irq);
39extern void reactivate_chan(struct chan *chan, int irq); 39extern void reactivate_chan(struct chan *chan, int irq);
40extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty); 40extern void chan_enable_winch(struct chan *chan, struct tty_port *port);
41extern int enable_chan(struct line *line); 41extern int enable_chan(struct line *line);
42extern void close_chan(struct line *line); 42extern void close_chan(struct line *line);
43extern int chan_window_size(struct line *line, 43extern 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)
122 return err; 122 return err;
123} 123}
124 124
125void chan_enable_winch(struct chan *chan, struct tty_struct *tty) 125void chan_enable_winch(struct chan *chan, struct tty_port *port)
126{ 126{
127 if (chan && chan->primary && chan->ops->winch) 127 if (chan && chan->primary && chan->ops->winch)
128 register_winch(chan->fd, tty); 128 register_winch(chan->fd, port);
129} 129}
130 130
131static void line_timer_cb(struct work_struct *work) 131static 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)
216 } 216 }
217} 217}
218 218
219static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, 219static int winch_tramp(int fd, struct tty_port *port, int *fd_out,
220 unsigned long *stack_out) 220 unsigned long *stack_out)
221{ 221{
222 struct winch_data data; 222 struct winch_data data;
@@ -271,7 +271,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
271 return err; 271 return err;
272} 272}
273 273
274void register_winch(int fd, struct tty_struct *tty) 274void register_winch(int fd, struct tty_port *port)
275{ 275{
276 unsigned long stack; 276 unsigned long stack;
277 int pid, thread, count, thread_fd = -1; 277 int pid, thread, count, thread_fd = -1;
@@ -281,17 +281,17 @@ void register_winch(int fd, struct tty_struct *tty)
281 return; 281 return;
282 282
283 pid = tcgetpgrp(fd); 283 pid = tcgetpgrp(fd);
284 if (is_skas_winch(pid, fd, tty)) { 284 if (is_skas_winch(pid, fd, port)) {
285 register_winch_irq(-1, fd, -1, tty, 0); 285 register_winch_irq(-1, fd, -1, port, 0);
286 return; 286 return;
287 } 287 }
288 288
289 if (pid == -1) { 289 if (pid == -1) {
290 thread = winch_tramp(fd, tty, &thread_fd, &stack); 290 thread = winch_tramp(fd, port, &thread_fd, &stack);
291 if (thread < 0) 291 if (thread < 0)
292 return; 292 return;
293 293
294 register_winch_irq(thread_fd, fd, thread, tty, stack); 294 register_winch_irq(thread_fd, fd, thread, port, stack);
295 295
296 count = write(thread_fd, &c, sizeof(c)); 296 count = write(thread_fd, &c, sizeof(c));
297 if (count != sizeof(c)) 297 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,
38 unsigned short *cols_out); 38 unsigned short *cols_out);
39extern void generic_free(void *data); 39extern void generic_free(void *data);
40 40
41struct tty_struct; 41struct tty_port;
42extern void register_winch(int fd, struct tty_struct *tty); 42extern void register_winch(int fd, struct tty_port *port);
43extern void register_winch_irq(int fd, int tty_fd, int pid, 43extern void register_winch_irq(int fd, int tty_fd, int pid,
44 struct tty_struct *tty, unsigned long stack); 44 struct tty_port *port, unsigned long stack);
45 45
46#define __channel_help(fn, prefix) \ 46#define __channel_help(fn, prefix) \
47__uml_help(fn, prefix "[0-9]*=<channel description>\n" \ 47__uml_help(fn, prefix "[0-9]*=<channel description>\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)
305 return ret; 305 return ret;
306 306
307 if (!line->sigio) { 307 if (!line->sigio) {
308 chan_enable_winch(line->chan_out, tty); 308 chan_enable_winch(line->chan_out, port);
309 line->sigio = 1; 309 line->sigio = 1;
310 } 310 }
311 311
@@ -603,7 +603,7 @@ struct winch {
603 int fd; 603 int fd;
604 int tty_fd; 604 int tty_fd;
605 int pid; 605 int pid;
606 struct tty_struct *tty; 606 struct tty_port *port;
607 unsigned long stack; 607 unsigned long stack;
608 struct work_struct work; 608 struct work_struct work;
609}; 609};
@@ -657,7 +657,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
657 goto out; 657 goto out;
658 } 658 }
659 } 659 }
660 tty = winch->tty; 660 tty = tty_port_tty_get(winch->port);
661 if (tty != NULL) { 661 if (tty != NULL) {
662 line = tty->driver_data; 662 line = tty->driver_data;
663 if (line != NULL) { 663 if (line != NULL) {
@@ -665,6 +665,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
665 &tty->winsize.ws_col); 665 &tty->winsize.ws_col);
666 kill_pgrp(tty->pgrp, SIGWINCH, 1); 666 kill_pgrp(tty->pgrp, SIGWINCH, 1);
667 } 667 }
668 tty_kref_put(tty);
668 } 669 }
669 out: 670 out:
670 if (winch->fd != -1) 671 if (winch->fd != -1)
@@ -672,7 +673,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
672 return IRQ_HANDLED; 673 return IRQ_HANDLED;
673} 674}
674 675
675void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, 676void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port,
676 unsigned long stack) 677 unsigned long stack)
677{ 678{
678 struct winch *winch; 679 struct winch *winch;
@@ -687,7 +688,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
687 .fd = fd, 688 .fd = fd,
688 .tty_fd = tty_fd, 689 .tty_fd = tty_fd,
689 .pid = pid, 690 .pid = pid,
690 .tty = tty, 691 .port = port,
691 .stack = stack }); 692 .stack = stack });
692 693
693 if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 694 if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
@@ -716,15 +717,18 @@ static void unregister_winch(struct tty_struct *tty)
716{ 717{
717 struct list_head *ele, *next; 718 struct list_head *ele, *next;
718 struct winch *winch; 719 struct winch *winch;
720 struct tty_struct *wtty;
719 721
720 spin_lock(&winch_handler_lock); 722 spin_lock(&winch_handler_lock);
721 723
722 list_for_each_safe(ele, next, &winch_handlers) { 724 list_for_each_safe(ele, next, &winch_handlers) {
723 winch = list_entry(ele, struct winch, list); 725 winch = list_entry(ele, struct winch, list);
724 if (winch->tty == tty) { 726 wtty = tty_port_tty_get(winch->port);
727 if (wtty == tty) {
725 free_winch(winch); 728 free_winch(winch);
726 break; 729 break;
727 } 730 }
731 tty_kref_put(wtty);
728 } 732 }
729 spin_unlock(&winch_handler_lock); 733 spin_unlock(&winch_handler_lock);
730} 734}