aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2009-06-11 12:24:17 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-11 08:50:56 -0700
commitfcc8ac1825d3d0fb81f73bc1a80ebc863168bb56 (patch)
tree737f7209430fd319ca257df62c9b1e64587d5a8b
parent65a29f60e121ae5116ac1736b50a237bf2db3225 (diff)
tty: Add carrier processing on close to the tty_port core
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>
-rw-r--r--drivers/char/epca.c4
-rw-r--r--drivers/char/isicom.c19
-rw-r--r--drivers/char/istallion.c8
-rw-r--r--drivers/char/mxser.c12
-rw-r--r--drivers/char/pcmcia/synclink_cs.c11
-rw-r--r--drivers/char/rocket.c13
-rw-r--r--drivers/char/stallion.c6
-rw-r--r--drivers/char/synclink.c9
-rw-r--r--drivers/char/synclink_gt.c9
-rw-r--r--drivers/char/synclinkmp.c9
-rw-r--r--drivers/char/tty_port.c27
-rw-r--r--include/linux/tty.h3
12 files changed, 89 insertions, 41 deletions
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index af7c13ca949..8797b774235 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -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)
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index a59eac584d1..4d745a89504 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -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,
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index fff19f7e29d..e18800c400b 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -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,
};
/*****************************************************************************/
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 13f8871e5b2..9533f43a30b 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -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,
};
/*
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 19d79fc5446..77b36488922 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -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);
}
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index f59fc5cea06..7399188049d 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -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,
};
/*
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 2ad813a801d..53e504f41b2 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -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,
};
/*****************************************************************************/
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index afd0b26ca05..afded3a2379 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -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,
};
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 5e256494686..67986ea0d47 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -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,
};
/*
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 26de60efe4b..6f727e3c53a 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -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
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index 9b8004c7268..926d4a5593f 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -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,12 +147,28 @@ 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
* @tty: the tty device being bound
@@ -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;
diff --git a/include/linux/tty.h b/include/linux/tty.h
index fc39db95499..98694364c96 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -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);