Skip to content

Commit

Permalink
[SERIAL] Clean up and fix tty transmission start/stoping
Browse files Browse the repository at this point in the history
The start_tx and stop_tx methods were passed a flag to indicate
whether the start/stop was from the tty start/stop callbacks, and
some drivers used this flag to decide whether to ask the UART to
immediately stop transmission (where the UART supports such a
feature.)

There are other cases when we wish this to occur - when CTS is
lowered, or if we change from soft to hard flow control and CTS
is inactive.  In these cases, this flag was false, and we would
allow the transmitter to drain before stopping.

There is really only one case where we want to let the transmitter
drain before disabling, and that's when we run out of characters
to send.

Hence, re-jig the start_tx and stop_tx methods to eliminate this
flag, and introduce new functions for the special "disable and
allow transmitter to drain" case.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Russell King authored and Russell King committed Aug 31, 2005
2 parents 6b39374 + 194d071 commit b129a8c
Show file tree
Hide file tree
Showing 34 changed files with 149 additions and 158 deletions.
15 changes: 4 additions & 11 deletions Documentation/serial/driver
Original file line number Diff line number Diff line change
Expand Up @@ -111,24 +111,17 @@ hardware.
Interrupts: locally disabled.
This call must not sleep

stop_tx(port,tty_stop)
stop_tx(port)
Stop transmitting characters. This might be due to the CTS
line becoming inactive or the tty layer indicating we want
to stop transmission.

tty_stop: 1 if this call is due to the TTY layer issuing a
TTY stop to the driver (equiv to rs_stop).
to stop transmission due to an XOFF character.

Locking: port->lock taken.
Interrupts: locally disabled.
This call must not sleep

start_tx(port,tty_start)
start transmitting characters. (incidentally, nonempty will
always be nonzero, and shouldn't be used - it will be dropped).

tty_start: 1 if this call was due to the TTY layer issuing
a TTY start to the driver (equiv to rs_start)
start_tx(port)
start transmitting characters.

Locking: port->lock taken.
Interrupts: locally disabled.
Expand Down
10 changes: 4 additions & 6 deletions drivers/serial/21285.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,15 @@ static const char serial21285_name[] = "Footbridge UART";
* int((BAUD_BASE - (baud >> 1)) / baud)
*/

static void
serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop)
static void serial21285_stop_tx(struct uart_port *port)
{
if (tx_enabled(port)) {
disable_irq(IRQ_CONTX);
tx_enabled(port) = 0;
}
}

static void
serial21285_start_tx(struct uart_port *port, unsigned int tty_start)
static void serial21285_start_tx(struct uart_port *port)
{
if (!tx_enabled(port)) {
enable_irq(IRQ_CONTX);
Expand Down Expand Up @@ -148,7 +146,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r
goto out;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
serial21285_stop_tx(port, 0);
serial21285_stop_tx(port);
goto out;
}

Expand All @@ -164,7 +162,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r
uart_write_wakeup(port);

if (uart_circ_empty(xmit))
serial21285_stop_tx(port, 0);
serial21285_stop_tx(port);

out:
return IRQ_HANDLED;
Expand Down
10 changes: 7 additions & 3 deletions drivers/serial/8250.c
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ static inline void __stop_tx(struct uart_8250_port *p)
}
}

static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
static void serial8250_stop_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;

Expand All @@ -1018,7 +1018,7 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)

static void transmit_chars(struct uart_8250_port *up);

static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;

Expand Down Expand Up @@ -1158,7 +1158,11 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
up->port.x_char = 0;
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
if (uart_tx_stopped(&up->port)) {
serial8250_stop_tx(&up->port);
return;
}
if (uart_circ_empty(xmit)) {
__stop_tx(up);
return;
}
Expand Down
8 changes: 4 additions & 4 deletions drivers/serial/amba-pl010.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ struct uart_amba_port {
unsigned int old_status;
};

