tty: Add carrier processing on close to the tty_port core
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Thu, 11 Jun 2009 11:24:17 +0000 (12:24 +0100)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 11 Jun 2009 15:50:56 +0000 (08:50 -0700)
Some drivers implement this internally, others miss it out. Push the
behaviour into the core code as that way everyone will do it consistently.

Update the dtr rts method to raise or lower depending upon flags. Having a
single method in this style fits most of the implementations more cleanly than
two funtions.

We need this in place before we tackle the USB side

Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
12 files changed:
drivers/char/epca.c
drivers/char/isicom.c
drivers/char/istallion.c
drivers/char/mxser.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/rocket.c
drivers/char/stallion.c
drivers/char/synclink.c
drivers/char/synclink_gt.c
drivers/char/synclinkmp.c
drivers/char/tty_port.c
include/linux/tty.h

index af7c13ca949377da39751cb78df840b21de7ff32..8797b774235053e873f81df29020da6110777198 100644 (file)
@@ -745,7 +745,7 @@ static int epca_carrier_raised(struct tty_port *port)
        return 0;
 }
 
-static void epca_raise_dtr_rts(struct tty_port *port)
+static void epca_dtr_rts(struct tty_port *port, int onoff)
 {
 }
 
@@ -925,7 +925,7 @@ static const struct tty_operations pc_ops = {
 
 static const struct tty_port_operations epca_port_ops = {
        .carrier_raised = epca_carrier_raised,
-       .raise_dtr_rts = epca_raise_dtr_rts,
+       .dtr_rts = epca_dtr_rts,
 };
 
 static int info_open(struct tty_struct *tty, struct file *filp)
index a59eac584d1621b3e4824ca3e644d944a31266a6..4d745a89504f196cc545145ca4bd653c4927ad0b 100644 (file)
@@ -329,7 +329,7 @@ static inline void drop_rts(struct isi_port *port)
 
 /* card->lock MUST NOT be held */
 
-static void isicom_raise_dtr_rts(struct tty_port *port)
+static void isicom_dtr_rts(struct tty_port *port, int on)
 {
        struct isi_port *ip = container_of(port, struct isi_port, port);
        struct isi_board *card = ip->card;
@@ -339,10 +339,17 @@ static void isicom_raise_dtr_rts(struct tty_port *port)
        if (!lock_card(card))
                return;
 
-       outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-       outw(0x0f04, base);
-       InterruptTheCard(base);
-       ip->status |= (ISI_DTR | ISI_RTS);
+       if (on) {
+               outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+               outw(0x0f04, base);
+               InterruptTheCard(base);
+               ip->status |= (ISI_DTR | ISI_RTS);
+       } else {
+               outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+               outw(0x0C04, base);
+               InterruptTheCard(base);
+               ip->status &= ~(ISI_DTR | ISI_RTS);
+       }
        unlock_card(card);
 }
 
@@ -1339,7 +1346,7 @@ static const struct tty_operations isicom_ops = {
 
 static const struct tty_port_operations isicom_port_ops = {
        .carrier_raised         = isicom_carrier_raised,
-       .raise_dtr_rts          = isicom_raise_dtr_rts,
+       .dtr_rts                = isicom_dtr_rts,
 };
 
 static int __devinit reset_card(struct pci_dev *pdev,
index fff19f7e29d25eac8c7cfbb4903638107dd8561c..e18800c400b10b60578b6fb9bb1d86a16dcbfd04 100644 (file)
@@ -1140,14 +1140,14 @@ static int stli_carrier_raised(struct tty_port *port)
        return (portp->sigs & TIOCM_CD) ? 1 : 0;
 }
 
-static void stli_raise_dtr_rts(struct tty_port *port)
+static void stli_dtr_rts(struct tty_port *port, int on)
 {
        struct stliport *portp = container_of(port, struct stliport, port);
        struct stlibrd *brdp = stli_brds[portp->brdnr];
-       stli_mkasysigs(&portp->asig, 1, 1);
+       stli_mkasysigs(&portp->asig, on, on);
        if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
                sizeof(asysigs_t), 0) < 0)
-                       printk(KERN_WARNING "istallion: dtr raise failed.\n");
+                       printk(KERN_WARNING "istallion: dtr set failed.\n");
 }
 
 
