static void belkin_sa_shutdown(struct usb_serial *serial);
 static int  belkin_sa_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void belkin_sa_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void belkin_sa_close(struct usb_serial_port *port);
 static void belkin_sa_read_int_callback(struct urb *urb);
 static void belkin_sa_set_termios(struct tty_struct *tty,
                        struct usb_serial_port *port, struct ktermios * old);
 } /* belkin_sa_open */
 
 
-static void belkin_sa_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void belkin_sa_close(struct usb_serial_port *port)
 {
        dbg("%s port %d", __func__, port->number);
 
 
        return r;
 }
 
-static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port,
-                               struct file *filp)
+static int ch341_carrier_raised(struct usb_serial_port *port)
+{
+       struct ch341_private *priv = usb_get_serial_port_data(port);
+       if (priv->line_status & CH341_BIT_DCD)
+               return 1;
+       return 0;
+}
+
+static void ch341_dtr_rts(struct usb_serial_port *port, int on)
 {
        struct ch341_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
-       unsigned int c_cflag;
 
+       dbg("%s - port %d", __func__, port->number);
+       /* drop DTR and RTS */
+       spin_lock_irqsave(&priv->lock, flags);
+       if (on)
+               priv->line_control |= CH341_BIT_RTS | CH341_BIT_DTR;
+       else
+               priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
+       spin_unlock_irqrestore(&priv->lock, flags);
+       ch341_set_handshake(port->serial->dev, priv->line_control);
+       wake_up_interruptible(&priv->delta_msr_wait);
+}
+
+static void ch341_close(struct usb_serial_port *port)
+{
        dbg("%s - port %d", __func__, port->number);
 
        /* shutdown our urbs */
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->interrupt_in_urb);
-
-       if (tty) {
-               c_cflag = tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       /* drop DTR and RTS */
-                       spin_lock_irqsave(&priv->lock, flags);
-                       priv->line_control = 0;
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       ch341_set_handshake(port->serial->dev, 0);
-               }
-       }
-       wake_up_interruptible(&priv->delta_msr_wait);
 }
 
 
        dbg("ch341_open()");
 
        priv->baud_rate = DEFAULT_BAUD_RATE;
-       priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
        r = ch341_configure(serial->dev, priv);
        if (r)
        if (r) {
                dev_err(&port->dev, "%s - failed submitting interrupt urb,"
                        " error %d\n", __func__, r);
-               ch341_close(tty, port, NULL);
+               ch341_close(port);
                return -EPROTO;
        }
 
 
        dbg("ch341_set_termios()");
 
-       if (!tty || !tty->termios)
-               return;
-
        baud_rate = tty_get_baud_rate(tty);
 
        priv->baud_rate = baud_rate;
        .usb_driver        = &ch341_driver,
        .num_ports         = 1,
        .open              = ch341_open,
+       .dtr_rts           = ch341_dtr_rts,
+       .carrier_raised    = ch341_carrier_raised,
        .close             = ch341_close,
        .ioctl             = ch341_ioctl,
        .set_termios       = ch341_set_termios,
 
                        kfree(tty);
                }
        }
-
+       /* So we know not to kill the hardware on a hangup on this
+          port. We have also bumped the use count by one so it won't go
+          idle */
        port->console = 1;
        retval = 0;
 
        kfree(tty);
 reset_open_count:
        port->port.count = 0;
-goto out;
+       goto out;
 }
 
 static void usb_console_write(struct console *co,
 
 static int cp2101_open(struct tty_struct *, struct usb_serial_port *,
                                                        struct file *);
 static void cp2101_cleanup(struct usb_serial_port *);
-static void cp2101_close(struct tty_struct *, struct usb_serial_port *,
-                                                       struct file*);
+static void cp2101_close(struct usb_serial_port *);
 static void cp2101_get_termios(struct tty_struct *,
        struct usb_serial_port *port);
 static void cp2101_get_termios_port(struct usb_serial_port *port,
        }
 }
 
-static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                       struct file *filp)
+static void cp2101_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
 
 static void cyberjack_shutdown(struct usb_serial *serial);
 static int  cyberjack_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void cyberjack_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void cyberjack_close(struct usb_serial_port *port);
 static int cyberjack_write(struct tty_struct *tty,
        struct usb_serial_port *port, const unsigned char *buf, int count);
 static int cyberjack_write_room(struct tty_struct *tty);
        return result;
 }
 
-static void cyberjack_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void cyberjack_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
 
 static void cypress_shutdown(struct usb_serial *serial);
 static int  cypress_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void cypress_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void cypress_close(struct usb_serial_port *port);
+static void cypress_dtr_rts(struct usb_serial_port *port, int on);
 static int  cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
                        const unsigned char *buf, int count);
 static void cypress_send(struct usb_serial_port *port);
        .shutdown =                     cypress_shutdown,
        .open =                         cypress_open,
        .close =                        cypress_close,
+       .dtr_rts =                      cypress_dtr_rts,
        .write =                        cypress_write,
        .write_room =                   cypress_write_room,
        .ioctl =                        cypress_ioctl,
        .shutdown =                     cypress_shutdown,
        .open =                         cypress_open,
        .close =                        cypress_close,
+       .dtr_rts =                      cypress_dtr_rts,
        .write =                        cypress_write,
        .write_room =                   cypress_write_room,
        .ioctl =                        cypress_ioctl,
        .shutdown =                     cypress_shutdown,
        .open =                         cypress_open,
        .close =                        cypress_close,
+       .dtr_rts =                      cypress_dtr_rts,
        .write =                        cypress_write,
        .write_room =                   cypress_write_room,
        .ioctl =                        cypress_ioctl,
        priv->rx_flags = 0;
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* raise both lines and set termios */
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->line_control = CONTROL_DTR | CONTROL_RTS;
-       priv->cmd_ctrl = 1;
-       spin_unlock_irqrestore(&priv->lock, flags);
+       /* Set termios */
        result = cypress_write(tty, port, NULL, 0);
 
        if (result) {
                                                        __func__, result);
                cypress_set_dead(port);
        }
-
+       port->port.drain_delay = 256;
        return result;
 } /* cypress_open */
 
+static void cypress_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct cypress_private *priv = usb_get_serial_port_data(port);
+       /* drop dtr and rts */
+       priv = usb_get_serial_port_data(port);
+       spin_lock_irq(&priv->lock);
+       if (on == 0)
+               priv->line_control = 0;
+       else 
+               priv->line_control = CONTROL_DTR | CONTROL_RTS;
+       priv->cmd_ctrl = 1;
+       spin_unlock_irq(&priv->lock);
+       cypress_write(NULL, port, NULL, 0);
+}
 
-static void cypress_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void cypress_close(struct usb_serial_port *port)
 {
        struct cypress_private *priv = usb_get_serial_port_data(port);
-       unsigned int c_cflag;
-       int bps;
-       long timeout;
-       wait_queue_t wait;
 
        dbg("%s - port %d", __func__, port->number);
 
-       /* wait for data to drain from buffer */
-       spin_lock_irq(&priv->lock);
-       timeout = CYPRESS_CLOSING_WAIT;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&tty->write_wait, &wait);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (cypress_buf_data_avail(priv->buf) == 0
-               || timeout == 0 || signal_pending(current)
-               /* without mutex, allowed due to harmless failure mode */
-               || port->serial->disconnected)
-                       break;
-               spin_unlock_irq(&priv->lock);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irq(&priv->lock);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&tty->write_wait, &wait);
-       /* clear out any remaining data in the buffer */
-       cypress_buf_clear(priv->buf);
-       spin_unlock_irq(&priv->lock);
-
        /* writing is potentially harmful, lock must be taken */
        mutex_lock(&port->serial->disc_mutex);
        if (port->serial->disconnected) {
                mutex_unlock(&port->serial->disc_mutex);
                return;
        }