static void pl010_stop_tx(struct uart_port *port, unsigned int tty_stop)
static void pl010_stop_tx(struct uart_port *port)
{
unsigned int cr;

Expand All @@ -114,7 +114,7 @@ static void pl010_stop_tx(struct uart_port *port, unsigned int tty_stop)
UART_PUT_CR(port, cr);
}

static void pl010_start_tx(struct uart_port *port, unsigned int tty_start)
static void pl010_start_tx(struct uart_port *port)
{
unsigned int cr;

Expand Down Expand Up @@ -219,7 +219,7 @@ static void pl010_tx_chars(struct uart_port *port)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
pl010_stop_tx(port, 0);
pl010_stop_tx(port);
return;
}

Expand All @@ -236,7 +236,7 @@ static void pl010_tx_chars(struct uart_port *port)
uart_write_wakeup(port);

if (uart_circ_empty(xmit))
pl010_stop_tx(port, 0);
pl010_stop_tx(port);
}

static void pl010_modem_status(struct uart_port *port)
Expand Down
8 changes: 4 additions & 4 deletions drivers/serial/amba-pl011.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ struct uart_amba_port {
unsigned int old_status;
};

static void pl011_stop_tx(struct uart_port *port, unsigned int tty_stop)
static void pl011_stop_tx(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;

uap->im &= ~UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC);
}

static void pl011_start_tx(struct uart_port *port, unsigned int tty_start)
static void pl011_start_tx(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;

Expand Down Expand Up @@ -184,7 +184,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
pl011_stop_tx(&uap->port, 0);
pl011_stop_tx(&uap->port);
return;
}

Expand All @@ -201,7 +201,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap)
uart_write_wakeup(&uap->port);

if (uart_circ_empty(xmit))
pl011_stop_tx(&uap->port, 0);
pl011_stop_tx(&uap->port);
}

static void pl011_modem_status(struct uart_amba_port *uap)
Expand Down
8 changes: 4 additions & 4 deletions drivers/serial/au1x00_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
}

static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
static void serial8250_stop_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;

Expand All @@ -210,7 +210,7 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}

static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;

Expand Down Expand Up @@ -337,7 +337,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
serial8250_stop_tx(&up->port, 0);
serial8250_stop_tx(&up->port);
return;
}

Expand All @@ -356,7 +356,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
DEBUG_INTR("THRE...");

if (uart_circ_empty(xmit))
serial8250_stop_tx(&up->port, 0);
serial8250_stop_tx(&up->port);
}

static _INLINE_ void check_modem_status(struct uart_8250_port *up)
Expand Down
10 changes: 4 additions & 6 deletions drivers/serial/clps711x.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,15 @@

#define tx_enabled(port) ((port)->unused[0])

static void
clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
static void clps711xuart_stop_tx(struct uart_port *port)
{
if (tx_enabled(port)) {
disable_irq(TX_IRQ(port));
tx_enabled(port) = 0;
}
}

static void
clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start)
static void clps711xuart_start_tx(struct uart_port *port)
{
if (!tx_enabled(port)) {
enable_irq(TX_IRQ(port));
Expand Down Expand Up @@ -165,7 +163,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re
return IRQ_HANDLED;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
clps711xuart_stop_tx(port, 0);
clps711xuart_stop_tx(port);
return IRQ_HANDLED;
}

Expand All @@ -182,7 +180,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re
uart_write_wakeup(port);

if (uart_circ_empty(xmit))
clps711xuart_stop_tx(port, 0);
clps711xuart_stop_tx(port);

return IRQ_HANDLED;
}
Expand Down
8 changes: 4 additions & 4 deletions drivers/serial/cpm_uart/cpm_uart_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
/*
* Stop transmitter
*/
static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
static void cpm_uart_stop_tx(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
volatile smc_t *smcp = pinfo->smcp;
Expand All @@ -141,7 +141,7 @@ static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
/*
* Start transmitter
*/
static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start)
static void cpm_uart_start_tx(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
volatile smc_t *smcp = pinfo->smcp;
Expand Down Expand Up @@ -623,7 +623,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
}