@@ -4417,7 +4417,7 @@ static const struct tty_operations stli_ops = {
 
 static const struct tty_port_operations stli_port_ops = {
        .carrier_raised = stli_carrier_raised,
-       .raise_dtr_rts = stli_raise_dtr_rts,
+       .dtr_rts = stli_dtr_rts,
 };
 
 /*****************************************************************************/
index 13f8871e5b2177bb844018f6543ca2e690e973b6..9533f43a30bb0e7bad9873acb85d25cf39e44625 100644 (file)
@@ -547,14 +547,18 @@ static int mxser_carrier_raised(struct tty_port *port)
        return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
 }
 
-static void mxser_raise_dtr_rts(struct tty_port *port)
+static void mxser_dtr_rts(struct tty_port *port, int on)
 {
        struct mxser_port *mp = container_of(port, struct mxser_port, port);
        unsigned long flags;
 
        spin_lock_irqsave(&mp->slock, flags);
-       outb(inb(mp->ioaddr + UART_MCR) |
-               UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
+       if (on)
+               outb(inb(mp->ioaddr + UART_MCR) |
+                       UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
+       else
+               outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS),
+                       mp->ioaddr + UART_MCR);
        spin_unlock_irqrestore(&mp->slock, flags);
 }
 
@@ -2356,7 +2360,7 @@ static const struct tty_operations mxser_ops = {
 
 struct tty_port_operations mxser_port_ops = {
        .carrier_raised = mxser_carrier_raised,
-       .raise_dtr_rts = mxser_raise_dtr_rts,
+       .dtr_rts = mxser_dtr_rts,
 };
 
 /*
index 19d79fc54461c592111fbce5d0e68e395e10dcd4..77b3648892249f494724bf2a6302bdfc9158c4c5 100644 (file)
@@ -383,7 +383,7 @@ static void async_mode(MGSLPC_INFO *info);
 static void tx_timeout(unsigned long context);
 
 static int carrier_raised(struct tty_port *port);
-static void raise_dtr_rts(struct tty_port *port);
+static void dtr_rts(struct tty_port *port, int onoff);
 
 #if SYNCLINK_GENERIC_HDLC
 #define dev_to_port(D) (dev_to_hdlc(D)->priv)
@@ -513,7 +513,7 @@ static void ldisc_receive_buf(struct tty_struct *tty,
 
 static const struct tty_port_operations mgslpc_port_ops = {
        .carrier_raised = carrier_raised,
-       .raise_dtr_rts = raise_dtr_rts
+       .dtr_rts = dtr_rts
 };
 
 static int mgslpc_probe(struct pcmcia_device *link)
@@ -2528,13 +2528,16 @@ static int carrier_raised(struct tty_port *port)
        return 0;
 }
 
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int onoff)
 {
        MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port);
        unsigned long flags;
 
        spin_lock_irqsave(&info->lock,flags);
-       info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+       if (onoff)
+               info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+       else
+               info->serial_signals &= ~SerialSignal_RTS + SerialSignal_DTR;
        set_signals(info);
        spin_unlock_irqrestore(&info->lock,flags);
 }
index f59fc5cea0673546fa03b0395a8d12b6f7872ff4..7399188049d84a8688e15ed8f8675d70940a0615 100644 (file)
@@ -872,11 +872,16 @@ static int carrier_raised(struct tty_port *port)
        return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0;
 }
 
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
 {
        struct r_port *info = container_of(port, struct r_port, port);
-       sSetDTR(&info->channel);
-       sSetRTS(&info->channel);
+       if (on) {
+               sSetDTR(&info->channel);
+               sSetRTS(&info->channel);
+       } else {
+               sClrDTR(&info->channel);
+               sClrRTS(&info->channel);
+       }
 }
 
 /*
@@ -2250,7 +2255,7 @@ static const struct tty_operations rocket_ops = {
 
 static const struct tty_port_operations rocket_port_ops = {
        .carrier_raised = carrier_raised,
-       .raise_dtr_rts = raise_dtr_rts,
+       .dtr_rts = dtr_rts,
 };
 
 /*
index 2ad813a801dc391cc8bca62a4cc847b16ea0d4d1..53e504f41b2043fa89b4b9a83637fe31251d38ab 100644 (file)
@@ -772,11 +772,11 @@ static int stl_carrier_raised(struct tty_port *port)
        return (portp->sigs & TIOCM_CD) ? 1 : 0;
 }
 
-static void stl_raise_dtr_rts(struct tty_port *port)
+static void stl_dtr_rts(struct tty_port *port, int on)
 {
        struct stlport *portp = container_of(port, struct stlport, port);
        /* Takes brd_lock internally */
-       stl_setsignals(portp, 1, 1);
+       stl_setsignals(portp, on, on);
 }
 
 /*****************************************************************************/
