tty: Fix a typo noted in passing
[safe/jmp/linux-2.6] / drivers / char / tty_io.c
index d8d240c..9384480 100644 (file)
@@ -295,7 +295,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
        struct tty_driver *p, *res = NULL;
        int tty_line = 0;
        int len;
-       char *str;
+       char *str, *stp;
 
        for (str = name; *str; str++)
                if ((*str >= '0' && *str <= '9') || *str == ',')
@@ -311,13 +311,14 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
        list_for_each_entry(p, &tty_drivers, tty_drivers) {
                if (strncmp(name, p->name, len) != 0)
                        continue;
-               if (*str == ',')
-                       str++;
-               if (*str == '\0')
-                       str = NULL;
+               stp = str;
+               if (*stp == ',')
+                       stp++;
+               if (*stp == '\0')
+                       stp = NULL;
 
                if (tty_line >= 0 && tty_line <= p->num && p->ops &&
-                   p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) {
+                   p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) {
                        res = tty_driver_kref_get(p);
                        *line = tty_line;
                        break;
@@ -464,49 +465,12 @@ void tty_wakeup(struct tty_struct *tty)
                        tty_ldisc_deref(ld);
                }
        }
-       wake_up_interruptible(&tty->write_wait);
+       wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
 }
 
 EXPORT_SYMBOL_GPL(tty_wakeup);
 
 /**
- *     tty_ldisc_flush -       flush line discipline queue
- *     @tty: tty
- *
- *     Flush the line discipline queue (if any) for this tty. If there
- *     is no line discipline active this is a no-op.
- */
-
-void tty_ldisc_flush(struct tty_struct *tty)
-{
-       struct tty_ldisc *ld = tty_ldisc_ref(tty);
-       if (ld) {
-               if (ld->ops->flush_buffer)
-                       ld->ops->flush_buffer(tty);
-               tty_ldisc_deref(ld);
-       }
-       tty_buffer_flush(tty);
-}
-
-EXPORT_SYMBOL_GPL(tty_ldisc_flush);
-
-/**
- *     tty_reset_termios       -       reset terminal state
- *     @tty: tty to reset
- *
- *     Restore a terminal to the driver default state
- */
-
-static void tty_reset_termios(struct tty_struct *tty)
-{
-       mutex_lock(&tty->termios_mutex);
-       *tty->termios = tty->driver->init_termios;
-       tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
-       tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
-       mutex_unlock(&tty->termios_mutex);
-}
-
-/**
  *     do_tty_hangup           -       actual handler for hangup events
  *     @work: tty device
  *
@@ -535,7 +499,6 @@ static void do_tty_hangup(struct work_struct *work)
        struct file *cons_filp = NULL;
        struct file *filp, *f = NULL;
        struct task_struct *p;
-       struct tty_ldisc *ld;
        int    closecount = 0, n;
        unsigned long flags;
        int refs = 0;
@@ -566,40 +529,8 @@ static void do_tty_hangup(struct work_struct *work)
                filp->f_op = &hung_up_tty_fops;
        }
        file_list_unlock();
-       /*
-        * FIXME! What are the locking issues here? This may me overdoing
-        * things... This question is especially important now that we've
-        * removed the irqlock.
-        */
-       ld = tty_ldisc_ref(tty);
-       if (ld != NULL) {
-               /* We may have no line discipline at this point */
-               if (ld->ops->flush_buffer)
-                       ld->ops->flush_buffer(tty);
-               tty_driver_flush_buffer(tty);
-               if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
-                   ld->ops->write_wakeup)
-                       ld->ops->write_wakeup(tty);
-               if (ld->ops->hangup)
-                       ld->ops->hangup(tty);
-       }
-       /*
-        * FIXME: Once we trust the LDISC code better we can wait here for
-        * ldisc completion and fix the driver call race
-        */
-       wake_up_interruptible(&tty->write_wait);
-       wake_up_interruptible(&tty->read_wait);
-       /*
-        * Shutdown the current line discipline, and reset it to
-        * N_TTY.
-        */
-       if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
-               tty_reset_termios(tty);
-       /* Defer ldisc switch */
-       /* tty_deferred_ldisc_switch(N_TTY);
 
-         This should get done automatically when the port closes and
-         tty_release is called */
+       tty_ldisc_hangup(tty);
 
        read_lock(&tasklist_lock);
        if (tty->session) {
@@ -628,12 +559,15 @@ static void do_tty_hangup(struct work_struct *work)
        read_unlock(&tasklist_lock);
 
        spin_lock_irqsave(&tty->ctrl_lock, flags);
-       tty->flags = 0;
+       clear_bit(TTY_THROTTLED, &tty->flags);
+       clear_bit(TTY_PUSH, &tty->flags);
+       clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
        put_pid(tty->session);
        put_pid(tty->pgrp);
        tty->session = NULL;
        tty->pgrp = NULL;
        tty->ctrl_status = 0;
+       set_bit(TTY_HUPPED, &tty->flags);
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 
        /* Account for the p->signal references we killed */
@@ -659,10 +593,7 @@ static void do_tty_hangup(struct work_struct *work)
         * can't yet guarantee all that.
         */
        set_bit(TTY_HUPPED, &tty->flags);
-       if (ld) {
-               tty_ldisc_enable(tty);
-               tty_ldisc_deref(ld);
-       }
+       tty_ldisc_enable(tty);
        unlock_kernel();
        if (f)
                fput(f);
@@ -879,7 +810,7 @@ void stop_tty(struct tty_struct *tty)
        if (tty->link && tty->link->packet) {
                tty->ctrl_status &= ~TIOCPKT_START;
                tty->ctrl_status |= TIOCPKT_STOP;
-               wake_up_interruptible(&tty->link->read_wait);
+               wake_up_interruptible_poll(&tty->link->read_wait, POLLIN);
        }
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
        if (tty->ops->stop)
@@ -913,7 +844,7 @@ void start_tty(struct tty_struct *tty)
        if (tty->link && tty->link->packet) {
                tty->ctrl_status &= ~TIOCPKT_STOP;
                tty->ctrl_status |= TIOCPKT_START;
-               wake_up_interruptible(&tty->link->read_wait);
+               wake_up_interruptible_poll(&tty->link->read_wait, POLLIN);
        }
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
        if (tty->ops->start)
@@ -970,7 +901,7 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
 void tty_write_unlock(struct tty_struct *tty)
 {
        mutex_unlock(&tty->atomic_write_lock);
-       wake_up_interruptible(&tty->write_wait);
+       wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
 }
 
 int tty_write_lock(struct tty_struct *tty, int ndelay)
@@ -1211,7 +1142,7 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)
  *     be held until the 'fast-open' is also done. Will change once we
  *     have refcounting in the driver and per driver locking
  */
-struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
+static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
                struct inode *inode, int idx)
 {
        struct tty_struct *tty;
@@ -1332,7 +1263,9 @@ static int tty_reopen(struct tty_struct *tty)
        tty->count++;
        tty->driver = driver; /* N.B. why do this every time?? */
 
+       mutex_lock(&tty->ldisc_mutex);
        WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
+       mutex_unlock(&tty->ldisc_mutex);
 
        return 0;
 }
@@ -1623,21 +1556,21 @@ void tty_release_dev(struct file *filp)
 
                if (tty_closing) {
                        if (waitqueue_active(&tty->read_wait)) {
-                               wake_up(&tty->read_wait);
+                               wake_up_poll(&tty->read_wait, POLLIN);
                                do_sleep++;
                        }
                        if (waitqueue_active(&tty->write_wait)) {
-                               wake_up(&tty->write_wait);
+                               wake_up_poll(&tty->write_wait, POLLOUT);
                                do_sleep++;
                        }
                }
                if (o_tty_closing) {
                        if (waitqueue_active(&o_tty->read_wait)) {
-                               wake_up(&o_tty->read_wait);
+                               wake_up_poll(&o_tty->read_wait, POLLIN);
                                do_sleep++;
                        }
                        if (waitqueue_active(&o_tty->write_wait)) {
-                               wake_up(&o_tty->write_wait);
+                               wake_up_poll(&o_tty->write_wait, POLLOUT);
                                do_sleep++;
                        }
                }