if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
cpm_uart_stop_tx(port, 0);
cpm_uart_stop_tx(port);
return 0;
}

Expand Down Expand Up @@ -656,7 +656,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
uart_write_wakeup(port);

if (uart_circ_empty(xmit)) {
cpm_uart_stop_tx(port, 0);
cpm_uart_stop_tx(port);
return 0;
}

Expand Down
10 changes: 5 additions & 5 deletions drivers/serial/dz.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ static inline void dz_out(struct dz_port *dport, unsigned offset,
* ------------------------------------------------------------
*/

static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop)
static void dz_stop_tx(struct uart_port *uport)
{
struct dz_port *dport = (struct dz_port *)uport;
unsigned short tmp, mask = 1 << dport->port.line;
Expand All @@ -125,7 +125,7 @@ static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop)
spin_unlock_irqrestore(&dport->port.lock, flags);
}

static void dz_start_tx(struct uart_port *uport, unsigned int tty_start)
static void dz_start_tx(struct uart_port *uport)
{
struct dz_port *dport = (struct dz_port *)uport;
unsigned short tmp, mask = 1 << dport->port.line;
Expand Down Expand Up @@ -290,7 +290,7 @@ static inline void dz_transmit_chars(struct dz_port *dport)
}
/* if nothing to do or stopped or hardware stopped */
if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
dz_stop_tx(&dport->port, 0);
dz_stop_tx(&dport->port);
return;
}

Expand All @@ -308,7 +308,7 @@ static inline void dz_transmit_chars(struct dz_port *dport)

/* Are we done */
if (uart_circ_empty(xmit))
dz_stop_tx(&dport->port, 0);
dz_stop_tx(&dport->port);
}

/*
Expand Down Expand Up @@ -440,7 +440,7 @@ static int dz_startup(struct uart_port *uport)
*/
static void dz_shutdown(struct uart_port *uport)
{
dz_stop_tx(uport, 0);
dz_stop_tx(uport);
}

/*
Expand Down
12 changes: 5 additions & 7 deletions drivers/serial/icom.c
Original file line number Diff line number Diff line change
Expand Up @@ -989,18 +989,16 @@ static unsigned int icom_get_mctrl(struct uart_port *port)
return result;
}

static void icom_stop_tx(struct uart_port *port, unsigned int tty_stop)
static void icom_stop_tx(struct uart_port *port)
{
unsigned char cmdReg;

if (tty_stop) {
trace(ICOM_PORT, "STOP", 0);
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
}
trace(ICOM_PORT, "STOP", 0);
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
}

static void icom_start_tx(struct uart_port *port, unsigned int tty_start)
static void icom_start_tx(struct uart_port *port)
{
unsigned char cmdReg;

Expand Down
8 changes: 4 additions & 4 deletions drivers/serial/imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ static void imx_timeout(unsigned long data)
/*
* interrupts disabled on entry
*/
static void imx_stop_tx(struct uart_port *port, unsigned int tty_stop)
static void imx_stop_tx(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN;
Expand Down Expand Up @@ -165,13 +165,13 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
} while (!(UTS((u32)sport->port.membase) & UTS_TXFULL));

if (uart_circ_empty(xmit))
imx_stop_tx(&sport->port, 0);
imx_stop_tx(&sport->port);
}

/*
* interrupts disabled on entry
*/
static void imx_start_tx(struct uart_port *port, unsigned int tty_start)
static void imx_start_tx(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;

Expand All @@ -196,7 +196,7 @@ static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs)
}

if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
imx_stop_tx(&sport->port, 0);
imx_stop_tx(&sport->port);
goto out;
}

Expand Down
Loading

0 comments on commit b129a8c

Please sign in to comment.