@@ -2547,7 +2547,7 @@ static const struct tty_operations stl_ops = {
 
 static const struct tty_port_operations stl_port_ops = {
        .carrier_raised = stl_carrier_raised,
-       .raise_dtr_rts = stl_raise_dtr_rts,
+       .dtr_rts = stl_dtr_rts,
 };
 
 /*****************************************************************************/
index afd0b26ca05681210edd0cc0f22b01497eea3e37..afded3a2379c592082e85e373236addce5d9fcd3 100644 (file)
@@ -3247,13 +3247,16 @@ static int carrier_raised(struct tty_port *port)
        return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
 }
 
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
 {
        struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
        unsigned long flags;
 
        spin_lock_irqsave(&info->irq_spinlock,flags);
-       info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+       if (on)
+               info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+       else
+               info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
        usc_set_serial_signals(info);
        spin_unlock_irqrestore(&info->irq_spinlock,flags);
 }
@@ -4258,7 +4261,7 @@ static void mgsl_add_device( struct mgsl_struct *info )
 
 static const struct tty_port_operations mgsl_port_ops = {
        .carrier_raised = carrier_raised,
-       .raise_dtr_rts = raise_dtr_rts,
+       .dtr_rts = dtr_rts,
 };
 
 
index 5e256494686a8413734db27db5b9826069e36847..67986ea0d479cea42ddd0ddde8ccd5fae30a8386 100644 (file)
@@ -3099,13 +3099,16 @@ static int carrier_raised(struct tty_port *port)
        return (info->signals & SerialSignal_DCD) ? 1 : 0;
 }
 
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
 {
        unsigned long flags;
        struct slgt_info *info = container_of(port, struct slgt_info, port);
 
        spin_lock_irqsave(&info->lock,flags);
-       info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+       if (on)
+               info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+       else
+               info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
        set_signals(info);
        spin_unlock_irqrestore(&info->lock,flags);
 }
