return tty;
 }
 
-static void pty_unix98_shutdown(struct tty_struct *tty)
-{
-       tty_driver_remove_tty(tty->driver, tty);
-       /* We have our own method as we don't use the tty index */
-}
-
 /* We have no need to install and remove our tty objects as devpts does all
    the work for us */
 
        .unthrottle = pty_unthrottle,
        .set_termios = pty_set_termios,
        .ioctl = pty_unix98_ioctl,
-       .shutdown = pty_unix98_shutdown,
-       .cleanup = pty_cleanup,
-       .resize = pty_resize
+       .resize = pty_resize,
+       .cleanup = pty_cleanup
 };
 
 static const struct tty_operations pty_unix98_ops = {
        .chars_in_buffer = pty_chars_in_buffer,
        .unthrottle = pty_unthrottle,
        .set_termios = pty_set_termios,
-       .shutdown = pty_unix98_shutdown,
        .cleanup = pty_cleanup,
 };
 
 
        struct ktermios *tp;
        int idx = tty->index;
 
-       tp = tty->driver->termios[idx];
-       if (tp == NULL) {
-               tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
-               if (tp == NULL)
-                       return -ENOMEM;
-               *tp = tty->driver->init_termios;
-               tty->driver->termios[idx] = tp;
+       if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
+               tty->termios = tty->driver->init_termios;
+       else {
+               /* Check for lazy saved data */
+               tp = tty->driver->termios[idx];
+               if (tp != NULL)
+                       tty->termios = *tp;
+               else
+                       tty->termios = tty->driver->init_termios;
        }
-       tty->termios = *tp;
-
        /* Compatibility until drivers always set this */
        tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios);
        tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios);
 {
        struct ktermios *tp;
        int idx = tty->index;
-       /* Kill this flag and push into drivers for locking etc */
-       if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
-               /* FIXME: Locking on ->termios array */
-               tp = tty->driver->termios[idx];
-               tty->driver->termios[idx] = NULL;
-               kfree(tp);
+
+       /* If the port is going to reset then it has no termios to save */
+       if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
+               return;
+
+       /* Stash the termios data */
+       tp = tty->driver->termios[idx];
+       if (tp == NULL) {
+               tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
+               if (tp == NULL) {
+                       pr_warn("tty: no memory to save termios state.\n");
+                       return;
+               }
        }
-       else
-               *tty->driver->termios[idx] = tty->termios;
+       *tp = tty->termios;
 }
 EXPORT_SYMBOL(tty_free_termios);
 
-void tty_shutdown(struct tty_struct *tty)
-{
-       tty_driver_remove_tty(tty->driver, tty);
-       tty_free_termios(tty);
-}
-EXPORT_SYMBOL(tty_shutdown);
 
 /**
  *     release_one_tty         -       release tty structure memory
 {
        struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
 
-       if (tty->ops->shutdown)
-               tty->ops->shutdown(tty);
-       else
-               tty_shutdown(tty);
-
        /* The hangup queue is now free so we can reuse it rather than
           waste a chunk of memory for each port */
        INIT_WORK(&tty->hangup_work, release_one_tty);
        /* This should always be true but check for the moment */
        WARN_ON(tty->index != idx);
 
+       if (tty->ops->shutdown)
+               tty->ops->shutdown(tty);
+       tty_free_termios(tty);
+       tty_driver_remove_tty(tty->driver, tty);
+
        if (tty->link)
                tty_kref_put(tty->link);
        tty_kref_put(tty);
 
  *
  * void (*shutdown)(struct tty_struct * tty);
  *
- *     This routine is called synchronously when a particular tty device
- *     is closed for the last time freeing up the resources.
- *     Note that tty_shutdown() is not called if ops->shutdown is defined.
- *     This means one is responsible to take care of calling ops->remove (e.g.
- *     via tty_driver_remove_tty) and releasing tty->termios.
- *     Note that this hook may be called from *all* the contexts where one
- *     uses tty refcounting (e.g. tty_port_tty_get).
- *
+ *     This routine is called under the tty lock when a particular tty device
+ *     is closed for the last time. It executes before the tty resources
+ *     are freed so may execute while another function holds a tty kref.
  *
  * void (*cleanup)(struct tty_struct * tty);
  *