@@ -1758,7 +1691,7 @@ static int __tty_open(struct inode *inode, struct file *filp)
        struct tty_driver *driver;
        int index;
        dev_t device = inode->i_rdev;
-       unsigned short saved_flags = filp->f_flags;
+       unsigned saved_flags = filp->f_flags;
 
        nonseekable_open(inode, filp);
 
@@ -1817,8 +1750,10 @@ got_driver:
                /* check whether we're reopening an existing tty */
                tty = tty_driver_lookup_tty(driver, inode, index);
 
-               if (IS_ERR(tty))
+               if (IS_ERR(tty)) {
+                       mutex_unlock(&tty_mutex);
                        return PTR_ERR(tty);
+               }
        }
 
        if (tty) {
@@ -2048,7 +1983,6 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
 /**
  *     tty_do_resize           -       resize event
  *     @tty: tty being resized
- *     @real_tty: real tty (not the same as tty if using a pty/tty pair)
  *     @rows: rows (character)
  *     @cols: cols (character)
  *
@@ -2056,41 +1990,34 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
  *     peform a terminal resize correctly
  */
 
-int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
-                                       struct winsize *ws)
+int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
 {
-       struct pid *pgrp, *rpgrp;
+       struct pid *pgrp;
        unsigned long flags;
 
-       /* For a PTY we need to lock the tty side */
-       mutex_lock(&real_tty->termios_mutex);
-       if (!memcmp(ws, &real_tty->winsize, sizeof(*ws)))
+       /* Lock the tty */
+       mutex_lock(&tty->termios_mutex);
+       if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
                goto done;
        /* Get the PID values and reference them so we can
           avoid holding the tty ctrl lock while sending signals */
        spin_lock_irqsave(&tty->ctrl_lock, flags);
        pgrp = get_pid(tty->pgrp);
-       rpgrp = get_pid(real_tty->pgrp);
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 
        if (pgrp)
                kill_pgrp(pgrp, SIGWINCH, 1);
-       if (rpgrp != pgrp && rpgrp)
-               kill_pgrp(rpgrp, SIGWINCH, 1);
-
        put_pid(pgrp);
-       put_pid(rpgrp);
 
        tty->winsize = *ws;
-       real_tty->winsize = *ws;
 done:
-       mutex_unlock(&real_tty->termios_mutex);
+       mutex_unlock(&tty->termios_mutex);
        return 0;
 }
 
 /**
  *     tiocswinsz              -       implement window size set ioctl
- *     @tty; tty
+ *     @tty; tty side of tty
  *     @arg: user buffer for result
  *
  *     Copies the user idea of the window size to the kernel. Traditionally
@@ -2103,17 +2030,16 @@ done:
  *     then calls into the default method.
  */
 
-static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
-       struct winsize __user *arg)
+static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg)
 {
        struct winsize tmp_ws;
        if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
                return -EFAULT;
 
        if (tty->ops->resize)
-               return tty->ops->resize(tty, real_tty, &tmp_ws);
+               return tty->ops->resize(tty, &tmp_ws);
        else
-               return tty_do_resize(tty, real_tty, &tmp_ws);
+               return tty_do_resize(tty, &tmp_ws);
 }
 
 /**
@@ -2159,7 +2085,7 @@ static int tioccons(struct file *file)
  *     the generic functionality existed. This piece of history is preserved
  *     in the expected tty API of posix OS's.
  *
- *     Locking: none, the open fle handle ensures it won't go away.
+ *     Locking: none, the open file handle ensures it won't go away.
  */
 
 static int fionbio(struct file *file, int __user *p)