-       /* wait for characters to drain from device */
-       if (tty) {
-               bps = tty_get_baud_rate(tty);
-               if (bps > 1200)
-                       timeout = max((HZ * 2560) / bps, HZ / 10);
-               else
-                       timeout = 2 * HZ;
-               schedule_timeout_interruptible(timeout);
-       }
-
+       cypress_buf_clear(priv->buf);
        dbg("%s - stopping urbs", __func__);
        usb_kill_urb(port->interrupt_in_urb);
        usb_kill_urb(port->interrupt_out_urb);
 
-       if (tty) {
-               c_cflag = tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       /* drop dtr and rts */
-                       priv = usb_get_serial_port_data(port);
-                       spin_lock_irq(&priv->lock);
-                       priv->line_control = 0;
-                       priv->cmd_ctrl = 1;
-                       spin_unlock_irq(&priv->lock);
-                       cypress_write(tty, port, NULL, 0);
-               }
-       }
 
        if (stats)
                dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
 
        int dp_throttled;
        int dp_throttle_restart;
        wait_queue_head_t dp_flush_wait;
-       int dp_in_close;                        /* close in progress */
        wait_queue_head_t dp_close_wait;        /* wait queue for close */
        struct work_struct dp_wakeup_work;
        struct usb_serial_port *dp_port;
 static int digi_chars_in_buffer(struct tty_struct *tty);
 static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
        struct file *filp);
-static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
-       struct file *filp);
+static void digi_close(struct usb_serial_port *port);
+static int digi_carrier_raised(struct usb_serial_port *port);
+static void digi_dtr_rts(struct usb_serial_port *port, int on);
 static int digi_startup_device(struct usb_serial *serial);
 static int digi_startup(struct usb_serial *serial);
 static void digi_shutdown(struct usb_serial *serial);
        .num_ports =                    3,
        .open =                         digi_open,
        .close =                        digi_close,
+       .dtr_rts =                      digi_dtr_rts,
+       .carrier_raised =               digi_carrier_raised,
        .write =                        digi_write,
        .write_room =                   digi_write_room,
        .write_bulk_callback =          digi_write_bulk_callback,
 
 }
 
+static void digi_dtr_rts(struct usb_serial_port *port, int on)
+{
+       /* Adjust DTR and RTS */
+       digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1);
+}
+
+static int digi_carrier_raised(struct usb_serial_port *port)
+{
+       struct digi_port *priv = usb_get_serial_port_data(port);
+       if (priv->dp_modem_signals & TIOCM_CD)
+               return 1;
+       return 0;
+}
 
 static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
                                struct file *filp)
        unsigned char buf[32];
        struct digi_port *priv = usb_get_serial_port_data(port);
        struct ktermios not_termios;
-       unsigned long flags = 0;
 
        dbg("digi_open: TOP: port=%d, open_count=%d",
                priv->dp_port_num, port->port.count);
        if (digi_startup_device(port->serial) != 0)
                return -ENXIO;
 
-       spin_lock_irqsave(&priv->dp_port_lock, flags);
-
-       /* don't wait on a close in progress for non-blocking opens */
-       if (priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) {
-               spin_unlock_irqrestore(&priv->dp_port_lock, flags);
-               return -EAGAIN;
-       }
-
-       /* wait for a close in progress to finish */
-       while (priv->dp_in_close) {
-               cond_wait_interruptible_timeout_irqrestore(
-                       &priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
-                       &priv->dp_port_lock, flags);
-               if (signal_pending(current))
-                       return -EINTR;
-               spin_lock_irqsave(&priv->dp_port_lock, flags);
-       }
-
-       spin_unlock_irqrestore(&priv->dp_port_lock, flags);
-
        /* read modem signals automatically whenever they change */
        buf[0] = DIGI_CMD_READ_INPUT_SIGNALS;
        buf[1] = priv->dp_port_num;
                not_termios.c_iflag = ~tty->termios->c_iflag;
                digi_set_termios(tty, port, ¬_termios);
        }
-
-       /* set DTR and RTS */
-       digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1);
-
        return 0;
 }
 
 
-static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
-                               struct file *filp)
+static void digi_close(struct usb_serial_port *port)
 {
        DEFINE_WAIT(wait);
        int ret;
        if (port->serial->disconnected)
                goto exit;
 
-       /* do cleanup only after final close on this port */
-       spin_lock_irq(&priv->dp_port_lock);
-       priv->dp_in_close = 1;
-       spin_unlock_irq(&priv->dp_port_lock);
-
-       /* tell line discipline to process only XON/XOFF */
-       tty->closing = 1;
-
-       /* wait for output to drain */
-       if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0)
-               tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT);
-
-       /* flush driver and line discipline buffers */
-       tty_driver_flush_buffer(tty);
-       tty_ldisc_flush(tty);
-
        if (port->serial->dev) {
-               /* wait for transmit idle */
-               if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0)
-                       digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
-               /* drop DTR and RTS */
-               digi_set_modem_signals(port, 0, 0);
+               /* FIXME: Transmit idle belongs in the wait_unti_sent path */
+               digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
 
                /* disable input flow control */
                buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
                /* shutdown any outstanding bulk writes */
                usb_kill_urb(port->write_urb);
        }
-       tty->closing = 0;
 exit:
        spin_lock_irq(&priv->dp_port_lock);
        priv->dp_write_urb_in_use = 0;
-       priv->dp_in_close = 0;
        wake_up_interruptible(&priv->dp_close_wait);
        spin_unlock_irq(&priv->dp_port_lock);
        mutex_unlock(&port->serial->disc_mutex);
                priv->dp_throttled = 0;
                priv->dp_throttle_restart = 0;
                init_waitqueue_head(&priv->dp_flush_wait);
-               priv->dp_in_close = 0;
                init_waitqueue_head(&priv->dp_close_wait);
                INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
                priv->dp_port = serial->port[i];
 
 /* function prototypes for an empeg-car player */
 static int  empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
                                                struct file *filp);
-static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                               struct file *filp);
+static void empeg_close(struct usb_serial_port *port);
 static int  empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
                                                const unsigned char *buf,
                                                int count);
 }
 
 
-static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
-                               struct file *filp)
+static void empeg_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
 
 static int  ftdi_sio_port_remove(struct usb_serial_port *port);
 static int  ftdi_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void ftdi_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void ftdi_close(struct usb_serial_port *port);
+static void ftdi_dtr_rts(struct usb_serial_port *port, int on);
 static int  ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
                        const unsigned char *buf, int count);
 static int  ftdi_write_room(struct tty_struct *tty);
        .port_remove =          ftdi_sio_port_remove,
        .open =                 ftdi_open,
        .close =                ftdi_close,
+       .dtr_rts =              ftdi_dtr_rts,
        .throttle =             ftdi_throttle,
        .unthrottle =           ftdi_unthrottle,
        .write =                ftdi_write,
 } /* ftdi_open */
 
 
+static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct ftdi_private *priv = usb_get_serial_port_data(port);
+       char buf[1];
+
+       mutex_lock(&port->serial->disc_mutex);
+       if (!port->serial->disconnected) {
+               /* Disable flow control */
+               if (!on && usb_control_msg(port->serial->dev,
+                           usb_sndctrlpipe(port->serial->dev, 0),
+                           FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+                           FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+                           0, priv->interface, buf, 0,
+                           WDR_TIMEOUT) < 0) {
+                           dev_err(&port->dev, "error from flowcontrol urb\n");
+               }
+               /* drop RTS and DTR */
+               if (on)
+                       set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+               else
+                       clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+       }
+       mutex_unlock(&port->serial->disc_mutex);
+}
 
 /*
  * usbserial:__serial_close  only calls ftdi_close if the point is open
  *
  */
 
