Skip to content

Commit

Permalink
tty: Add carrier processing on close to the tty_port core
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Alan-Cox authored and torvalds committed Jun 11, 2009
1 parent 65a29f6 commit fcc8ac1
Show file tree
Hide file tree
Showing 12 changed files with 89 additions and 41 deletions.
4 changes: 2 additions & 2 deletions drivers/char/epca.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
}

Expand Down Expand Up @@ -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)
Expand Down
19 changes: 13 additions & 6 deletions drivers/char/isicom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}

Expand Down Expand Up @@ -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,
Expand Down
8 changes: 4 additions & 4 deletions drivers/char/istallion.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}


Expand Down Expand Up @@ -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,
};

/*****************************************************************************/
Expand Down
12 changes: 8 additions & 4 deletions drivers/char/mxser.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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,
};

/*
Expand Down
11 changes: 7 additions & 4 deletions drivers/char/pcmcia/synclink_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand Down
13 changes: 9 additions & 4 deletions drivers/char/rocket.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

/*
Expand Down Expand Up @@ -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,
};

/*
Expand Down
6 changes: 3 additions & 3 deletions drivers/char/stallion.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/*****************************************************************************/
Expand Down Expand Up @@ -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,
};

/*****************************************************************************/
Expand Down
9 changes: 6 additions & 3 deletions drivers/char/synclink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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,
};


Expand Down
9 changes: 6 additions & 3 deletions drivers/char/synclink_gt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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,
};

/*
Expand Down
9 changes: 6 additions & 3 deletions drivers/char/synclinkmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand Down
27 changes: 23 additions & 4 deletions drivers/char/tty_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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.
*/
Expand Down Expand Up @@ -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;

Expand Down
3 changes: 2 additions & 1 deletion include/linux/tty.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit fcc8ac1

Please sign in to comment.