diff options
author | David S. Miller <davem@davemloft.net> | 2009-06-15 06:02:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-06-15 06:02:23 -0400 |
commit | 9cbc1cb8cd46ce1f7645b9de249b2ce8460129bb (patch) | |
tree | 8d104ec2a459346b99413b0b77421ca7b9936c1a /drivers/char/tty_io.c | |
parent | ca44d6e60f9de26281fda203f58b570e1748c015 (diff) | |
parent | 45e3e1935e2857c54783291107d33323b3ef33c8 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
Documentation/feature-removal-schedule.txt
drivers/scsi/fcoe/fcoe.c
net/core/drop_monitor.c
net/core/net-traces.c
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 122 |
1 files changed, 34 insertions, 88 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 66b99a2049e3..939e198d7670 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -295,7 +295,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) | |||
295 | struct tty_driver *p, *res = NULL; | 295 | struct tty_driver *p, *res = NULL; |
296 | int tty_line = 0; | 296 | int tty_line = 0; |
297 | int len; | 297 | int len; |
298 | char *str; | 298 | char *str, *stp; |
299 | 299 | ||
300 | for (str = name; *str; str++) | 300 | for (str = name; *str; str++) |
301 | if ((*str >= '0' && *str <= '9') || *str == ',') | 301 | if ((*str >= '0' && *str <= '9') || *str == ',') |
@@ -311,13 +311,14 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) | |||
311 | list_for_each_entry(p, &tty_drivers, tty_drivers) { | 311 | list_for_each_entry(p, &tty_drivers, tty_drivers) { |
312 | if (strncmp(name, p->name, len) != 0) | 312 | if (strncmp(name, p->name, len) != 0) |
313 | continue; | 313 | continue; |
314 | if (*str == ',') | 314 | stp = str; |
315 | str++; | 315 | if (*stp == ',') |
316 | if (*str == '\0') | 316 | stp++; |
317 | str = NULL; | 317 | if (*stp == '\0') |
318 | stp = NULL; | ||
318 | 319 | ||
319 | if (tty_line >= 0 && tty_line <= p->num && p->ops && | 320 | if (tty_line >= 0 && tty_line <= p->num && p->ops && |
320 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) { | 321 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) { |
321 | res = tty_driver_kref_get(p); | 322 | res = tty_driver_kref_get(p); |
322 | *line = tty_line; | 323 | *line = tty_line; |
323 | break; | 324 | break; |
@@ -470,43 +471,6 @@ void tty_wakeup(struct tty_struct *tty) | |||
470 | EXPORT_SYMBOL_GPL(tty_wakeup); | 471 | EXPORT_SYMBOL_GPL(tty_wakeup); |
471 | 472 | ||
472 | /** | 473 | /** |
473 | * tty_ldisc_flush - flush line discipline queue | ||
474 | * @tty: tty | ||
475 | * | ||
476 | * Flush the line discipline queue (if any) for this tty. If there | ||
477 | * is no line discipline active this is a no-op. | ||
478 | */ | ||
479 | |||
480 | void tty_ldisc_flush(struct tty_struct *tty) | ||
481 | { | ||
482 | struct tty_ldisc *ld = tty_ldisc_ref(tty); | ||
483 | if (ld) { | ||
484 | if (ld->ops->flush_buffer) | ||
485 | ld->ops->flush_buffer(tty); | ||
486 | tty_ldisc_deref(ld); | ||
487 | } | ||
488 | tty_buffer_flush(tty); | ||
489 | } | ||
490 | |||
491 | EXPORT_SYMBOL_GPL(tty_ldisc_flush); | ||
492 | |||
493 | /** | ||
494 | * tty_reset_termios - reset terminal state | ||
495 | * @tty: tty to reset | ||
496 | * | ||
497 | * Restore a terminal to the driver default state | ||
498 | */ | ||
499 | |||
500 | static void tty_reset_termios(struct tty_struct *tty) | ||
501 | { | ||
502 | mutex_lock(&tty->termios_mutex); | ||
503 | *tty->termios = tty->driver->init_termios; | ||
504 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); | ||
505 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); | ||
506 | mutex_unlock(&tty->termios_mutex); | ||
507 | } | ||
508 | |||
509 | /** | ||
510 | * do_tty_hangup - actual handler for hangup events | 474 | * do_tty_hangup - actual handler for hangup events |
511 | * @work: tty device | 475 | * @work: tty device |
512 | * | 476 | * |
@@ -535,7 +499,6 @@ static void do_tty_hangup(struct work_struct *work) | |||
535 | struct file *cons_filp = NULL; | 499 | struct file *cons_filp = NULL; |
536 | struct file *filp, *f = NULL; | 500 | struct file *filp, *f = NULL; |
537 | struct task_struct *p; | 501 | struct task_struct *p; |
538 | struct tty_ldisc *ld; | ||
539 | int closecount = 0, n; | 502 | int closecount = 0, n; |
540 | unsigned long flags; | 503 | unsigned long flags; |
541 | int refs = 0; | 504 | int refs = 0; |
@@ -566,40 +529,8 @@ static void do_tty_hangup(struct work_struct *work) | |||
566 | filp->f_op = &hung_up_tty_fops; | 529 | filp->f_op = &hung_up_tty_fops; |
567 | } | 530 | } |
568 | file_list_unlock(); | 531 | file_list_unlock(); |
569 | /* | ||
570 | * FIXME! What are the locking issues here? This may me overdoing | ||
571 | * things... This question is especially important now that we've | ||
572 | * removed the irqlock. | ||
573 | */ | ||
574 | ld = tty_ldisc_ref(tty); | ||
575 | if (ld != NULL) { | ||
576 | /* We may have no line discipline at this point */ | ||
577 | if (ld->ops->flush_buffer) | ||
578 | ld->ops->flush_buffer(tty); | ||
579 | tty_driver_flush_buffer(tty); | ||
580 | if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && | ||
581 | ld->ops->write_wakeup) | ||
582 | ld->ops->write_wakeup(tty); | ||
583 | if (ld->ops->hangup) | ||
584 | ld->ops->hangup(tty); | ||
585 | } | ||
586 | /* | ||
587 | * FIXME: Once we trust the LDISC code better we can wait here for | ||
588 | * ldisc completion and fix the driver call race | ||
589 | */ | ||
590 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); | ||
591 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); | ||
592 | /* | ||
593 | * Shutdown the current line discipline, and reset it to | ||
594 | * N_TTY. | ||
595 | */ | ||
596 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) | ||
597 | tty_reset_termios(tty); | ||
598 | /* Defer ldisc switch */ | ||
599 | /* tty_deferred_ldisc_switch(N_TTY); | ||
600 | 532 | ||
601 | This should get done automatically when the port closes and | 533 | tty_ldisc_hangup(tty); |
602 | tty_release is called */ | ||
603 | 534 | ||
604 | read_lock(&tasklist_lock); | 535 | read_lock(&tasklist_lock); |
605 | if (tty->session) { | 536 | if (tty->session) { |
@@ -628,12 +559,15 @@ static void do_tty_hangup(struct work_struct *work) | |||
628 | read_unlock(&tasklist_lock); | 559 | read_unlock(&tasklist_lock); |
629 | 560 | ||
630 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 561 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
631 | tty->flags = 0; | 562 | clear_bit(TTY_THROTTLED, &tty->flags); |
563 | clear_bit(TTY_PUSH, &tty->flags); | ||
564 | clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); | ||
632 | put_pid(tty->session); | 565 | put_pid(tty->session); |
633 | put_pid(tty->pgrp); | 566 | put_pid(tty->pgrp); |
634 | tty->session = NULL; | 567 | tty->session = NULL; |
635 | tty->pgrp = NULL; | 568 | tty->pgrp = NULL; |
636 | tty->ctrl_status = 0; | 569 | tty->ctrl_status = 0; |
570 | set_bit(TTY_HUPPED, &tty->flags); | ||
637 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 571 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
638 | 572 | ||
639 | /* Account for the p->signal references we killed */ | 573 | /* Account for the p->signal references we killed */ |
@@ -659,10 +593,7 @@ static void do_tty_hangup(struct work_struct *work) | |||
659 | * can't yet guarantee all that. | 593 | * can't yet guarantee all that. |
660 | */ | 594 | */ |
661 | set_bit(TTY_HUPPED, &tty->flags); | 595 | set_bit(TTY_HUPPED, &tty->flags); |
662 | if (ld) { | 596 | tty_ldisc_enable(tty); |
663 | tty_ldisc_enable(tty); | ||
664 | tty_ldisc_deref(ld); | ||
665 | } | ||
666 | unlock_kernel(); | 597 | unlock_kernel(); |
667 | if (f) | 598 | if (f) |
668 | fput(f); | 599 | fput(f); |
@@ -2480,6 +2411,24 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int | |||
2480 | return tty->ops->tiocmset(tty, file, set, clear); | 2411 | return tty->ops->tiocmset(tty, file, set, clear); |
2481 | } | 2412 | } |
2482 | 2413 | ||
2414 | struct tty_struct *tty_pair_get_tty(struct tty_struct *tty) | ||
2415 | { | ||
2416 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | ||
2417 | tty->driver->subtype == PTY_TYPE_MASTER) | ||
2418 | tty = tty->link; | ||
2419 | return tty; | ||
2420 | } | ||
2421 | EXPORT_SYMBOL(tty_pair_get_tty); | ||
2422 | |||
2423 | struct tty_struct *tty_pair_get_pty(struct tty_struct *tty) | ||
2424 | { | ||
2425 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | ||
2426 | tty->driver->subtype == PTY_TYPE_MASTER) | ||
2427 | return tty; | ||
2428 | return tty->link; | ||
2429 | } | ||
2430 | EXPORT_SYMBOL(tty_pair_get_pty); | ||
2431 | |||
2483 | /* | 2432 | /* |
2484 | * Split this up, as gcc can choke on it otherwise.. | 2433 | * Split this up, as gcc can choke on it otherwise.. |
2485 | */ | 2434 | */ |
@@ -2495,11 +2444,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2495 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) | 2444 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) |
2496 | return -EINVAL; | 2445 | return -EINVAL; |
2497 | 2446 | ||
2498 | real_tty = tty; | 2447 | real_tty = tty_pair_get_tty(tty); |
2499 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | ||
2500 | tty->driver->subtype == PTY_TYPE_MASTER) | ||
2501 | real_tty = tty->link; | ||
2502 | |||
2503 | 2448 | ||
2504 | /* | 2449 | /* |
2505 | * Factor out some common prep work | 2450 | * Factor out some common prep work |
@@ -2555,7 +2500,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2555 | case TIOCGSID: | 2500 | case TIOCGSID: |
2556 | return tiocgsid(tty, real_tty, p); | 2501 | return tiocgsid(tty, real_tty, p); |
2557 | case TIOCGETD: | 2502 | case TIOCGETD: |
2558 | return put_user(tty->ldisc.ops->num, (int __user *)p); | 2503 | return put_user(tty->ldisc->ops->num, (int __user *)p); |
2559 | case TIOCSETD: | 2504 | case TIOCSETD: |
2560 | return tiocsetd(tty, p); | 2505 | return tiocsetd(tty, p); |
2561 | /* | 2506 | /* |
@@ -2770,6 +2715,7 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
2770 | tty->buf.head = tty->buf.tail = NULL; | 2715 | tty->buf.head = tty->buf.tail = NULL; |
2771 | tty_buffer_init(tty); | 2716 | tty_buffer_init(tty); |
2772 | mutex_init(&tty->termios_mutex); | 2717 | mutex_init(&tty->termios_mutex); |
2718 | mutex_init(&tty->ldisc_mutex); | ||
2773 | init_waitqueue_head(&tty->write_wait); | 2719 | init_waitqueue_head(&tty->write_wait); |
2774 | init_waitqueue_head(&tty->read_wait); | 2720 | init_waitqueue_head(&tty->read_wait); |
2775 | INIT_WORK(&tty->hangup_work, do_tty_hangup); | 2721 | INIT_WORK(&tty->hangup_work, do_tty_hangup); |