-static void ftdi_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void ftdi_close(struct usb_serial_port *port)
 { /* ftdi_close */
-       unsigned int c_cflag = tty->termios->c_cflag;
        struct ftdi_private *priv = usb_get_serial_port_data(port);
-       char buf[1];
 
        dbg("%s", __func__);
 
-       mutex_lock(&port->serial->disc_mutex);
-       if (c_cflag & HUPCL && !port->serial->disconnected) {
-               /* Disable flow control */
-               if (usb_control_msg(port->serial->dev,
-                                   usb_sndctrlpipe(port->serial->dev, 0),
-                                   FTDI_SIO_SET_FLOW_CTRL_REQUEST,
-                                   FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-                                   0, priv->interface, buf, 0,
-                                   WDR_TIMEOUT) < 0) {
-                       dev_err(&port->dev, "error from flowcontrol urb\n");
-               }
-
-               /* drop RTS and DTR */
-               clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-       } /* Note change no line if hupcl is off */
-       mutex_unlock(&port->serial->disc_mutex);
 
        /* cancel any scheduled reading */
        cancel_delayed_work_sync(&priv->rx_work);
 
 }
 
 
-static void garmin_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void garmin_close(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
        struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
 
-void usb_serial_generic_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+void usb_serial_generic_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
        generic_cleanup(port);
 
 /* function prototypes for the usbserial callbacks */
 static int edge_open(struct tty_struct *tty, struct usb_serial_port *port,
                                        struct file *filp);
-static void edge_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                       struct file *filp);
+static void edge_close(struct usb_serial_port *port);
 static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
                                        const unsigned char *buf, int count);
 static int edge_write_room(struct tty_struct *tty);
 
        if (!edge_port->txfifo.fifo) {
                dbg("%s - no memory", __func__);
-               edge_close(tty, port, filp);
+               edge_close(port);
                return -ENOMEM;
        }
 
 
        if (!edge_port->write_urb) {
                dbg("%s - no memory", __func__);
-               edge_close(tty, port, filp);
+               edge_close(port);
                return -ENOMEM;
        }
 
  * edge_close
  *     this function is called by the tty driver when a port is closed
  *****************************************************************************/
-static void edge_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void edge_close(struct usb_serial_port *port)
 {
        struct edgeport_serial *edge_serial;
        struct edgeport_port *edge_port;
 
        return status;
 }
 
-static void edge_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void edge_close(struct usb_serial_port *port)
 {
        struct edgeport_serial *edge_serial;
        struct edgeport_port *edge_port;
 
 /* Function prototypes for an ipaq */
 static int  ipaq_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void ipaq_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void ipaq_close(struct usb_serial_port *port);
 static int  ipaq_calc_num_ports(struct usb_serial *serial);
 static int  ipaq_startup(struct usb_serial *serial);
 static void ipaq_shutdown(struct usb_serial *serial);
 }
 
 
-static void ipaq_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void ipaq_close(struct usb_serial_port *port)
 {
        struct ipaq_private     *priv = usb_get_serial_port_data(port);
 
 
        return 0;
 }
 
-static void ipw_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void ipw_dtr_rts(struct usb_serial_port *port, int on)
 {
        struct usb_device *dev = port->serial->dev;
        int result;
 
-       if (tty_hung_up_p(filp)) {
-               dbg("%s: tty_hung_up_p ...", __func__);
-               return;
-       }
-
        /*--1: drop the dtr */
        dbg("%s:dropping dtr", __func__);
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                         IPW_SIO_SET_PIN,
                         USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-                        IPW_PIN_CLRDTR,
+                        on ? IPW_PIN_SETDTR : IPW_PIN_CLRDTR,
                         0,
                         NULL,
                         0,
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                         IPW_SIO_SET_PIN, USB_TYPE_VENDOR |
                                        USB_RECIP_INTERFACE | USB_DIR_OUT,
-                        IPW_PIN_CLRRTS,
+                        on ? IPW_PIN_SETRTS : IPW_PIN_CLRRTS,
                         0,
                         NULL,
                         0,
        if (result < 0)
                dev_err(&port->dev,
                                "dropping rts failed (error = %d)\n", result);
+}
 
+static void ipw_close(struct usb_serial_port *port)
+{
+       struct usb_device *dev = port->serial->dev;
+       int result;
 
        /*--3: purge */
        dbg("%s:sending purge", __func__);
        .num_ports =            1,
        .open =                 ipw_open,
        .close =                ipw_close,
+       .dtr_rts =              ipw_dtr_rts,
        .port_probe =           ipw_probe,
        .port_remove =          ipw_disconnect,
        .write =                ipw_write,
 
 static int  ir_startup (struct usb_serial *serial);
 static int  ir_open(struct tty_struct *tty, struct usb_serial_port *port,
                                        struct file *filep);
-static void ir_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                       struct file *filep);
+static void ir_close(struct usb_serial_port *port);
 static int  ir_write(struct tty_struct *tty, struct usb_serial_port *port,
                                        const unsigned char *buf, int count);
 static void ir_write_bulk_callback (struct urb *urb);
        return result;
 }
 
-static void ir_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file * filp)
+static void ir_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
 
 struct iuu_private {
        spinlock_t lock;        /* store irq state */
        wait_queue_head_t delta_msr_wait;
-       u8 line_control;
        u8 line_status;
        u8 termios_initialized;
        int tiostatus;          /* store IUART SIGNAL for tiocmget call */
        return status;
 }
 
-static int set_control_lines(struct usb_device *dev, u8 value)
-{
-       return 0;
-}
-
-static void iuu_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void iuu_close(struct usb_serial_port *port)
 {
        /* iuu_led (port,255,0,0,0); */
        struct usb_serial *serial;
-       struct iuu_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
-       unsigned int c_cflag;
 
        serial = port->serial;
        if (!serial)
 
        iuu_uart_off(port);
        if (serial->dev) {
-               if (tty) {
-                       c_cflag = tty->termios->c_cflag;
-                       if (c_cflag & HUPCL) {
-                               /* drop DTR and RTS */
-                               priv = usb_get_serial_port_data(port);
-                               spin_lock_irqsave(&priv->lock, flags);
-                               priv->line_control = 0;
-                               spin_unlock_irqrestore(&priv->lock, flags);
-                               set_control_lines(port->serial->dev, 0);
-                       }
-               }
                /* free writebuf */
                /* shutdown our urbs */
                dbg("%s - shutting down urbs", __func__);
        if (result) {
                dev_err(&port->dev, "%s - failed submitting read urb,"
                        " error %d\n", __func__, result);
-               iuu_close(tty, port, NULL);
+               iuu_close(port);
                return -EPROTO;
        } else {
                dbg("%s - rxcmd OK", __func__);
 
                usb_kill_urb(urb);
 }
 
-static void keyspan_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
+
+       p_priv->rts_state = on;
+       p_priv->dtr_state = on;
+       keyspan_send_setup(port, 0);
+}
+
+static void keyspan_close(struct usb_serial_port *port)
 {
        int                     i;
        struct usb_serial       *serial = port->serial;
                        stop_urb(p_priv->out_urbs[i]);
                }
        }
-       tty_port_tty_set(&port->port, NULL);
 }
 
 /* download the firmware to a pre-renumeration device */
 
 static int  keyspan_open               (struct tty_struct *tty,
                                         struct usb_serial_port *port,
                                         struct file *filp);
-static void keyspan_close              (struct tty_struct *tty,
-                                        struct usb_serial_port *port,
-                                        struct file *filp);
+static void keyspan_close              (struct usb_serial_port *port);
+static void keyspan_dtr_rts            (struct usb_serial_port *port, int on);
 static int  keyspan_startup            (struct usb_serial *serial);
 static void keyspan_shutdown           (struct usb_serial *serial);
 static int  keyspan_write_room         (struct tty_struct *tty);
        .num_ports              = 1,
        .open                   = keyspan_open,
        .close                  = keyspan_close,
