diff options
| author | Jiri Slaby <jslaby@suse.cz> | 2012-06-04 07:35:27 -0400 |
|---|---|---|
| committer | Richard Weinberger <richard@nod.at> | 2012-07-28 11:47:58 -0400 |
| commit | 6fc58845ad189f8ceebd68a2ff524bfcd689a75e (patch) | |
| tree | 7acc1ed13ec6427bf80f9ef3bf6eb4be0119663d | |
| parent | 060ed31dd9ede0726f8c88aff36c6cd8ec6d0fe8 (diff) | |
TTY: um/line, use tty from tty_port
This means switching to the tty refcounted model so that we will not
race with interrupts.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Jeff Dike <jdike@addtoit.com>
Cc: Richard Weinberger <richard@nod.at>
Cc: user-mode-linux-devel@lists.sourceforge.net
Signed-off-by: Richard Weinberger <richard@nod.at>
| -rw-r--r-- | arch/um/drivers/chan_kern.c | 4 | ||||
| -rw-r--r-- | arch/um/drivers/line.c | 25 | ||||
| -rw-r--r-- | arch/um/drivers/line.h | 1 |
3 files changed, 21 insertions, 9 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 45e248c2f43c..87eebfe03c61 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
| @@ -150,9 +150,11 @@ void chan_enable_winch(struct chan *chan, struct tty_struct *tty) | |||
| 150 | static void line_timer_cb(struct work_struct *work) | 150 | static void line_timer_cb(struct work_struct *work) |
| 151 | { | 151 | { |
| 152 | struct line *line = container_of(work, struct line, task.work); | 152 | struct line *line = container_of(work, struct line, task.work); |
| 153 | struct tty_struct *tty = tty_port_tty_get(&line->port); | ||
| 153 | 154 | ||
| 154 | if (!line->throttled) | 155 | if (!line->throttled) |
| 155 | chan_interrupt(line, line->tty, line->driver->read_irq); | 156 | chan_interrupt(line, tty, line->driver->read_irq); |
| 157 | tty_kref_put(tty); | ||
| 156 | } | 158 | } |
| 157 | 159 | ||
| 158 | int enable_chan(struct line *line) | 160 | int enable_chan(struct line *line) |
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 482a7bd4a64c..fb6e4ea09921 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
| @@ -19,9 +19,11 @@ static irqreturn_t line_interrupt(int irq, void *data) | |||
| 19 | { | 19 | { |
| 20 | struct chan *chan = data; | 20 | struct chan *chan = data; |
| 21 | struct line *line = chan->line; | 21 | struct line *line = chan->line; |
| 22 | struct tty_struct *tty = tty_port_tty_get(&line->port); | ||
| 22 | 23 | ||
| 23 | if (line) | 24 | if (line) |
| 24 | chan_interrupt(line, line->tty, irq); | 25 | chan_interrupt(line, tty, irq); |
| 26 | tty_kref_put(tty); | ||
| 25 | return IRQ_HANDLED; | 27 | return IRQ_HANDLED; |
| 26 | } | 28 | } |
| 27 | 29 | ||
| @@ -333,7 +335,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data) | |||
| 333 | { | 335 | { |
| 334 | struct chan *chan = data; | 336 | struct chan *chan = data; |
| 335 | struct line *line = chan->line; | 337 | struct line *line = chan->line; |
| 336 | struct tty_struct *tty = line->tty; | 338 | struct tty_struct *tty; |
| 337 | int err; | 339 | int err; |
| 338 | 340 | ||
| 339 | /* | 341 | /* |
| @@ -352,10 +354,13 @@ static irqreturn_t line_write_interrupt(int irq, void *data) | |||
| 352 | } | 354 | } |
| 353 | spin_unlock(&line->lock); | 355 | spin_unlock(&line->lock); |
| 354 | 356 | ||
| 357 | tty = tty_port_tty_get(&line->port); | ||
| 355 | if (tty == NULL) | 358 | if (tty == NULL) |
| 356 | return IRQ_NONE; | 359 | return IRQ_NONE; |
| 357 | 360 | ||
| 358 | tty_wakeup(tty); | 361 | tty_wakeup(tty); |
| 362 | tty_kref_put(tty); | ||
| 363 | |||
| 359 | return IRQ_HANDLED; | 364 | return IRQ_HANDLED; |
| 360 | } | 365 | } |
| 361 | 366 | ||
| @@ -409,7 +414,7 @@ int line_open(struct line *lines, struct tty_struct *tty) | |||
| 409 | 414 | ||
| 410 | BUG_ON(tty->driver_data); | 415 | BUG_ON(tty->driver_data); |
| 411 | tty->driver_data = line; | 416 | tty->driver_data = line; |
| 412 | line->tty = tty; | 417 | tty_port_tty_set(&line->port, tty); |
| 413 | 418 | ||
| 414 | err = enable_chan(line); | 419 | err = enable_chan(line); |
| 415 | if (err) /* line_close() will be called by our caller */ | 420 | if (err) /* line_close() will be called by our caller */ |
| @@ -449,7 +454,7 @@ void line_close(struct tty_struct *tty, struct file * filp) | |||
| 449 | if (--line->port.count) | 454 | if (--line->port.count) |
| 450 | goto out_unlock; | 455 | goto out_unlock; |
| 451 | 456 | ||
| 452 | line->tty = NULL; | 457 | tty_port_tty_set(&line->port, NULL); |
| 453 | tty->driver_data = NULL; | 458 | tty->driver_data = NULL; |
| 454 | 459 | ||
| 455 | if (line->sigio) { | 460 | if (line->sigio) { |
| @@ -610,9 +615,15 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, | |||
| 610 | mutex_lock(&line->count_lock); | 615 | mutex_lock(&line->count_lock); |
| 611 | if (!line->valid) | 616 | if (!line->valid) |
| 612 | CONFIG_CHUNK(str, size, n, "none", 1); | 617 | CONFIG_CHUNK(str, size, n, "none", 1); |
| 613 | else if (line->tty == NULL) | 618 | else { |
| 614 | CONFIG_CHUNK(str, size, n, line->init_str, 1); | 619 | struct tty_struct *tty = tty_port_tty_get(&line->port); |
| 615 | else n = chan_config_string(line, str, size, error_out); | 620 | if (tty == NULL) { |
| 621 | CONFIG_CHUNK(str, size, n, line->init_str, 1); | ||
| 622 | } else { | ||
| 623 | n = chan_config_string(line, str, size, error_out); | ||
| 624 | tty_kref_put(tty); | ||
| 625 | } | ||
| 626 | } | ||
| 616 | mutex_unlock(&line->count_lock); | 627 | mutex_unlock(&line->count_lock); |
| 617 | 628 | ||
| 618 | return n; | 629 | return n; |
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h index 0e06a1f441d7..5b3d4fbdec18 100644 --- a/arch/um/drivers/line.h +++ b/arch/um/drivers/line.h | |||
| @@ -33,7 +33,6 @@ struct line_driver { | |||
| 33 | 33 | ||
| 34 | struct line { | 34 | struct line { |
| 35 | struct tty_port port; | 35 | struct tty_port port; |
| 36 | struct tty_struct *tty; | ||
| 37 | struct mutex count_lock; | 36 | struct mutex count_lock; |
| 38 | int valid; | 37 | int valid; |
| 39 | 38 | ||