@@ -2169,13 +2095,12 @@ static int fionbio(struct file *file, int __user *p)
        if (get_user(nonblock, p))
                return -EFAULT;
 
-       /* file->f_flags is still BKL protected in the fs layer - vomit */
-       lock_kernel();
+       spin_lock(&file->f_lock);
        if (nonblock)
                file->f_flags |= O_NONBLOCK;
        else
                file->f_flags &= ~O_NONBLOCK;
-       unlock_kernel();
+       spin_unlock(&file->f_lock);
        return 0;
 }
 
@@ -2488,6 +2413,24 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
        return tty->ops->tiocmset(tty, file, set, clear);
 }
 
+struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
+{
+       if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+           tty->driver->subtype == PTY_TYPE_MASTER)
+               tty = tty->link;
+       return tty;
+}
+EXPORT_SYMBOL(tty_pair_get_tty);
+
+struct tty_struct *tty_pair_get_pty(struct tty_struct *tty)
+{
+       if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+           tty->driver->subtype == PTY_TYPE_MASTER)
+           return tty;
+       return tty->link;
+}
+EXPORT_SYMBOL(tty_pair_get_pty);
+
 /*
  * Split this up, as gcc can choke on it otherwise..
  */
@@ -2503,11 +2446,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        if (tty_paranoia_check(tty, inode, "tty_ioctl"))
                return -EINVAL;
 
-       real_tty = tty;
-       if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
-           tty->driver->subtype == PTY_TYPE_MASTER)
-               real_tty = tty->link;
-
+       real_tty = tty_pair_get_tty(tty);
 
        /*
         * Factor out some common prep work
@@ -2538,7 +2477,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case TIOCGWINSZ:
                return tiocgwinsz(real_tty, p);
        case TIOCSWINSZ:
-               return tiocswinsz(tty, real_tty, p);
+               return tiocswinsz(real_tty, p);
        case TIOCCONS:
                return real_tty != tty ? -EINVAL : tioccons(file);
        case FIONBIO:
@@ -2563,7 +2502,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case TIOCGSID:
                return tiocgsid(tty, real_tty, p);
        case TIOCGETD:
-               return put_user(tty->ldisc.ops->num, (int __user *)p);
+               return put_user(tty->ldisc->ops->num, (int __user *)p);
        case TIOCSETD:
                return tiocsetd(tty, p);
        /*
@@ -2689,7 +2628,7 @@ void __do_SAK(struct tty_struct *tty)
        /* Kill the entire session */
        do_each_pid_task(session, PIDTYPE_SID, p) {
                printk(KERN_NOTICE "SAK: killed process %d"
-                       " (%s): task_session_nr(p)==tty->session\n",
+                       " (%s): task_session(p)==tty->session\n",
                        task_pid_nr(p), p->comm);
                send_sig(SIGKILL, p, 1);
        } while_each_pid_task(session, PIDTYPE_SID, p);
@@ -2699,7 +2638,7 @@ void __do_SAK(struct tty_struct *tty)
        do_each_thread(g, p) {
                if (p->signal->tty == tty) {
                        printk(KERN_NOTICE "SAK: killed process %d"
-                           " (%s): task_session_nr(p)==tty->session\n",
+                           " (%s): task_session(p)==tty->session\n",
                            task_pid_nr(p), p->comm);
                        send_sig(SIGKILL, p, 1);
                        continue;
@@ -2778,6 +2717,7 @@ void initialize_tty_struct(struct tty_struct *tty,
        tty->buf.head = tty->buf.tail = NULL;
        tty_buffer_init(tty);
        mutex_init(&tty->termios_mutex);
+       mutex_init(&tty->ldisc_mutex);
        init_waitqueue_head(&tty->write_wait);
        init_waitqueue_head(&tty->read_wait);
        INIT_WORK(&tty->hangup_work, do_tty_hangup);