+       .dtr_rts                = keyspan_dtr_rts,
        .write                  = keyspan_write,
        .write_room             = keyspan_write_room,
        .set_termios            = keyspan_set_termios,
        .num_ports              = 2,
        .open                   = keyspan_open,
        .close                  = keyspan_close,
+       .dtr_rts                = keyspan_dtr_rts,
        .write                  = keyspan_write,
        .write_room             = keyspan_write_room,
        .set_termios            = keyspan_set_termios,
        .num_ports              = 4,
        .open                   = keyspan_open,
        .close                  = keyspan_close,
+       .dtr_rts                = keyspan_dtr_rts,
        .write                  = keyspan_write,
        .write_room             = keyspan_write_room,
        .set_termios            = keyspan_set_termios,
 
 }
 
 
+static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct usb_serial *serial = port->serial;
+
+       if (serial->dev) {
+               if (on)
+                       keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2));
+               else
+                       keyspan_pda_set_modem_info(serial, 0);
+       }
+}
+
+static int keyspan_pda_carrier_raised(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
+       unsigned char modembits;
+
+       /* If we can read the modem status and the DCD is low then
+          carrier is not raised yet */
+       if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) {
+               if (!(modembits & (1>>6)))
+                       return 0;
+       }
+       /* Carrier raised, or we failed (eg disconnected) so
+          progress accordingly */
+       return 1;
+}
+
+
 static int keyspan_pda_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp)
 {
        priv->tx_room = room;
        priv->tx_throttled = room ? 0 : 1;
 
-       /* the normal serial device seems to always turn on DTR and RTS here,
-          so do the same */
-       if (tty && (tty->termios->c_cflag & CBAUD))
-               keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2));
-       else
-               keyspan_pda_set_modem_info(serial, 0);
-
        /*Start reading from the device*/
        port->interrupt_in_urb->dev = serial->dev;
        rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 error:
        return rc;
 }
-
-
-static void keyspan_pda_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void keyspan_pda_close(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
 
        if (serial->dev) {
-               /* the normal serial device seems to always shut
-                  off DTR and RTS now */
-               if (tty->termios->c_cflag & HUPCL)
-                       keyspan_pda_set_modem_info(serial, 0);
-
                /* shutdown our bulk reads and writes */
                usb_kill_urb(port->write_urb);
                usb_kill_urb(port->interrupt_in_urb);
        .usb_driver =           &keyspan_pda_driver,
        .id_table =             id_table_std,
        .num_ports =            1,
+       .dtr_rts =              keyspan_pda_dtr_rts,
+       .carrier_raised =       keyspan_pda_carrier_raised,
        .open =                 keyspan_pda_open,
        .close =                keyspan_pda_close,
        .write =                keyspan_pda_write,
 
 static void klsi_105_shutdown(struct usb_serial *serial);
 static int  klsi_105_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void klsi_105_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void klsi_105_close(struct usb_serial_port *port);
 static int  klsi_105_write(struct tty_struct *tty,
        struct usb_serial_port *port, const unsigned char *buf, int count);
 static void klsi_105_write_bulk_callback(struct urb *urb);
 } /* klsi_105_open */
 
 
-static void klsi_105_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void klsi_105_close(struct usb_serial_port *port)
 {
        struct klsi_105_private *priv = usb_get_serial_port_data(port);
        int rc;
 
 static void kobil_shutdown(struct usb_serial *serial);
 static int  kobil_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void kobil_close(struct tty_struct *tty, struct usb_serial_port *port,
-                       struct file *filp);
+static void kobil_close(struct usb_serial_port *port);
 static int  kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
                         const unsigned char *buf, int count);
 static int  kobil_write_room(struct tty_struct *tty);
 
        for (i = 0; i < serial->num_ports; ++i) {
                while (serial->port[i]->port.count > 0)
-                       kobil_close(NULL, serial->port[i], NULL);
+                       kobil_close(serial->port[i]);
                kfree(usb_get_serial_port_data(serial->port[i]));
                usb_set_serial_port_data(serial->port[i], NULL);
        }
 }
 
 
-static void kobil_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void kobil_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
+       /* FIXME: Add rts/dtr methods */
        if (port->write_urb) {
                usb_kill_urb(port->write_urb);
                usb_free_urb(port->write_urb);
 
 static void mct_u232_shutdown(struct usb_serial *serial);
 static int  mct_u232_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void mct_u232_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void mct_u232_close(struct usb_serial_port *port);
+static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
 static void mct_u232_read_int_callback(struct urb *urb);
 static void mct_u232_set_termios(struct tty_struct *tty,
                        struct usb_serial_port *port, struct ktermios *old);
        .num_ports =         1,
        .open =              mct_u232_open,
        .close =             mct_u232_close,
+       .dtr_rts =           mct_u232_dtr_rts,
        .throttle =          mct_u232_throttle,
        .unthrottle =        mct_u232_unthrottle,
        .read_int_callback = mct_u232_read_int_callback,
        return retval;
 } /* mct_u232_open */
 
-
-static void mct_u232_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
 {
-       unsigned int c_cflag;
        unsigned int control_state;
        struct mct_u232_private *priv = usb_get_serial_port_data(port);
-       dbg("%s port %d", __func__, port->number);
 
-       if (tty) {
-               c_cflag = tty->termios->c_cflag;
-               mutex_lock(&port->serial->disc_mutex);
-               if (c_cflag & HUPCL && !port->serial->disconnected) {
-                       /* drop DTR and RTS */
-                       spin_lock_irq(&priv->lock);
+       mutex_lock(&port->serial->disc_mutex);
+       if (!port->serial->disconnected) {
+               /* drop DTR and RTS */
+               spin_lock_irq(&priv->lock);
+               if (on)
+                       priv->control_state |= TIOCM_DTR | TIOCM_RTS;
+               else
                        priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-                       control_state = priv->control_state;
-                       spin_unlock_irq(&priv->lock);
-                       mct_u232_set_modem_ctrl(port->serial, control_state);
-               }
-               mutex_unlock(&port->serial->disc_mutex);
+               control_state = priv->control_state;
+               spin_unlock_irq(&priv->lock);
+               mct_u232_set_modem_ctrl(port->serial, control_state);
        }
+       mutex_unlock(&port->serial->disc_mutex);
+}
 
+static void mct_u232_close(struct usb_serial_port *port)
+{
+       dbg("%s port %d", __func__, port->number);
 
        if (port->serial->dev) {
                /* shutdown our urbs */
 
        return chars;
 }
 
-static void mos7720_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void mos7720_close(struct usb_serial_port *port)
 {
        struct usb_serial *serial;
        struct moschip_port *mos7720_port;
 
 
 }
 
-/************************************************************************
- *
- * mos7840_block_until_tx_empty
- *
- *     This function will block the close until one of the following:
- *             1. TX count are 0
- *             2. The mos7840 has stopped
- *             3. A timeout of 3 seconds without activity has expired
- *
- ************************************************************************/
-static void mos7840_block_until_tx_empty(struct tty_struct *tty,
-                               struct moschip_port *mos7840_port)
-{
-       int timeout = HZ / 10;
-       int wait = 30;
-       int count;
-
-       while (1) {
-
-               count = mos7840_chars_in_buffer(tty);
-
-               /* Check for Buffer status */
-               if (count <= 0)
-                       return;
-
-               /* Block the thread for a while */
-               interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
-                                              timeout);
-
-               /* No activity.. count down section */
-               wait--;
-               if (wait == 0) {
-                       dbg("%s - TIMEOUT", __func__);
-                       return;
-               } else {
-                       /* Reset timeout value back to seconds */
-                       wait = 30;
-               }
-       }
-}
-
 /*****************************************************************************
  * mos7840_close
  *     this function is called by the tty driver when a port is closed
  *****************************************************************************/
 
-static void mos7840_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void mos7840_close(struct usb_serial_port *port)
 {
        struct usb_serial *serial;
        struct moschip_port *mos7840_port;
                }
        }
 