@@ -3419,7 +3422,7 @@ static void add_device(struct slgt_info *info)
 
 static const struct tty_port_operations slgt_port_ops = {
        .carrier_raised = carrier_raised,
-       .raise_dtr_rts = raise_dtr_rts,
+       .dtr_rts = dtr_rts,
 };
 
 /*
index 26de60efe4b247162c3be863bb3a3c66d86d6c49..6f727e3c53ade1028d21cf11f364bdcc2fafbed9 100644 (file)
@@ -3277,13 +3277,16 @@ static int carrier_raised(struct tty_port *port)
        return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
 }
 
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
 {
        SLMP_INFO *info = container_of(port, SLMP_INFO, port);
        unsigned long flags;
 
        spin_lock_irqsave(&info->lock,flags);
-       info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+       if (on)
+               info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+       else
+               info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
        set_signals(info);
        spin_unlock_irqrestore(&info->lock,flags);
 }
@@ -3746,7 +3749,7 @@ static void add_device(SLMP_INFO *info)
 
 static const struct tty_port_operations port_ops = {
        .carrier_raised = carrier_raised,
-       .raise_dtr_rts = raise_dtr_rts,
+       .dtr_rts = dtr_rts,
 };
 
 /* Allocate and initialize a device instance structure
index 9b8004c72686a45f6ea577f1cd342e001dbbfa49..926d4a5593fac0f0d1c4033252efe32e23564a7a 100644 (file)
@@ -137,7 +137,7 @@ int tty_port_carrier_raised(struct tty_port *port)
 EXPORT_SYMBOL(tty_port_carrier_raised);
 
 /**
- *     tty_port_raise_dtr_rts  -       Riase DTR/RTS
+ *     tty_port_raise_dtr_rts  -       Raise DTR/RTS
  *     @port: tty port
  *
  *     Wrapper for the DTR/RTS raise logic. For the moment this is used
@@ -147,11 +147,27 @@ EXPORT_SYMBOL(tty_port_carrier_raised);
 
 void tty_port_raise_dtr_rts(struct tty_port *port)
 {
-       if (port->ops->raise_dtr_rts)
-               port->ops->raise_dtr_rts(port);
+       if (port->ops->dtr_rts)
+               port->ops->dtr_rts(port, 1);
 }
 EXPORT_SYMBOL(tty_port_raise_dtr_rts);
 
+/**
+ *     tty_port_lower_dtr_rts  -       Lower DTR/RTS
+ *     @port: tty port
+ *
+ *     Wrapper for the DTR/RTS raise logic. For the moment this is used
+ *     to hide some internal details. This will eventually become entirely
+ *     internal to the tty port.
+ */
+
+void tty_port_lower_dtr_rts(struct tty_port *port)
+{
+       if (port->ops->dtr_rts)
+               port->ops->dtr_rts(port, 0);
+}
+EXPORT_SYMBOL(tty_port_lower_dtr_rts);
+
 /**
  *     tty_port_block_til_ready        -       Waiting logic for tty open
  *     @port: the tty port being opened
@@ -167,7 +183,7 @@ EXPORT_SYMBOL(tty_port_raise_dtr_rts);
  *             - port flags and counts
  *
  *     The passed tty_port must implement the carrier_raised method if it can
- *     do carrier detect and the raise_dtr_rts method if it supports software
+ *     do carrier detect and the dtr_rts method if it supports software
  *     management of these lines. Note that the dtr/rts raise is done each
  *     iteration as a hangup may have previously dropped them while we wait.
  */
@@ -302,6 +318,9 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
 
        tty_ldisc_flush(tty);
 
+       if (tty->termios->c_cflag & HUPCL)
+               tty_port_lower_dtr_rts(port);
+
        spin_lock_irqsave(&port->lock, flags);
        tty->closing = 0;
 
index fc39db95499fbab4142800b24faf52b182fae113..98694364c96fdef164b4e790a5eb58e42a2e7497 100644 (file)
@@ -185,7 +185,7 @@ struct tty_port;
 struct tty_port_operations {
        /* Return 1 if the carrier is raised */
        int (*carrier_raised)(struct tty_port *port);
-       void (*raise_dtr_rts)(struct tty_port *port);
+       void (*dtr_rts)(struct tty_port *port, int raise);
 };
        
 struct tty_port {
@@ -438,6 +438,7 @@ extern struct tty_struct *tty_port_tty_get(struct tty_port *port);
 extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
 extern int tty_port_carrier_raised(struct tty_port *port);
 extern void tty_port_raise_dtr_rts(struct tty_port *port);
+extern void tty_port_lower_dtr_rts(struct tty_port *port);
 extern void tty_port_hangup(struct tty_port *port);
 extern int tty_port_block_til_ready(struct tty_port *port,
                                struct tty_struct *tty, struct file *filp);