-       if (serial->dev)
-               /* flush and block until tx is empty */
-               mos7840_block_until_tx_empty(tty, mos7840_port);
-
        /* While closing port, shutdown all bulk read, write  *
         * and interrupt read if they exists                  */
        if (serial->dev) {
 
        return result;
 }
 
-static void navman_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void navman_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
 
 /* function prototypes */
 static int  omninet_open(struct tty_struct *tty, struct usb_serial_port *port,
                                                        struct file *filp);
-static void omninet_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                                       struct file *filp);
+static void omninet_close(struct usb_serial_port *port);
 static void omninet_read_bulk_callback(struct urb *urb);
 static void omninet_write_bulk_callback(struct urb *urb);
 static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
        return result;
 }
 
-static void omninet_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void omninet_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
        usb_kill_urb(port->read_urb);
 
        return result;
 }
 
-static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port,
-                         struct file *filp)
+static void opticon_close(struct usb_serial_port *port)
 {
        struct opticon_private *priv = usb_get_serial_data(port->serial);
 
 
 /* Function prototypes */
 static int  option_open(struct tty_struct *tty, struct usb_serial_port *port,
                                                        struct file *filp);
-static void option_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                                       struct file *filp);
+static void option_close(struct usb_serial_port *port);
+static void option_dtr_rts(struct usb_serial_port *port, int on);
+
 static int  option_startup(struct usb_serial *serial);
 static void option_shutdown(struct usb_serial *serial);
 static int  option_write_room(struct tty_struct *tty);
 static int  option_tiocmget(struct tty_struct *tty, struct file *file);
 static int  option_tiocmset(struct tty_struct *tty, struct file *file,
                                unsigned int set, unsigned int clear);
-static int  option_send_setup(struct tty_struct *tty, struct usb_serial_port *port);
+static int  option_send_setup(struct usb_serial_port *port);
 static int  option_suspend(struct usb_serial *serial, pm_message_t message);
 static int  option_resume(struct usb_serial *serial);
 
        .num_ports         = 1,
        .open              = option_open,
        .close             = option_close,
+       .dtr_rts           = option_dtr_rts,
        .write             = option_write,
        .write_room        = option_write_room,
        .chars_in_buffer   = option_chars_in_buffer,
        dbg("%s", __func__);
        /* Doesn't support option setting */
        tty_termios_copy_hw(tty->termios, old_termios);
-       option_send_setup(tty, port);
+       option_send_setup(port);
 }
 
 static int option_tiocmget(struct tty_struct *tty, struct file *file)
                portdata->rts_state = 0;
        if (clear & TIOCM_DTR)
                portdata->dtr_state = 0;
-       return option_send_setup(tty, port);
+       return option_send_setup(port);
 }
 
 /* Write */
 
        dbg("%s", __func__);
 
-       /* Set some sane defaults */
-       portdata->rts_state = 1;
-       portdata->dtr_state = 1;
-
        /* Reset low level data toggle and start reading from endpoints */
        for (i = 0; i < N_IN_URB; i++) {
                urb = portdata->in_urbs[i];
                                usb_pipeout(urb->pipe), 0); */
        }
 
-       option_send_setup(tty, port);
+       option_send_setup(port);
 
        return 0;
 }
 
-static void option_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void option_dtr_rts(struct usb_serial_port *port, int on)
 {
-       int i;
        struct usb_serial *serial = port->serial;
        struct option_port_private *portdata;
 
        dbg("%s", __func__);
        portdata = usb_get_serial_port_data(port);
+       mutex_lock(&serial->disc_mutex);
+       portdata->rts_state = on;
+       portdata->dtr_state = on;
+       if (serial->dev)
+               option_send_setup(port);
+       mutex_unlock(&serial->disc_mutex);
+}
 
-       portdata->rts_state = 0;
-       portdata->dtr_state = 0;
 
-       if (serial->dev) {
-               mutex_lock(&serial->disc_mutex);
-               if (!serial->disconnected)
-                       option_send_setup(tty, port);
-               mutex_unlock(&serial->disc_mutex);
+static void option_close(struct usb_serial_port *port)
+{
+       int i;
+       struct usb_serial *serial = port->serial;
+       struct option_port_private *portdata;
+
+       dbg("%s", __func__);
+       portdata = usb_get_serial_port_data(port);
 
+       if (serial->dev) {
                /* Stop reading/writing urbs */
                for (i = 0; i < N_IN_URB; i++)
                        usb_kill_urb(portdata->in_urbs[i]);
                for (i = 0; i < N_OUT_URB; i++)
                        usb_kill_urb(portdata->out_urbs[i]);
        }
-       tty_port_tty_set(&port->port, NULL);
 }
 
 /* Helper functions used by option_setup_urbs */
  * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
  * CDC.
 */
-static int option_send_setup(struct tty_struct *tty,
-                                               struct usb_serial_port *port)
+static int option_send_setup(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
        struct option_port_private *portdata;
        int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+       int val = 0;
        dbg("%s", __func__);
 
        portdata = usb_get_serial_port_data(port);
 
-       if (tty) {
-               int val = 0;
-               if (portdata->dtr_state)
-                       val |= 0x01;
-               if (portdata->rts_state)
-                       val |= 0x02;
+       if (portdata->dtr_state)
+               val |= 0x01;
+       if (portdata->rts_state)
+               val |= 0x02;
 
-               return usb_control_msg(serial->dev,
-                       usb_rcvctrlpipe(serial->dev, 0),
-                       0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
-       }
-       return 0;
+       return usb_control_msg(serial->dev,
+               usb_rcvctrlpipe(serial->dev, 0),
+               0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
 }
 
 static int option_startup(struct usb_serial *serial)
 
 /* function prototypes */
 static int oti6858_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void oti6858_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void oti6858_close(struct usb_serial_port *port);
 static void oti6858_set_termios(struct tty_struct *tty,
                        struct usb_serial_port *port, struct ktermios *old);
 static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
        if (result != 0) {
                dev_err(&port->dev, "%s(): usb_submit_urb() failed"
                               " with error %d\n", __func__, result);
-               oti6858_close(tty, port, NULL);
+               oti6858_close(port);
                return -EPROTO;
        }
 
        /* setup termios */
        if (tty)
                oti6858_set_termios(tty, port, &tmp_termios);
-
+       port->port.drain_delay = 256;   /* FIXME: check the FIFO length */
        return 0;
 }
 
-static void oti6858_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void oti6858_close(struct usb_serial_port *port)
 {
        struct oti6858_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
-       long timeout;
-       wait_queue_t wait;
 
        dbg("%s(port = %d)", __func__, port->number);
 
-       /* wait for data to drain from the buffer */
        spin_lock_irqsave(&priv->lock, flags);
-       timeout = 30 * HZ;      /* PL2303_CLOSING_WAIT */
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&tty->write_wait, &wait);
-       dbg("%s(): entering wait loop", __func__);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (oti6858_buf_data_avail(priv->buf) == 0
-               || timeout == 0 || signal_pending(current)
-               || port->serial->disconnected)
-                       break;
-               spin_unlock_irqrestore(&priv->lock, flags);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irqsave(&priv->lock, flags);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&tty->write_wait, &wait);
-       dbg("%s(): after wait loop", __func__);
-
        /* clear out any remaining data in the buffer */
        oti6858_buf_clear(priv->buf);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* wait for characters to drain from the device */
-       /* (this is long enough for the entire 256 byte */
-       /* pl2303 hardware buffer to drain with no flow */
-       /* control for data rates of 1200 bps or more, */
-       /* for lower rates we should really know how much */
-       /* data is in the buffer to compute a delay */
-       /* that is not unnecessarily long) */
-       /* FIXME
-       bps = tty_get_baud_rate(tty);
-       if (bps > 1200)
-               timeout = max((HZ*2560)/bps,HZ/10);
-       else
-       */
-               timeout = 2*HZ;
-       schedule_timeout_interruptible(timeout);
-       dbg("%s(): after schedule_timeout_interruptible()", __func__);
+       dbg("%s(): after buf_clear()", __func__);
 
        /* cancel scheduled setup */
        cancel_delayed_work(&priv->delayed_setup_work);
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->interrupt_in_urb);
-
-       /*
-       if (tty && (tty->termios->c_cflag) & HUPCL) {
-               // drop DTR and RTS
-               spin_lock_irqsave(&priv->lock, flags);
-               priv->pending_setup.control &= ~CONTROL_MASK;
-               spin_unlock_irqrestore(&priv->lock, flags);
-       }
-       */
 }
 
 static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
 
        kfree(buf);
 }
 
-static void pl2303_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void pl2303_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       u8 control;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       /* Change DTR and RTS */
+       if (on)
+               priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+       else
+               priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+       control = priv->line_control;
+       spin_unlock_irqrestore(&priv->lock, flags);
+       set_control_lines(port->serial->dev, control);
+}
+
+static void pl2303_close(struct usb_serial_port *port)
 {
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
-       unsigned int c_cflag;
-       int bps;
-       long timeout;
-       wait_queue_t wait;
 
        dbg("%s - port %d", __func__, port->number);
 
-       /* wait for data to drain from the buffer */
        spin_lock_irqsave(&priv->lock, flags);
-       timeout = PL2303_CLOSING_WAIT;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&tty->write_wait, &wait);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (pl2303_buf_data_avail(priv->buf) == 0 ||
-                   timeout == 0 || signal_pending(current) ||
-                   port->serial->disconnected)
-                       break;
-               spin_unlock_irqrestore(&priv->lock, flags);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irqsave(&priv->lock, flags);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&tty->write_wait, &wait);
        /* clear out any remaining data in the buffer */
        pl2303_buf_clear(priv->buf);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* wait for characters to drain from the device */
-       /* (this is long enough for the entire 256 byte */
-       /* pl2303 hardware buffer to drain with no flow */
-       /* control for data rates of 1200 bps or more, */
-       /* for lower rates we should really know how much */
-       /* data is in the buffer to compute a delay */
-       /* that is not unnecessarily long) */
-       bps = tty_get_baud_rate(tty);
-       if (bps > 1200)
-               timeout = max((HZ*2560)/bps, HZ/10);
-       else
-               timeout = 2*HZ;
-       schedule_timeout_interruptible(timeout);
-
        /* shutdown our urbs */
        dbg("%s - shutting down urbs", __func__);
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->interrupt_in_urb);
 
-       if (tty) {
-               c_cflag = tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       /* drop DTR and RTS */
-                       spin_lock_irqsave(&priv->lock, flags);
-                       priv->line_control = 0;
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       set_control_lines(port->serial->dev, 0);
-               }
-       }
 }
 
 static int pl2303_open(struct tty_struct *tty,
        if (result) {
                dev_err(&port->dev, "%s - failed submitting read urb,"
                        " error %d\n", __func__, result);
-               pl2303_close(tty, port, NULL);
+               pl2303_close(port);
                return -EPROTO;
        }
 
        if (result) {
                dev_err(&port->dev, "%s - failed submitting interrupt urb,"
                        " error %d\n", __func__, result);
-               pl2303_close(tty, port, NULL);
+               pl2303_close(port);
                return -EPROTO;
        }
+       port->port.drain_delay = 256;
        return 0;
 }
 
        return result;
 }
 
+static int pl2303_carrier_raised(struct usb_serial_port *port)
+{
+       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       if (priv->line_status & UART_DCD)
+               return 1;
+       return 0;
+}
+
 static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 {
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        .num_ports =            1,
        .open =                 pl2303_open,
        .close =                pl2303_close,
+       .dtr_rts =              pl2303_dtr_rts,
+       .carrier_raised =       pl2303_carrier_raised,
        .write =                pl2303_write,
        .ioctl =                pl2303_ioctl,
        .break_ctl =            pl2303_break_ctl,
 
        int ri_state;
 };
 
-static int sierra_send_setup(struct tty_struct *tty,
-                                               struct usb_serial_port *port)
+static int sierra_send_setup(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
        struct sierra_port_private *portdata;
        __u16 interface = 0;
+       int val = 0;
 
        dev_dbg(&port->dev, "%s", __func__);
 
        portdata = usb_get_serial_port_data(port);
 
-       if (tty) {
-               int val = 0;
-               if (portdata->dtr_state)
-                       val |= 0x01;
-               if (portdata->rts_state)
-                       val |= 0x02;
-
-               /* If composite device then properly report interface */
-               if (serial->num_ports == 1) {
-                       interface = sierra_calc_interface(serial);
-
-                       /* Control message is sent only to interfaces with
-                        * interrupt_in endpoints
-                        */
-                       if (port->interrupt_in_urb) {
-                               /* send control message */
-                               return usb_control_msg(serial->dev,
-                                       usb_rcvctrlpipe(serial->dev, 0),
-                                       0x22, 0x21, val, interface,
-                                       NULL, 0, USB_CTRL_SET_TIMEOUT);
-                       }
-               }
-
-               /* Otherwise the need to do non-composite mapping */
-               else {
-                       if (port->bulk_out_endpointAddress == 2)
-                               interface = 0;
-                       else if (port->bulk_out_endpointAddress == 4)
-                               interface = 1;
-                       else if (port->bulk_out_endpointAddress == 5)
-                               interface = 2;
-
-                       return usb_control_msg(serial->dev,
-                               usb_rcvctrlpipe(serial->dev, 0),
-                               0x22, 0x21, val, interface,
-                               NULL, 0, USB_CTRL_SET_TIMEOUT);
-
-               }
+       if (portdata->dtr_state)
+               val |= 0x01;
+       if (portdata->rts_state)
+               val |= 0x02;
+
+       /* If composite device then properly report interface */
+       if (serial->num_ports == 1)
+               interface = sierra_calc_interface(serial);
+
+       /* Otherwise the need to do non-composite mapping */
+       else {
+               if (port->bulk_out_endpointAddress == 2)
+                       interface = 0;
+               else if (port->bulk_out_endpointAddress == 4)
+                       interface = 1;
+               else if (port->bulk_out_endpointAddress == 5)
+                       interface = 2;
        }
-
+       return usb_control_msg(serial->dev,
+                       usb_rcvctrlpipe(serial->dev, 0),
+                       0x22, 0x21, val, interface,
+                       NULL, 0, USB_CTRL_SET_TIMEOUT);
        return 0;
 }
 
 {
        dev_dbg(&port->dev, "%s", __func__);
        tty_termios_copy_hw(tty->termios, old_termios);
-       sierra_send_setup(tty, port);
+       sierra_send_setup(port);
 }
 
 static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
                portdata->rts_state = 0;
        if (clear & TIOCM_DTR)
                portdata->dtr_state = 0;
-       return sierra_send_setup(tty, port);
+       return sierra_send_setup(port);
 }
 
 static void sierra_outdat_callback(struct urb *urb)
                }
        }
 
-       sierra_send_setup(tty, port);
+       sierra_send_setup(port);
 
        /* start up the interrupt endpoint if we have one */
        if (port->interrupt_in_urb) {
        return 0;
 }
 
-static void sierra_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void sierra_dtr_rts(struct usb_serial_port *port, int on)
 {
-       int i;
        struct usb_serial *serial = port->serial;
        struct sierra_port_private *portdata;
 
-       dev_dbg(&port->dev, "%s", __func__);
        portdata = usb_get_serial_port_data(port);
-
-       portdata->rts_state = 0;
-       portdata->dtr_state = 0;
+       portdata->rts_state = on;
+       portdata->dtr_state = on;
 
        if (serial->dev) {
                mutex_lock(&serial->disc_mutex);
                if (!serial->disconnected)
-                       sierra_send_setup(tty, port);
+                       sierra_send_setup(port);
                mutex_unlock(&serial->disc_mutex);
+       }
+}
+
+static void sierra_close(struct usb_serial_port *port)
+{
+       int i;
+       struct usb_serial *serial = port->serial;
+       struct sierra_port_private *portdata;
 
+       dev_dbg(&port->dev, "%s", __func__);
+       portdata = usb_get_serial_port_data(port);
+
+       if (serial->dev) {
                /* Stop reading/writing urbs */
                for (i = 0; i < N_IN_URB; i++)
                        usb_kill_urb(portdata->in_urbs[i]);
        }
-
        usb_kill_urb(port->interrupt_in_urb);
-       tty_port_tty_set(&port->port, NULL);
 }
 
 static int sierra_startup(struct usb_serial *serial)
        .probe             = sierra_probe,
        .open              = sierra_open,
        .close             = sierra_close,
+       .dtr_rts           = sierra_dtr_rts,
        .write             = sierra_write,
        .write_room        = sierra_write_room,
        .set_termios       = sierra_set_termios,
 
                        "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
 }
 
+static int spcp8x5_carrier_raised(struct usb_serial_port *port)
+{
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       if (priv->line_status & MSR_STATUS_LINE_DCD)
+               return 1;
+       return 0;
+}
+
+static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       u8 control;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (on)
+               priv->line_control = MCR_CONTROL_LINE_DTR
+                                               | MCR_CONTROL_LINE_RTS;
+       else
+               priv->line_control &= ~ (MCR_CONTROL_LINE_DTR
+                                               | MCR_CONTROL_LINE_RTS);
+       control = priv->line_control;
+       spin_unlock_irqrestore(&priv->lock, flags);
+       spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+}
+
 /* close the serial port. We should wait for data sending to device 1st and
  * then kill all urb. */
-static void spcp8x5_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void spcp8x5_close(struct usb_serial_port *port)
 {
        struct spcp8x5_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
-       unsigned int c_cflag;
-       int bps;
-       long timeout;
-       wait_queue_t wait;
        int result;
 
        dbg("%s - port %d", __func__, port->number);
 
-       /* wait for data to drain from the buffer */
        spin_lock_irqsave(&priv->lock, flags);
-       timeout = SPCP8x5_CLOSING_WAIT;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&tty->write_wait, &wait);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (ringbuf_avail_data(priv->buf) == 0 ||
-                   timeout == 0 || signal_pending(current))
-                       break;
-               spin_unlock_irqrestore(&priv->lock, flags);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irqsave(&priv->lock, flags);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&tty->write_wait, &wait);
-
        /* clear out any remaining data in the buffer */
        clear_ringbuf(priv->buf);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* wait for characters to drain from the device (this is long enough
-        * for the entire all byte spcp8x5 hardware buffer to drain with no
-        * flow control for data rates of 1200 bps or more, for lower rates we
-        * should really know how much data is in the buffer to compute a delay
-        * that is not unnecessarily long) */
-       bps = tty_get_baud_rate(tty);
-       if (bps > 1200)
-               timeout = max((HZ*2560) / bps, HZ/10);
-       else
-               timeout = 2*HZ;
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout(timeout);
-
-       /* clear control lines */
-       if (tty) {
-               c_cflag = tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       spin_lock_irqsave(&priv->lock, flags);
-                       priv->line_control = 0;
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type);
-               }
-       }
-
        /* kill urb */
        if (port->write_urb != NULL) {
                result = usb_unlink_urb(port->write_urb);
        if (ret)
                return ret;
 
-       spin_lock_irqsave(&priv->lock, flags);
-       if (tty && (tty->termios->c_cflag & CBAUD))
-               priv->line_control = MCR_DTR | MCR_RTS;
-       else
-               priv->line_control = 0;
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
 
        /* Setup termios */
        port->read_urb->dev = serial->dev;
        ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (ret) {
-               spcp8x5_close(tty, port, NULL);
+               spcp8x5_close(port);
                return -EPROTO;
        }
+       port->port.drain_delay = 256;
        return 0;
 }
 
        .num_ports              = 1,
        .open                   = spcp8x5_open,
        .close                  = spcp8x5_close,
+       .dtr_rts                = spcp8x5_dtr_rts,
+       .carrier_raised         = spcp8x5_carrier_raised,
        .write                  = spcp8x5_write,
        .set_termios            = spcp8x5_set_termios,
        .ioctl                  = spcp8x5_ioctl,
 
        return result;
 }
 
-static void symbol_close(struct tty_struct *tty, struct usb_serial_port *port,
-                         struct file *filp)
+static void symbol_close(struct usb_serial_port *port)
 {
        struct symbol_private *priv = usb_get_serial_data(port->serial);
 
 
 static void ti_shutdown(struct usb_serial *serial);
 static int ti_open(struct tty_struct *tty, struct usb_serial_port *port,
                struct file *file);
-static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
-               struct file *file);
+static void ti_close(struct usb_serial_port *port);
 static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
                const unsigned char *data, int count);
 static int ti_write_room(struct tty_struct *tty);
 }
 
 
-static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                                       struct file *file)
+static void ti_close(struct usb_serial_port *port)
 {
        struct ti_device *tdev;
        struct ti_port *tport;
 
                        goto bailout_interface_put;
                mutex_unlock(&serial->disc_mutex);
        }
-
        mutex_unlock(&port->mutex);
-       return 0;
+       /* Now do the correct tty layer semantics */
+       retval = tty_port_block_til_ready(&port->port, tty, filp);
+       if (retval == 0)
+               return 0;
 
 bailout_interface_put:
        usb_autopm_put_interface(serial->interface);
        return retval;
 }
 
-static void serial_close(struct tty_struct *tty, struct file *filp)
+/**
+ *     serial_do_down          -       shut down hardware
+ *     @port: port to shut down
+ *
+ *     Shut down a USB port unless it is the console. We never shut down the
+ *     console hardware as it will always be in use.
+ *
+ *     Don't free any resources at this point
+ */
+static void serial_do_down(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = tty->driver_data;
+       struct usb_serial_driver *drv = port->serial->type;
        struct usb_serial *serial;
        struct module *owner;
-       int count;
 
-       if (!port)
+       /* The console is magical, do not hang up the console hardware
+          or there will be tears */
+       if (port->console)
                return;
 
-       dbg("%s - port %d", __func__, port->number);
-
        mutex_lock(&port->mutex);
        serial = port->serial;
        owner = serial->type->driver.owner;
 
-       if (port->port.count == 0) {
-               mutex_unlock(&port->mutex);
-               return;
-       }
-
-       if (port->port.count == 1)
-               /* only call the device specific close if this
-                * port is being closed by the last owner. Ensure we do
-                * this before we drop the port count. The call is protected
-                * by the port mutex
-                */
-               serial->type->close(tty, port, filp);
-
-       if (port->port.count == (port->console ? 2 : 1)) {
-               struct tty_struct *tty = tty_port_tty_get(&port->port);
-               if (tty) {
-                       /* We must do this before we drop the port count to
-                          zero. */
-                       if (tty->driver_data)
-                               tty->driver_data = NULL;
-                       tty_port_tty_set(&port->port, NULL);
-                       tty_kref_put(tty);
-               }
-       }
+       if (drv->close)
+               drv->close(port);
 
-       --port->port.count;
-       count = port->port.count;
        mutex_unlock(&port->mutex);
-       put_device(&port->dev);
+}
+
+/**
+ *     serial_do_free          -       free resources post close/hangup
+ *     @port: port to free up
+ *
+ *     Do the resource freeing and refcount dropping for the port. We must
+ *     be careful about ordering and we must avoid freeing up the console.
+ */
 
+static void serial_do_free(struct usb_serial_port *port)
+{
+       struct usb_serial *serial;
+       struct module *owner;
+
+       /* The console is magical, do not hang up the console hardware
+          or there will be tears */
+       if (port->console)
+               return;
+
+       serial = port->serial;
+       owner = serial->type->driver.owner;
+       put_device(&port->dev);
        /* Mustn't dereference port any more */
-       if (count == 0) {
-               mutex_lock(&serial->disc_mutex);
-               if (!serial->disconnected)
-                       usb_autopm_put_interface(serial->interface);
-               mutex_unlock(&serial->disc_mutex);
-       }
+       mutex_lock(&serial->disc_mutex);
+       if (!serial->disconnected)
+               usb_autopm_put_interface(serial->interface);
+       mutex_unlock(&serial->disc_mutex);
        usb_serial_put(serial);
-
        /* Mustn't dereference serial any more */
-       if (count == 0)
-               module_put(owner);
+       module_put(owner);
+}
+
+static void serial_close(struct tty_struct *tty, struct file *filp)
+{
+       struct usb_serial_port *port = tty->driver_data;
+
+       dbg("%s - port %d", __func__, port->number);
+
+
+       if (tty_port_close_start(&port->port, tty, filp) == 0)
+               return;
+
+       serial_do_down(port);           
+       tty_port_close_end(&port->port, tty);
+       tty_port_tty_set(&port->port, NULL);
+       serial_do_free(port);
+}
+
+static void serial_hangup(struct tty_struct *tty)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       serial_do_down(port);
+       tty_port_hangup(&port->port);
+       serial_do_free(port);
 }
 
 static int serial_write(struct tty_struct *tty, const unsigned char *buf,
        return NULL;
 }
 
+static int serial_carrier_raised(struct tty_port *port)
+{
+       struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
+       struct usb_serial_driver *drv = p->serial->type;
+       if (drv->carrier_raised)
+               return drv->carrier_raised(p);
+       /* No carrier control - don't block */
+       return 1;       
+}
+
+static void serial_dtr_rts(struct tty_port *port, int on)
+{
+       struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
+       struct usb_serial_driver *drv = p->serial->type;
+       if (drv->dtr_rts)
+               drv->dtr_rts(p, on);
+}
+
+static const struct tty_port_operations serial_port_ops = {
+       .carrier_raised = serial_carrier_raised,
+       .dtr_rts = serial_dtr_rts,
+};
+
 int usb_serial_probe(struct usb_interface *interface,
                               const struct usb_device_id *id)
 {
                if (!port)
                        goto probe_error;
                tty_port_init(&port->port);
+               port->port.ops = &serial_port_ops;
                port->serial = serial;
                spin_lock_init(&port->lock);
                mutex_init(&port->mutex);
                if (port) {
                        struct tty_struct *tty = tty_port_tty_get(&port->port);
                        if (tty) {
+                               /* The hangup will occur asynchronously but
+                                  the object refcounts will sort out all the
+                                  cleanup */
                                tty_hangup(tty);
                                tty_kref_put(tty);
                        }
        .open =                 serial_open,
        .close =                serial_close,
        .write =                serial_write,
+       .hangup =               serial_hangup,
        .write_room =           serial_write_room,
        .ioctl =                serial_ioctl,
        .set_termios =          serial_set_termios,
        .proc_fops =            &serial_proc_fops,
 };
 
+
 struct tty_driver *usb_serial_tty_driver;
 
 static int __init usb_serial_init(void)
 
 /* function prototypes for a handspring visor */
 static int  visor_open(struct tty_struct *tty, struct usb_serial_port *port,
                                        struct file *filp);
-static void visor_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                       struct file *filp);
+static void visor_close(struct usb_serial_port *port);
 static int  visor_write(struct tty_struct *tty, struct usb_serial_port *port,
                                        const unsigned char *buf, int count);
 static int  visor_write_room(struct tty_struct *tty);
 }
 
 
-static void visor_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void visor_close(struct usb_serial_port *port)
 {
        struct visor_private *priv = usb_get_serial_port_data(port);
        unsigned char *transfer_buffer;
 
 static void whiteheat_shutdown(struct usb_serial *serial);
 static int  whiteheat_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void whiteheat_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void whiteheat_close(struct usb_serial_port *port);
 static int  whiteheat_write(struct tty_struct *tty,
                        struct usb_serial_port *port,
                        const unsigned char *buf, int count);
 }
 
 
-static void whiteheat_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void whiteheat_close(struct usb_serial_port *port)
 {
        struct whiteheat_private *info = usb_get_serial_port_data(port);
        struct whiteheat_urb_wrap *wrap;
 
        dbg("%s - port %d", __func__, port->number);
 
-       mutex_lock(&port->serial->disc_mutex);
-       /* filp is NULL when called from usb_serial_disconnect */
-       if ((filp && (tty_hung_up_p(filp))) || port->serial->disconnected) {
-               mutex_unlock(&port->serial->disc_mutex);
-               return;
-       }
-       mutex_unlock(&port->serial->disc_mutex);
-
-       tty->closing = 1;
-
-/*
- * Not currently in use; tty_wait_until_sent() calls
- * serial_chars_in_buffer() which deadlocks on the second semaphore
- * acquisition. This should be fixed at some point. Greg's been
- * notified.
-       if ((filp->f_flags & (O_NDELAY | O_NONBLOCK)) == 0) {
-               tty_wait_until_sent(tty, CLOSING_DELAY);
-       }
-*/
-
-       tty_driver_flush_buffer(tty);
-       tty_ldisc_flush(tty);
-
        firm_report_tx_done(port);
-
        firm_close(port);
 
        /* shutdown our bulk reads and writes */
        }
        spin_unlock_irq(&info->lock);
        mutex_unlock(&info->deathwarrant);
-
        stop_command_port(port->serial);
-
-       tty->closing = 0;
 }
 
 
 
        /* Called by console with tty = NULL and by tty */
        int  (*open)(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-       void (*close)(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+       void (*close)(struct usb_serial_port *port);
        int  (*write)(struct tty_struct *tty, struct usb_serial_port *port,
                        const unsigned char *buf, int count);
        /* Called only by the tty layer */
        int  (*tiocmget)(struct tty_struct *tty, struct file *file);
        int  (*tiocmset)(struct tty_struct *tty, struct file *file,
                         unsigned int set, unsigned int clear);
+       /* Called by the tty layer for port level work. There may or may not
+          be an attached tty at this point */
+       void (*dtr_rts)(struct usb_serial_port *port, int on);
+       int  (*carrier_raised)(struct usb_serial_port *port);
        /* USB events */
        void (*read_int_callback)(struct urb *urb);
        void (*write_int_callback)(struct urb *urb);
                struct usb_serial_port *port, struct file *filp);
 extern int usb_serial_generic_write(struct tty_struct *tty,
        struct usb_serial_port *port, const unsigned char *buf, int count);
-extern void usb_serial_generic_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+extern void usb_serial_generic_close(struct usb_serial_port *port);
 extern int usb_serial_generic_resume(struct usb_serial *serial);
 extern int usb_serial_generic_write_room(struct tty_struct *tty);
 extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);