tty: serial: switch from circ_buf to kfifo

Switch from struct circ_buf to proper kfifo. kfifo provides much better
API, esp. when wrap-around of the buffer needs to be taken into account.
Look at pl011_dma_tx_refill() or cpm_uart_tx_pump() changes for example.

Kfifo API can also fill in scatter-gather DMA structures, so it easier
for that use case too. Look at lpuart_dma_tx() for example. Note that
not all drivers can be converted to that (like atmel_serial), they
handle DMA specially.

Note that usb-serial uses kfifo for TX for ages.

omap needed a bit more care as it needs to put a char into FIFO to start
the DMA transfer when OMAP_DMA_TX_KICK is set. In that case, we have to
do kfifo_dma_out_prepare twice: once to find out the tx_size (to find
out if it is worths to do DMA at all -- size >= 4), the second time for
the actual transfer.

All traces of circ_buf are removed from serial_core.h (and its struct
uart_state).

Signed-off-by: Jiri Slaby (SUSE) <jirislaby@kernel.org>
Cc: Al Cooper <alcooperx@gmail.com>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Cc: Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com>
Cc: Tharun Kumar P <tharunkumar.pasumarthi@microchip.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Vineet Gupta <vgupta@kernel.org>
Cc: Richard Genoud <richard.genoud@gmail.com>
Cc: Nicolas Ferre <nicolas.ferre@microchip.com>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Claudiu Beznea <claudiu.beznea@tuxon.dev>
Cc: Alexander Shiyan <shc_work@mail.ru>
Cc: Baruch Siach <baruch@tkos.co.il>
Cc: Maciej W. Rozycki <macro@orcam.me.uk>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: Neil Armstrong <neil.armstrong@linaro.org>
Cc: Kevin Hilman <khilman@baylibre.com>
Cc: Jerome Brunet <jbrunet@baylibre.com>
Cc: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Cc: Taichi Sugaya <sugaya.taichi@socionext.com>
Cc: Takao Orito <orito.takao@socionext.com>
Cc: Bjorn Andersson <andersson@kernel.org>
Cc: Konrad Dybcio <konrad.dybcio@linaro.org>
Cc: Pali Rohár <pali@kernel.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
Cc: Naveen N. Rao <naveen.n.rao@linux.ibm.com>
Cc: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Cc: Alim Akhtar <alim.akhtar@samsung.com>
Cc: Laxman Dewangan <ldewangan@nvidia.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Orson Zhai <orsonzhai@gmail.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Chunyan Zhang <zhang.lyra@gmail.com>
Cc: Patrice Chotard <patrice.chotard@foss.st.com>
Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Hammer Hsieh <hammerh0314@gmail.com>
Cc: Peter Korsgaard <jacmet@sunsite.dk>
Cc: Timur Tabi <timur@kernel.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: Christian König <christian.koenig@amd.com>
Link: https://lore.kernel.org/r/20240405060826.2521-13-jirislaby@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Jiri Slaby (SUSE) 2024-04-05 08:08:23 +02:00 committed by Greg Kroah-Hartman
parent f8fef2fa41
commit 1788cf6a91
59 changed files with 688 additions and 780 deletions

View File

@ -413,20 +413,18 @@ static int stop_tx_dma(struct uart_8250_port *p)
static int brcmuart_tx_dma(struct uart_8250_port *p) static int brcmuart_tx_dma(struct uart_8250_port *p)
{ {
struct brcmuart_priv *priv = p->port.private_data; struct brcmuart_priv *priv = p->port.private_data;
struct circ_buf *xmit = &p->port.state->xmit; struct tty_port *tport = &p->port.state->port;
u32 tx_size; u32 tx_size;
if (uart_tx_stopped(&p->port) || priv->tx_running || if (uart_tx_stopped(&p->port) || priv->tx_running ||
uart_circ_empty(xmit)) { kfifo_is_empty(&tport->xmit_fifo)) {
return 0; return 0;
} }
tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
priv->dma.tx_err = 0; priv->dma.tx_err = 0;
memcpy(priv->tx_buf, &xmit->buf[xmit->tail], tx_size); tx_size = uart_fifo_out(&p->port, priv->tx_buf, UART_XMIT_SIZE);
uart_xmit_advance(&p->port, tx_size);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&p->port); uart_write_wakeup(&p->port);
udma_writel(priv, REGS_DMA_TX, UDMA_TX_TRANSFER_LEN, tx_size); udma_writel(priv, REGS_DMA_TX, UDMA_TX_TRANSFER_LEN, tx_size);
@ -540,7 +538,7 @@ static void brcmuart_tx_isr(struct uart_port *up, u32 isr)
struct brcmuart_priv *priv = up->private_data; struct brcmuart_priv *priv = up->private_data;
struct device *dev = up->dev; struct device *dev = up->dev;
struct uart_8250_port *port_8250 = up_to_u8250p(up); struct uart_8250_port *port_8250 = up_to_u8250p(up);
struct circ_buf *xmit = &port_8250->port.state->xmit; struct tty_port *tport = &port_8250->port.state->port;
if (isr & UDMA_INTR_TX_ABORT) { if (isr & UDMA_INTR_TX_ABORT) {
if (priv->tx_running) if (priv->tx_running)
@ -548,7 +546,7 @@ static void brcmuart_tx_isr(struct uart_port *up, u32 isr)
return; return;
} }
priv->tx_running = false; priv->tx_running = false;
if (!uart_circ_empty(xmit) && !uart_tx_stopped(up)) if (!kfifo_is_empty(&tport->xmit_fifo) && !uart_tx_stopped(up))
brcmuart_tx_dma(port_8250); brcmuart_tx_dma(port_8250);
} }

View File

@ -280,7 +280,8 @@ static void serial8250_backup_timeout(struct timer_list *t)
*/ */
lsr = serial_lsr_in(up); lsr = serial_lsr_in(up);
if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) && if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
(!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) && (!kfifo_is_empty(&up->port.state->port.xmit_fifo) ||
up->port.x_char) &&
(lsr & UART_LSR_THRE)) { (lsr & UART_LSR_THRE)) {
iir &= ~(UART_IIR_ID | UART_IIR_NO_INT); iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
iir |= UART_IIR_THRI; iir |= UART_IIR_THRI;

View File

@ -15,7 +15,7 @@ static void __dma_tx_complete(void *param)
{ {
struct uart_8250_port *p = param; struct uart_8250_port *p = param;
struct uart_8250_dma *dma = p->dma; struct uart_8250_dma *dma = p->dma;
struct circ_buf *xmit = &p->port.state->xmit; struct tty_port *tport = &p->port.state->port;
unsigned long flags; unsigned long flags;
int ret; int ret;
@ -28,7 +28,7 @@ static void __dma_tx_complete(void *param)
uart_xmit_advance(&p->port, dma->tx_size); uart_xmit_advance(&p->port, dma->tx_size);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&p->port); uart_write_wakeup(&p->port);
ret = serial8250_tx_dma(p); ret = serial8250_tx_dma(p);
@ -86,7 +86,7 @@ static void dma_rx_complete(void *param)
int serial8250_tx_dma(struct uart_8250_port *p) int serial8250_tx_dma(struct uart_8250_port *p)
{ {
struct uart_8250_dma *dma = p->dma; struct uart_8250_dma *dma = p->dma;
struct circ_buf *xmit = &p->port.state->xmit; struct tty_port *tport = &p->port.state->port;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
struct uart_port *up = &p->port; struct uart_port *up = &p->port;
struct scatterlist sg; struct scatterlist sg;
@ -103,18 +103,23 @@ int serial8250_tx_dma(struct uart_8250_port *p)
uart_xchar_out(up, UART_TX); uart_xchar_out(up, UART_TX);
} }
if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) { if (uart_tx_stopped(&p->port) || kfifo_is_empty(&tport->xmit_fifo)) {
/* We have been called from __dma_tx_complete() */ /* We have been called from __dma_tx_complete() */
return 0; return 0;
} }
dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
serial8250_do_prepare_tx_dma(p); serial8250_do_prepare_tx_dma(p);
sg_init_table(&sg, 1); sg_init_table(&sg, 1);
sg_dma_address(&sg) = dma->tx_addr + xmit->tail; /* kfifo can do more than one sg, we don't (quite yet) */
sg_dma_len(&sg) = dma->tx_size; ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1,
UART_XMIT_SIZE, dma->tx_addr);
/* we already checked empty fifo above, so there should be something */
if (WARN_ON_ONCE(ret != 1))
return 0;
dma->tx_size = sg_dma_len(&sg);
desc = dmaengine_prep_slave_sg(dma->txchan, &sg, 1, desc = dmaengine_prep_slave_sg(dma->txchan, &sg, 1,
DMA_MEM_TO_DEV, DMA_MEM_TO_DEV,
@ -257,7 +262,7 @@ int serial8250_request_dma(struct uart_8250_port *p)
/* TX buffer */ /* TX buffer */
dma->tx_addr = dma_map_single(dma->txchan->device->dev, dma->tx_addr = dma_map_single(dma->txchan->device->dev,
p->port.state->xmit.buf, p->port.state->port.xmit_buf,
UART_XMIT_SIZE, UART_XMIT_SIZE,
DMA_TO_DEVICE); DMA_TO_DEVICE);
if (dma_mapping_error(dma->txchan->device->dev, dma->tx_addr)) { if (dma_mapping_error(dma->txchan->device->dev, dma->tx_addr)) {

View File

@ -214,7 +214,7 @@ static void exar_shutdown(struct uart_port *port)
{ {
bool tx_complete = false; bool tx_complete = false;
struct uart_8250_port *up = up_to_u8250p(port); struct uart_8250_port *up = up_to_u8250p(port);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
int i = 0; int i = 0;
u16 lsr; u16 lsr;
@ -225,7 +225,8 @@ static void exar_shutdown(struct uart_port *port)
else else
tx_complete = false; tx_complete = false;
usleep_range(1000, 1100); usleep_range(1000, 1100);
} while (!uart_circ_empty(xmit) && !tx_complete && i++ < 1000); } while (!kfifo_is_empty(&tport->xmit_fifo) &&
!tx_complete && i++ < 1000);
serial8250_do_shutdown(port); serial8250_do_shutdown(port);
} }

View File

@ -199,7 +199,7 @@ static int mtk8250_startup(struct uart_port *port)
if (up->dma) { if (up->dma) {
data->rx_status = DMA_RX_START; data->rx_status = DMA_RX_START;
uart_circ_clear(&port->state->xmit); kfifo_reset(&port->state->port.xmit_fifo);
} }
#endif #endif
memset(&port->icount, 0, sizeof(port->icount)); memset(&port->icount, 0, sizeof(port->icount));

View File

@ -1094,7 +1094,7 @@ static void omap_8250_dma_tx_complete(void *param)
{ {
struct uart_8250_port *p = param; struct uart_8250_port *p = param;
struct uart_8250_dma *dma = p->dma; struct uart_8250_dma *dma = p->dma;
struct circ_buf *xmit = &p->port.state->xmit; struct tty_port *tport = &p->port.state->port;
unsigned long flags; unsigned long flags;
bool en_thri = false; bool en_thri = false;
struct omap8250_priv *priv = p->port.private_data; struct omap8250_priv *priv = p->port.private_data;
@ -1113,10 +1113,10 @@ static void omap_8250_dma_tx_complete(void *param)
omap8250_restore_regs(p); omap8250_restore_regs(p);
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&p->port); uart_write_wakeup(&p->port);
if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) { if (!kfifo_is_empty(&tport->xmit_fifo) && !uart_tx_stopped(&p->port)) {
int ret; int ret;
ret = omap_8250_tx_dma(p); ret = omap_8250_tx_dma(p);
@ -1138,15 +1138,15 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
{ {
struct uart_8250_dma *dma = p->dma; struct uart_8250_dma *dma = p->dma;
struct omap8250_priv *priv = p->port.private_data; struct omap8250_priv *priv = p->port.private_data;
struct circ_buf *xmit = &p->port.state->xmit; struct tty_port *tport = &p->port.state->port;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
struct scatterlist sg; struct scatterlist sg;
unsigned int skip_byte = 0; int skip_byte = -1;
int ret; int ret;
if (dma->tx_running) if (dma->tx_running)
return 0; return 0;
if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) { if (uart_tx_stopped(&p->port) || kfifo_is_empty(&tport->xmit_fifo)) {
/* /*
* Even if no data, we need to return an error for the two cases * Even if no data, we need to return an error for the two cases
@ -1161,8 +1161,18 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
return 0; return 0;
} }
dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); sg_init_table(&sg, 1);
ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1,
UART_XMIT_SIZE, dma->tx_addr);
if (ret != 1) {
serial8250_clear_THRI(p);
return 0;
}
dma->tx_size = sg_dma_len(&sg);
if (priv->habit & OMAP_DMA_TX_KICK) { if (priv->habit & OMAP_DMA_TX_KICK) {
unsigned char c;
u8 tx_lvl; u8 tx_lvl;
/* /*
@ -1189,13 +1199,16 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
skip_byte = 1; if (!kfifo_get(&tport->xmit_fifo, &c)) {
ret = -EINVAL;
goto err;
}
skip_byte = c;
/* now we need to recompute due to kfifo_get */
kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1,
UART_XMIT_SIZE, dma->tx_addr);
} }
sg_init_table(&sg, 1);
sg_dma_address(&sg) = dma->tx_addr + xmit->tail + skip_byte;
sg_dma_len(&sg) = dma->tx_size - skip_byte;
desc = dmaengine_prep_slave_sg(dma->txchan, &sg, 1, DMA_MEM_TO_DEV, desc = dmaengine_prep_slave_sg(dma->txchan, &sg, 1, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) { if (!desc) {
@ -1218,11 +1231,13 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
dma->tx_err = 0; dma->tx_err = 0;
serial8250_clear_THRI(p); serial8250_clear_THRI(p);
if (skip_byte) ret = 0;
serial_out(p, UART_TX, xmit->buf[xmit->tail]); goto out_skip;
return 0;
err: err:
dma->tx_err = 1; dma->tx_err = 1;
out_skip:
if (skip_byte >= 0)
serial_out(p, UART_TX, skip_byte);
return ret; return ret;
} }
@ -1311,7 +1326,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
serial8250_modem_status(up); serial8250_modem_status(up);
if (status & UART_LSR_THRE && up->dma->tx_err) { if (status & UART_LSR_THRE && up->dma->tx_err) {
if (uart_tx_stopped(&up->port) || if (uart_tx_stopped(&up->port) ||
uart_circ_empty(&up->port.state->xmit)) { kfifo_is_empty(&up->port.state->port.xmit_fifo)) {
up->dma->tx_err = 0; up->dma->tx_err = 0;
serial8250_tx_chars(up); serial8250_tx_chars(up);
} else { } else {

View File

@ -382,10 +382,10 @@ static void pci1xxxx_rx_burst(struct uart_port *port, u32 uart_status)
} }
static void pci1xxxx_process_write_data(struct uart_port *port, static void pci1xxxx_process_write_data(struct uart_port *port,
struct circ_buf *xmit,
int *data_empty_count, int *data_empty_count,
u32 *valid_byte_count) u32 *valid_byte_count)
{ {
struct tty_port *tport = &port->state->port;
u32 valid_burst_count = *valid_byte_count / UART_BURST_SIZE; u32 valid_burst_count = *valid_byte_count / UART_BURST_SIZE;
/* /*
@ -395,41 +395,36 @@ static void pci1xxxx_process_write_data(struct uart_port *port,
* one byte at a time. * one byte at a time.
*/ */
while (valid_burst_count) { while (valid_burst_count) {
u32 c;
if (*data_empty_count - UART_BURST_SIZE < 0) if (*data_empty_count - UART_BURST_SIZE < 0)
break; break;
if (xmit->tail > (UART_XMIT_SIZE - UART_BURST_SIZE)) if (kfifo_len(&tport->xmit_fifo) < UART_BURST_SIZE)
break; break;
writel(*(unsigned int *)&xmit->buf[xmit->tail], if (WARN_ON(kfifo_out(&tport->xmit_fifo, (u8 *)&c, sizeof(c)) !=
port->membase + UART_TX_BURST_FIFO); sizeof(c)))
break;
writel(c, port->membase + UART_TX_BURST_FIFO);
*valid_byte_count -= UART_BURST_SIZE; *valid_byte_count -= UART_BURST_SIZE;
*data_empty_count -= UART_BURST_SIZE; *data_empty_count -= UART_BURST_SIZE;
valid_burst_count -= UART_BYTE_SIZE; valid_burst_count -= UART_BYTE_SIZE;
xmit->tail = (xmit->tail + UART_BURST_SIZE) &
(UART_XMIT_SIZE - 1);
} }
while (*valid_byte_count) { while (*valid_byte_count) {
if (*data_empty_count - UART_BYTE_SIZE < 0) u8 c;
if (!kfifo_get(&tport->xmit_fifo, &c))
break; break;
writeb(xmit->buf[xmit->tail], port->membase + writeb(c, port->membase + UART_TX_BYTE_FIFO);
UART_TX_BYTE_FIFO);
*data_empty_count -= UART_BYTE_SIZE; *data_empty_count -= UART_BYTE_SIZE;
*valid_byte_count -= UART_BYTE_SIZE; *valid_byte_count -= UART_BYTE_SIZE;
/*
* When the tail of the circular buffer is reached, the next
* byte is transferred to the beginning of the buffer.
*/
xmit->tail = (xmit->tail + UART_BYTE_SIZE) &
(UART_XMIT_SIZE - 1);
/* /*
* If there are any pending burst count, data is handled by * If there are any pending burst count, data is handled by
* transmitting DWORDs at a time. * transmitting DWORDs at a time.
*/ */
if (valid_burst_count && (xmit->tail < if (valid_burst_count &&
(UART_XMIT_SIZE - UART_BURST_SIZE))) kfifo_len(&tport->xmit_fifo) >= UART_BURST_SIZE)
break; break;
} }
} }
@ -437,11 +432,9 @@ static void pci1xxxx_process_write_data(struct uart_port *port,
static void pci1xxxx_tx_burst(struct uart_port *port, u32 uart_status) static void pci1xxxx_tx_burst(struct uart_port *port, u32 uart_status)
{ {
struct uart_8250_port *up = up_to_u8250p(port); struct uart_8250_port *up = up_to_u8250p(port);
struct tty_port *tport = &port->state->port;
u32 valid_byte_count; u32 valid_byte_count;
int data_empty_count; int data_empty_count;
struct circ_buf *xmit;
xmit = &port->state->xmit;
if (port->x_char) { if (port->x_char) {
writeb(port->x_char, port->membase + UART_TX); writeb(port->x_char, port->membase + UART_TX);
@ -450,25 +443,25 @@ static void pci1xxxx_tx_burst(struct uart_port *port, u32 uart_status)
return; return;
} }
if ((uart_tx_stopped(port)) || (uart_circ_empty(xmit))) { if ((uart_tx_stopped(port)) || kfifo_is_empty(&tport->xmit_fifo)) {
port->ops->stop_tx(port); port->ops->stop_tx(port);
} else { } else {
data_empty_count = (pci1xxxx_read_burst_status(port) & data_empty_count = (pci1xxxx_read_burst_status(port) &
UART_BST_STAT_TX_COUNT_MASK) >> 8; UART_BST_STAT_TX_COUNT_MASK) >> 8;
do { do {
valid_byte_count = uart_circ_chars_pending(xmit); valid_byte_count = kfifo_len(&tport->xmit_fifo);
pci1xxxx_process_write_data(port, xmit, pci1xxxx_process_write_data(port,
&data_empty_count, &data_empty_count,
&valid_byte_count); &valid_byte_count);
port->icount.tx++; port->icount.tx++;
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
break; break;
} while (data_empty_count && valid_byte_count); } while (data_empty_count && valid_byte_count);
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
/* /*
@ -476,7 +469,8 @@ static void pci1xxxx_tx_burst(struct uart_port *port, u32 uart_status)
* the HW can go idle. So we get here once again with empty FIFO and * the HW can go idle. So we get here once again with empty FIFO and
* disable the interrupt and RPM in __stop_tx() * disable the interrupt and RPM in __stop_tx()
*/ */
if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM)) if (kfifo_is_empty(&tport->xmit_fifo) &&
!(up->capabilities & UART_CAP_RPM))
port->ops->stop_tx(port); port->ops->stop_tx(port);
} }

View File

@ -1630,7 +1630,7 @@ static void serial8250_start_tx(struct uart_port *port)
/* Port locked to synchronize UART_IER access against the console. */ /* Port locked to synchronize UART_IER access against the console. */
lockdep_assert_held_once(&port->lock); lockdep_assert_held_once(&port->lock);
if (!port->x_char && uart_circ_empty(&port->state->xmit)) if (!port->x_char && kfifo_is_empty(&port->state->port.xmit_fifo))
return; return;
serial8250_rpm_get_tx(up); serial8250_rpm_get_tx(up);
@ -1778,7 +1778,7 @@ EXPORT_SYMBOL_GPL(serial8250_rx_chars);
void serial8250_tx_chars(struct uart_8250_port *up) void serial8250_tx_chars(struct uart_8250_port *up)
{ {
struct uart_port *port = &up->port; struct uart_port *port = &up->port;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
int count; int count;
if (port->x_char) { if (port->x_char) {
@ -1789,14 +1789,19 @@ void serial8250_tx_chars(struct uart_8250_port *up)
serial8250_stop_tx(port); serial8250_stop_tx(port);
return; return;
} }
if (uart_circ_empty(xmit)) { if (kfifo_is_empty(&tport->xmit_fifo)) {
__stop_tx(up); __stop_tx(up);
return; return;
} }
count = up->tx_loadsz; count = up->tx_loadsz;
do { do {
serial_out(up, UART_TX, xmit->buf[xmit->tail]); unsigned char c;
if (!uart_fifo_get(port, &c))
break;
serial_out(up, UART_TX, c);
if (up->bugs & UART_BUG_TXRACE) { if (up->bugs & UART_BUG_TXRACE) {
/* /*
* The Aspeed BMC virtual UARTs have a bug where data * The Aspeed BMC virtual UARTs have a bug where data
@ -1809,9 +1814,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
*/ */
serial_in(up, UART_SCR); serial_in(up, UART_SCR);
} }
uart_xmit_advance(port, 1);
if (uart_circ_empty(xmit))
break;
if ((up->capabilities & UART_CAP_HFIFO) && if ((up->capabilities & UART_CAP_HFIFO) &&
!uart_lsr_tx_empty(serial_in(up, UART_LSR))) !uart_lsr_tx_empty(serial_in(up, UART_LSR)))
break; break;
@ -1821,7 +1824,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
break; break;
} while (--count > 0); } while (--count > 0);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
/* /*
@ -1829,7 +1832,8 @@ void serial8250_tx_chars(struct uart_8250_port *up)
* HW can go idle. So we get here once again with empty FIFO and disable * HW can go idle. So we get here once again with empty FIFO and disable
* the interrupt and RPM in __stop_tx() * the interrupt and RPM in __stop_tx()
*/ */
if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM)) if (kfifo_is_empty(&tport->xmit_fifo) &&
!(up->capabilities & UART_CAP_RPM))
__stop_tx(up); __stop_tx(up);
} }
EXPORT_SYMBOL_GPL(serial8250_tx_chars); EXPORT_SYMBOL_GPL(serial8250_tx_chars);

View File

@ -535,6 +535,7 @@ static void pl011_start_tx_pio(struct uart_amba_port *uap);
static void pl011_dma_tx_callback(void *data) static void pl011_dma_tx_callback(void *data)
{ {
struct uart_amba_port *uap = data; struct uart_amba_port *uap = data;
struct tty_port *tport = &uap->port.state->port;
struct pl011_dmatx_data *dmatx = &uap->dmatx; struct pl011_dmatx_data *dmatx = &uap->dmatx;
unsigned long flags; unsigned long flags;
u16 dmacr; u16 dmacr;
@ -558,7 +559,7 @@ static void pl011_dma_tx_callback(void *data)
* get further refills (hence we check dmacr). * get further refills (hence we check dmacr).
*/ */
if (!(dmacr & UART011_TXDMAE) || uart_tx_stopped(&uap->port) || if (!(dmacr & UART011_TXDMAE) || uart_tx_stopped(&uap->port) ||
uart_circ_empty(&uap->port.state->xmit)) { kfifo_is_empty(&tport->xmit_fifo)) {
uap->dmatx.queued = false; uap->dmatx.queued = false;
uart_port_unlock_irqrestore(&uap->port, flags); uart_port_unlock_irqrestore(&uap->port, flags);
return; return;
@ -588,7 +589,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
struct dma_chan *chan = dmatx->chan; struct dma_chan *chan = dmatx->chan;
struct dma_device *dma_dev = chan->device; struct dma_device *dma_dev = chan->device;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
struct circ_buf *xmit = &uap->port.state->xmit; struct tty_port *tport = &uap->port.state->port;
unsigned int count; unsigned int count;
/* /*
@ -597,7 +598,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
* the standard interrupt handling. This ensures that we * the standard interrupt handling. This ensures that we
* issue a uart_write_wakeup() at the appropriate time. * issue a uart_write_wakeup() at the appropriate time.
*/ */
count = uart_circ_chars_pending(xmit); count = kfifo_len(&tport->xmit_fifo);
if (count < (uap->fifosize >> 1)) { if (count < (uap->fifosize >> 1)) {
uap->dmatx.queued = false; uap->dmatx.queued = false;
return 0; return 0;
@ -613,21 +614,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
if (count > PL011_DMA_BUFFER_SIZE) if (count > PL011_DMA_BUFFER_SIZE)
count = PL011_DMA_BUFFER_SIZE; count = PL011_DMA_BUFFER_SIZE;
if (xmit->tail < xmit->head) { count = kfifo_out_peek(&tport->xmit_fifo, dmatx->buf, count);
memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], count);
} else {
size_t first = UART_XMIT_SIZE - xmit->tail;
size_t second;
if (first > count)
first = count;
second = count - first;
memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], first);
if (second)
memcpy(&dmatx->buf[first], &xmit->buf[0], second);
}
dmatx->len = count; dmatx->len = count;
dmatx->dma = dma_map_single(dma_dev->dev, dmatx->buf, count, dmatx->dma = dma_map_single(dma_dev->dev, dmatx->buf, count,
DMA_TO_DEVICE); DMA_TO_DEVICE);
@ -670,7 +657,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
*/ */
uart_xmit_advance(&uap->port, count); uart_xmit_advance(&uap->port, count);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&uap->port); uart_write_wakeup(&uap->port);
return 1; return 1;
@ -1454,7 +1441,7 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
/* Returns true if tx interrupts have to be (kept) enabled */ /* Returns true if tx interrupts have to be (kept) enabled */
static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq) static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
{ {
struct circ_buf *xmit = &uap->port.state->xmit; struct tty_port *tport = &uap->port.state->port;
int count = uap->fifosize >> 1; int count = uap->fifosize >> 1;
if (uap->port.x_char) { if (uap->port.x_char) {
@ -1463,7 +1450,7 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
uap->port.x_char = 0; uap->port.x_char = 0;
--count; --count;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(&uap->port)) {
pl011_stop_tx(&uap->port); pl011_stop_tx(&uap->port);
return false; return false;
} }
@ -1472,20 +1459,25 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
if (pl011_dma_tx_irq(uap)) if (pl011_dma_tx_irq(uap))
return true; return true;
do { while (1) {
unsigned char c;
if (likely(from_irq) && count-- == 0) if (likely(from_irq) && count-- == 0)
break; break;
if (!pl011_tx_char(uap, xmit->buf[xmit->tail], from_irq)) if (!kfifo_peek(&tport->xmit_fifo, &c))
break; break;
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); if (!pl011_tx_char(uap, c, from_irq))
} while (!uart_circ_empty(xmit)); break;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) kfifo_skip(&tport->xmit_fifo);
}
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&uap->port); uart_write_wakeup(&uap->port);
if (uart_circ_empty(xmit)) { if (kfifo_is_empty(&tport->xmit_fifo)) {
pl011_stop_tx(&uap->port); pl011_stop_tx(&uap->port);
return false; return false;
} }

View File

@ -390,7 +390,7 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_port *up)
static void ar933x_uart_tx_chars(struct ar933x_uart_port *up) static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
{ {
struct circ_buf *xmit = &up->port.state->xmit; struct tty_port *tport = &up->port.state->port;
struct serial_rs485 *rs485conf = &up->port.rs485; struct serial_rs485 *rs485conf = &up->port.rs485;
int count; int count;
bool half_duplex_send = false; bool half_duplex_send = false;
@ -399,7 +399,7 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
return; return;
if ((rs485conf->flags & SER_RS485_ENABLED) && if ((rs485conf->flags & SER_RS485_ENABLED) &&
(up->port.x_char || !uart_circ_empty(xmit))) { (up->port.x_char || !kfifo_is_empty(&tport->xmit_fifo))) {
ar933x_uart_stop_rx_interrupt(up); ar933x_uart_stop_rx_interrupt(up);
gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_ON_SEND)); gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_ON_SEND));
half_duplex_send = true; half_duplex_send = true;
@ -408,6 +408,7 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
count = up->port.fifosize; count = up->port.fifosize;
do { do {
unsigned int rdata; unsigned int rdata;
unsigned char c;
rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG); rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG);
if ((rdata & AR933X_UART_DATA_TX_CSR) == 0) if ((rdata & AR933X_UART_DATA_TX_CSR) == 0)
@ -420,18 +421,16 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
continue; continue;
} }
if (uart_circ_empty(xmit)) if (!uart_fifo_get(&up->port, &c))
break; break;
ar933x_uart_putc(up, xmit->buf[xmit->tail]); ar933x_uart_putc(up, c);
uart_xmit_advance(&up->port, 1);
} while (--count > 0); } while (--count > 0);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&up->port); uart_write_wakeup(&up->port);
if (!uart_circ_empty(xmit)) { if (!kfifo_is_empty(&tport->xmit_fifo)) {
ar933x_uart_start_tx_interrupt(up); ar933x_uart_start_tx_interrupt(up);
} else if (half_duplex_send) { } else if (half_duplex_send) {
ar933x_uart_wait_tx_complete(up); ar933x_uart_wait_tx_complete(up);

View File

@ -155,7 +155,7 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port)
*/ */
static void arc_serial_tx_chars(struct uart_port *port) static void arc_serial_tx_chars(struct uart_port *port)
{ {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
int sent = 0; int sent = 0;
unsigned char ch; unsigned char ch;
@ -164,9 +164,7 @@ static void arc_serial_tx_chars(struct uart_port *port)
port->icount.tx++; port->icount.tx++;
port->x_char = 0; port->x_char = 0;
sent = 1; sent = 1;
} else if (!uart_circ_empty(xmit)) { } else if (uart_fifo_get(port, &ch)) {
ch = xmit->buf[xmit->tail];
uart_xmit_advance(port, 1);
while (!(UART_GET_STATUS(port) & TXEMPTY)) while (!(UART_GET_STATUS(port) & TXEMPTY))
cpu_relax(); cpu_relax();
UART_SET_DATA(port, ch); UART_SET_DATA(port, ch);
@ -177,7 +175,7 @@ static void arc_serial_tx_chars(struct uart_port *port)
* If num chars in xmit buffer are too few, ask tty layer for more. * If num chars in xmit buffer are too few, ask tty layer for more.
* By Hard ISR to schedule processing in software interrupt part * By Hard ISR to schedule processing in software interrupt part
*/ */
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (sent) if (sent)

View File

@ -857,7 +857,7 @@ static void atmel_complete_tx_dma(void *arg)
{ {
struct atmel_uart_port *atmel_port = arg; struct atmel_uart_port *atmel_port = arg;
struct uart_port *port = &atmel_port->uart; struct uart_port *port = &atmel_port->uart;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
struct dma_chan *chan = atmel_port->chan_tx; struct dma_chan *chan = atmel_port->chan_tx;
unsigned long flags; unsigned long flags;
@ -873,15 +873,15 @@ static void atmel_complete_tx_dma(void *arg)
atmel_port->desc_tx = NULL; atmel_port->desc_tx = NULL;
spin_unlock(&atmel_port->lock_tx); spin_unlock(&atmel_port->lock_tx);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
/* /*
* xmit is a circular buffer so, if we have just send data from * xmit is a circular buffer so, if we have just send data from the
* xmit->tail to the end of xmit->buf, now we have to transmit the * tail to the end, now we have to transmit the remaining data from the
* remaining data from the beginning of xmit->buf to xmit->head. * beginning to the head.
*/ */
if (!uart_circ_empty(xmit)) if (!kfifo_is_empty(&tport->xmit_fifo))
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx); atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
else if (atmel_uart_is_half_duplex(port)) { else if (atmel_uart_is_half_duplex(port)) {
/* /*
@ -919,18 +919,18 @@ static void atmel_release_tx_dma(struct uart_port *port)
static void atmel_tx_dma(struct uart_port *port) static void atmel_tx_dma(struct uart_port *port)
{ {
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
struct dma_chan *chan = atmel_port->chan_tx; struct dma_chan *chan = atmel_port->chan_tx;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
struct scatterlist sgl[2], *sg, *sg_tx = &atmel_port->sg_tx; struct scatterlist sgl[2], *sg, *sg_tx = &atmel_port->sg_tx;
unsigned int tx_len, part1_len, part2_len, sg_len; unsigned int tx_len, tail, part1_len, part2_len, sg_len;
dma_addr_t phys_addr; dma_addr_t phys_addr;
/* Make sure we have an idle channel */ /* Make sure we have an idle channel */
if (atmel_port->desc_tx != NULL) if (atmel_port->desc_tx != NULL)
return; return;
if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) { if (!kfifo_is_empty(&tport->xmit_fifo) && !uart_tx_stopped(port)) {
/* /*
* DMA is idle now. * DMA is idle now.
* Port xmit buffer is already mapped, * Port xmit buffer is already mapped,
@ -940,9 +940,8 @@ static void atmel_tx_dma(struct uart_port *port)
* Take the port lock to get a * Take the port lock to get a
* consistent xmit buffer state. * consistent xmit buffer state.
*/ */
tx_len = CIRC_CNT_TO_END(xmit->head, tx_len = kfifo_out_linear(&tport->xmit_fifo, &tail,
xmit->tail, UART_XMIT_SIZE);
UART_XMIT_SIZE);
if (atmel_port->fifo_size) { if (atmel_port->fifo_size) {
/* multi data mode */ /* multi data mode */
@ -956,7 +955,7 @@ static void atmel_tx_dma(struct uart_port *port)
sg_init_table(sgl, 2); sg_init_table(sgl, 2);
sg_len = 0; sg_len = 0;
phys_addr = sg_dma_address(sg_tx) + xmit->tail; phys_addr = sg_dma_address(sg_tx) + tail;
if (part1_len) { if (part1_len) {
sg = &sgl[sg_len++]; sg = &sgl[sg_len++];
sg_dma_address(sg) = phys_addr; sg_dma_address(sg) = phys_addr;
@ -973,7 +972,7 @@ static void atmel_tx_dma(struct uart_port *port)
/* /*
* save tx_len so atmel_complete_tx_dma() will increase * save tx_len so atmel_complete_tx_dma() will increase
* xmit->tail correctly * tail correctly
*/ */
atmel_port->tx_len = tx_len; atmel_port->tx_len = tx_len;
@ -1003,13 +1002,14 @@ static void atmel_tx_dma(struct uart_port *port)
dma_async_issue_pending(chan); dma_async_issue_pending(chan);
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
} }
static int atmel_prepare_tx_dma(struct uart_port *port) static int atmel_prepare_tx_dma(struct uart_port *port)
{ {
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
struct tty_port *tport = &port->state->port;
struct device *mfd_dev = port->dev->parent; struct device *mfd_dev = port->dev->parent;
dma_cap_mask_t mask; dma_cap_mask_t mask;
struct dma_slave_config config; struct dma_slave_config config;
@ -1031,11 +1031,11 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
spin_lock_init(&atmel_port->lock_tx); spin_lock_init(&atmel_port->lock_tx);
sg_init_table(&atmel_port->sg_tx, 1); sg_init_table(&atmel_port->sg_tx, 1);
/* UART circular tx buffer is an aligned page. */ /* UART circular tx buffer is an aligned page. */
BUG_ON(!PAGE_ALIGNED(port->state->xmit.buf)); BUG_ON(!PAGE_ALIGNED(tport->xmit_buf));
sg_set_page(&atmel_port->sg_tx, sg_set_page(&atmel_port->sg_tx,
virt_to_page(port->state->xmit.buf), virt_to_page(tport->xmit_buf),
UART_XMIT_SIZE, UART_XMIT_SIZE,
offset_in_page(port->state->xmit.buf)); offset_in_page(tport->xmit_buf));
nent = dma_map_sg(port->dev, nent = dma_map_sg(port->dev,
&atmel_port->sg_tx, &atmel_port->sg_tx,
1, 1,
@ -1047,7 +1047,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
} else { } else {
dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__, dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__,
sg_dma_len(&atmel_port->sg_tx), sg_dma_len(&atmel_port->sg_tx),
port->state->xmit.buf, tport->xmit_buf,
&sg_dma_address(&atmel_port->sg_tx)); &sg_dma_address(&atmel_port->sg_tx));
} }
@ -1459,9 +1459,8 @@ static void atmel_release_tx_pdc(struct uart_port *port)
static void atmel_tx_pdc(struct uart_port *port) static void atmel_tx_pdc(struct uart_port *port)
{ {
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
int count;
/* nothing left to transmit? */ /* nothing left to transmit? */
if (atmel_uart_readl(port, ATMEL_PDC_TCR)) if (atmel_uart_readl(port, ATMEL_PDC_TCR))
@ -1474,17 +1473,19 @@ static void atmel_tx_pdc(struct uart_port *port)
/* disable PDC transmit */ /* disable PDC transmit */
atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS); atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) { if (!kfifo_is_empty(&tport->xmit_fifo) && !uart_tx_stopped(port)) {
unsigned int count, tail;
dma_sync_single_for_device(port->dev, dma_sync_single_for_device(port->dev,
pdc->dma_addr, pdc->dma_addr,
pdc->dma_size, pdc->dma_size,
DMA_TO_DEVICE); DMA_TO_DEVICE);
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); count = kfifo_out_linear(&tport->xmit_fifo, &tail,
UART_XMIT_SIZE);
pdc->ofs = count; pdc->ofs = count;
atmel_uart_writel(port, ATMEL_PDC_TPR, atmel_uart_writel(port, ATMEL_PDC_TPR, pdc->dma_addr + tail);
pdc->dma_addr + xmit->tail);
atmel_uart_writel(port, ATMEL_PDC_TCR, count); atmel_uart_writel(port, ATMEL_PDC_TCR, count);
/* re-enable PDC transmit */ /* re-enable PDC transmit */
atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN); atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
@ -1498,7 +1499,7 @@ static void atmel_tx_pdc(struct uart_port *port)
} }
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
} }
@ -1506,9 +1507,9 @@ static int atmel_prepare_tx_pdc(struct uart_port *port)
{ {
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
pdc->buf = xmit->buf; pdc->buf = tport->xmit_buf;
pdc->dma_addr = dma_map_single(port->dev, pdc->dma_addr = dma_map_single(port->dev,
pdc->buf, pdc->buf,
UART_XMIT_SIZE, UART_XMIT_SIZE,

View File

@ -146,7 +146,8 @@ static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
{ {
struct uart_port *port = dev_id; struct uart_port *port = dev_id;
struct clps711x_port *s = dev_get_drvdata(port->dev); struct clps711x_port *s = dev_get_drvdata(port->dev);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned char c;
if (port->x_char) { if (port->x_char) {
writew(port->x_char, port->membase + UARTDR_OFFSET); writew(port->x_char, port->membase + UARTDR_OFFSET);
@ -155,7 +156,7 @@ static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
if (s->tx_enabled) { if (s->tx_enabled) {
disable_irq_nosync(port->irq); disable_irq_nosync(port->irq);
s->tx_enabled = 0; s->tx_enabled = 0;
@ -163,18 +164,17 @@ static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
while (!uart_circ_empty(xmit)) { while (uart_fifo_get(port, &c)) {
u32 sysflg = 0; u32 sysflg = 0;
writew(xmit->buf[xmit->tail], port->membase + UARTDR_OFFSET); writew(c, port->membase + UARTDR_OFFSET);
uart_xmit_advance(port, 1);
regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
if (sysflg & SYSFLG_UTXFF) if (sysflg & SYSFLG_UTXFF)
break; break;
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
return IRQ_HANDLED; return IRQ_HANDLED;

View File

@ -648,7 +648,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
int count; int count;
struct uart_cpm_port *pinfo = struct uart_cpm_port *pinfo =
container_of(port, struct uart_cpm_port, port); container_of(port, struct uart_cpm_port, port);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
/* Handle xon/xoff */ /* Handle xon/xoff */
if (port->x_char) { if (port->x_char) {
@ -673,7 +673,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
return 1; return 1;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
cpm_uart_stop_tx(port); cpm_uart_stop_tx(port);
return 0; return 0;
} }
@ -681,16 +681,10 @@ static int cpm_uart_tx_pump(struct uart_port *port)
/* Pick next descriptor and fill from buffer */ /* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur; bdp = pinfo->tx_cur;
while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) && !uart_circ_empty(xmit)) { while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) &&
count = 0; !kfifo_is_empty(&tport->xmit_fifo)) {
p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo); p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
while (count < pinfo->tx_fifosize) { count = uart_fifo_out(port, p, pinfo->tx_fifosize);
*p++ = xmit->buf[xmit->tail];
uart_xmit_advance(port, 1);
count++;
if (uart_circ_empty(xmit))
break;
}
out_be16(&bdp->cbd_datlen, count); out_be16(&bdp->cbd_datlen, count);
setbits16(&bdp->cbd_sc, BD_SC_READY); setbits16(&bdp->cbd_sc, BD_SC_READY);
/* Get next BD. */ /* Get next BD. */
@ -701,10 +695,10 @@ static int cpm_uart_tx_pump(struct uart_port *port)
} }
pinfo->tx_cur = bdp; pinfo->tx_cur = bdp;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) { if (kfifo_is_empty(&tport->xmit_fifo)) {
cpm_uart_stop_tx(port); cpm_uart_stop_tx(port);
return 0; return 0;
} }

View File

@ -179,8 +179,9 @@ static void digicolor_uart_rx(struct uart_port *port)
static void digicolor_uart_tx(struct uart_port *port) static void digicolor_uart_tx(struct uart_port *port)
{ {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned long flags; unsigned long flags;
unsigned char c;
if (digicolor_uart_tx_full(port)) if (digicolor_uart_tx_full(port))
return; return;
@ -194,20 +195,19 @@ static void digicolor_uart_tx(struct uart_port *port)
goto out; goto out;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
digicolor_uart_stop_tx(port); digicolor_uart_stop_tx(port);
goto out; goto out;
} }
while (!uart_circ_empty(xmit)) { while (uart_fifo_get(port, &c)) {
writeb(xmit->buf[xmit->tail], port->membase + UA_EMI_REC); writeb(c, port->membase + UA_EMI_REC);
uart_xmit_advance(port, 1);
if (digicolor_uart_tx_full(port)) if (digicolor_uart_tx_full(port))
break; break;
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
out: out:

View File

@ -252,13 +252,13 @@ static inline void dz_receive_chars(struct dz_mux *mux)
static inline void dz_transmit_chars(struct dz_mux *mux) static inline void dz_transmit_chars(struct dz_mux *mux)
{ {
struct dz_port *dport = &mux->dport[0]; struct dz_port *dport = &mux->dport[0];
struct circ_buf *xmit; struct tty_port *tport;
unsigned char tmp; unsigned char tmp;
u16 status; u16 status;
status = dz_in(dport, DZ_CSR); status = dz_in(dport, DZ_CSR);
dport = &mux->dport[LINE(status)]; dport = &mux->dport[LINE(status)];
xmit = &dport->port.state->xmit; tport = &dport->port.state->port;
if (dport->port.x_char) { /* XON/XOFF chars */ if (dport->port.x_char) { /* XON/XOFF chars */
dz_out(dport, DZ_TDR, dport->port.x_char); dz_out(dport, DZ_TDR, dport->port.x_char);
@ -267,7 +267,8 @@ static inline void dz_transmit_chars(struct dz_mux *mux)
return; return;
} }
/* If nothing to do or stopped or hardware stopped. */ /* If nothing to do or stopped or hardware stopped. */
if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { if (uart_tx_stopped(&dport->port) ||
!uart_fifo_get(&dport->port, &tmp)) {
uart_port_lock(&dport->port); uart_port_lock(&dport->port);
dz_stop_tx(&dport->port); dz_stop_tx(&dport->port);
uart_port_unlock(&dport->port); uart_port_unlock(&dport->port);
@ -278,15 +279,13 @@ static inline void dz_transmit_chars(struct dz_mux *mux)
* If something to do... (remember the dz has no output fifo, * If something to do... (remember the dz has no output fifo,
* so we go one char at a time) :-< * so we go one char at a time) :-<
*/ */
tmp = xmit->buf[xmit->tail];
dz_out(dport, DZ_TDR, tmp); dz_out(dport, DZ_TDR, tmp);
uart_xmit_advance(&dport->port, 1);
if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < DZ_WAKEUP_CHARS)
uart_write_wakeup(&dport->port); uart_write_wakeup(&dport->port);
/* Are we are done. */ /* Are we are done. */
if (uart_circ_empty(xmit)) { if (kfifo_is_empty(&tport->xmit_fifo)) {
uart_port_lock(&dport->port); uart_port_lock(&dport->port);
dz_stop_tx(&dport->port); dz_stop_tx(&dport->port);
uart_port_unlock(&dport->port); uart_port_unlock(&dport->port);

View File

@ -174,17 +174,18 @@ static void linflex_put_char(struct uart_port *sport, unsigned char c)
static inline void linflex_transmit_buffer(struct uart_port *sport) static inline void linflex_transmit_buffer(struct uart_port *sport)
{ {
struct circ_buf *xmit = &sport->state->xmit; struct tty_port *tport = &sport->state->port;
unsigned char c;
while (!uart_circ_empty(xmit)) { while (uart_fifo_get(sport, &c)) {
linflex_put_char(sport, xmit->buf[xmit->tail]); linflex_put_char(sport, c);
uart_xmit_advance(sport, 1); sport->icount.tx++;
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(sport); uart_write_wakeup(sport);
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
linflex_stop_tx(sport); linflex_stop_tx(sport);
} }
@ -200,7 +201,7 @@ static void linflex_start_tx(struct uart_port *port)
static irqreturn_t linflex_txint(int irq, void *dev_id) static irqreturn_t linflex_txint(int irq, void *dev_id)
{ {
struct uart_port *sport = dev_id; struct uart_port *sport = dev_id;
struct circ_buf *xmit = &sport->state->xmit; struct tty_port *tport = &sport->state->port;
unsigned long flags; unsigned long flags;
uart_port_lock_irqsave(sport, &flags); uart_port_lock_irqsave(sport, &flags);
@ -210,7 +211,7 @@ static irqreturn_t linflex_txint(int irq, void *dev_id)
goto out; goto out;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(sport)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(sport)) {
linflex_stop_tx(sport); linflex_stop_tx(sport);
goto out; goto out;
} }

View File

@ -7,6 +7,7 @@
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/bits.h> #include <linux/bits.h>
#include <linux/circ_buf.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/delay.h> #include <linux/delay.h>
@ -473,7 +474,7 @@ static void lpuart32_stop_rx(struct uart_port *port)
static void lpuart_dma_tx(struct lpuart_port *sport) static void lpuart_dma_tx(struct lpuart_port *sport)
{ {
struct circ_buf *xmit = &sport->port.state->xmit; struct tty_port *tport = &sport->port.state->port;
struct scatterlist *sgl = sport->tx_sgl; struct scatterlist *sgl = sport->tx_sgl;
struct device *dev = sport->port.dev; struct device *dev = sport->port.dev;
struct dma_chan *chan = sport->dma_tx_chan; struct dma_chan *chan = sport->dma_tx_chan;
@ -482,18 +483,10 @@ static void lpuart_dma_tx(struct lpuart_port *sport)
if (sport->dma_tx_in_progress) if (sport->dma_tx_in_progress)
return; return;
sport->dma_tx_bytes = uart_circ_chars_pending(xmit); sg_init_table(sgl, ARRAY_SIZE(sport->tx_sgl));
sport->dma_tx_bytes = kfifo_len(&tport->xmit_fifo);
if (xmit->tail < xmit->head || xmit->head == 0) { sport->dma_tx_nents = kfifo_dma_out_prepare(&tport->xmit_fifo, sgl,
sport->dma_tx_nents = 1; ARRAY_SIZE(sport->tx_sgl), sport->dma_tx_bytes);
sg_init_one(sgl, xmit->buf + xmit->tail, sport->dma_tx_bytes);
} else {
sport->dma_tx_nents = 2;
sg_init_table(sgl, 2);
sg_set_buf(sgl, xmit->buf + xmit->tail,
UART_XMIT_SIZE - xmit->tail);
sg_set_buf(sgl + 1, xmit->buf, xmit->head);
}
ret = dma_map_sg(chan->device->dev, sgl, sport->dma_tx_nents, ret = dma_map_sg(chan->device->dev, sgl, sport->dma_tx_nents,
DMA_TO_DEVICE); DMA_TO_DEVICE);
@ -521,14 +514,15 @@ static void lpuart_dma_tx(struct lpuart_port *sport)
static bool lpuart_stopped_or_empty(struct uart_port *port) static bool lpuart_stopped_or_empty(struct uart_port *port)
{ {
return uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port); return kfifo_is_empty(&port->state->port.xmit_fifo) ||
uart_tx_stopped(port);
} }
static void lpuart_dma_tx_complete(void *arg) static void lpuart_dma_tx_complete(void *arg)
{ {
struct lpuart_port *sport = arg; struct lpuart_port *sport = arg;
struct scatterlist *sgl = &sport->tx_sgl[0]; struct scatterlist *sgl = &sport->tx_sgl[0];
struct circ_buf *xmit = &sport->port.state->xmit; struct tty_port *tport = &sport->port.state->port;
struct dma_chan *chan = sport->dma_tx_chan; struct dma_chan *chan = sport->dma_tx_chan;
unsigned long flags; unsigned long flags;
@ -545,7 +539,7 @@ static void lpuart_dma_tx_complete(void *arg)
sport->dma_tx_in_progress = false; sport->dma_tx_in_progress = false;
uart_port_unlock_irqrestore(&sport->port, flags); uart_port_unlock_irqrestore(&sport->port, flags);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&sport->port); uart_write_wakeup(&sport->port);
if (waitqueue_active(&sport->dma_wait)) { if (waitqueue_active(&sport->dma_wait)) {
@ -756,8 +750,9 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
static inline void lpuart32_transmit_buffer(struct lpuart_port *sport) static inline void lpuart32_transmit_buffer(struct lpuart_port *sport)
{ {
struct circ_buf *xmit = &sport->port.state->xmit; struct tty_port *tport = &sport->port.state->port;
unsigned long txcnt; unsigned long txcnt;
unsigned char c;
if (sport->port.x_char) { if (sport->port.x_char) {
lpuart32_write(&sport->port, sport->port.x_char, UARTDATA); lpuart32_write(&sport->port, sport->port.x_char, UARTDATA);
@ -774,18 +769,18 @@ static inline void lpuart32_transmit_buffer(struct lpuart_port *sport)
txcnt = lpuart32_read(&sport->port, UARTWATER); txcnt = lpuart32_read(&sport->port, UARTWATER);
txcnt = txcnt >> UARTWATER_TXCNT_OFF; txcnt = txcnt >> UARTWATER_TXCNT_OFF;
txcnt &= UARTWATER_COUNT_MASK; txcnt &= UARTWATER_COUNT_MASK;
while (!uart_circ_empty(xmit) && (txcnt < sport->txfifo_size)) { while (txcnt < sport->txfifo_size &&
lpuart32_write(&sport->port, xmit->buf[xmit->tail], UARTDATA); uart_fifo_get(&sport->port, &c)) {
uart_xmit_advance(&sport->port, 1); lpuart32_write(&sport->port, c, UARTDATA);
txcnt = lpuart32_read(&sport->port, UARTWATER); txcnt = lpuart32_read(&sport->port, UARTWATER);
txcnt = txcnt >> UARTWATER_TXCNT_OFF; txcnt = txcnt >> UARTWATER_TXCNT_OFF;
txcnt &= UARTWATER_COUNT_MASK; txcnt &= UARTWATER_COUNT_MASK;
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&sport->port); uart_write_wakeup(&sport->port);
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
lpuart32_stop_tx(&sport->port); lpuart32_stop_tx(&sport->port);
} }

View File

@ -877,10 +877,10 @@ unlock:
static int icom_write(struct uart_port *port) static int icom_write(struct uart_port *port)
{ {
struct icom_port *icom_port = to_icom_port(port); struct icom_port *icom_port = to_icom_port(port);
struct tty_port *tport = &port->state->port;
unsigned long data_count; unsigned long data_count;
unsigned char cmdReg; unsigned char cmdReg;
unsigned long offset; unsigned long offset;
int temp_tail = port->state->xmit.tail;
trace(icom_port, "WRITE", 0); trace(icom_port, "WRITE", 0);
@ -890,16 +890,8 @@ static int icom_write(struct uart_port *port)
return 0; return 0;
} }
data_count = 0; data_count = kfifo_out_peek(&tport->xmit_fifo, icom_port->xmit_buf,
while ((port->state->xmit.head != temp_tail) && XMIT_BUFF_SZ);
(data_count <= XMIT_BUFF_SZ)) {
icom_port->xmit_buf[data_count++] =
port->state->xmit.buf[temp_tail];
temp_tail++;
temp_tail &= (UART_XMIT_SIZE - 1);
}
if (data_count) { if (data_count) {
icom_port->statStg->xmit[0].flags = icom_port->statStg->xmit[0].flags =
@ -956,7 +948,8 @@ static inline void check_modem_status(struct icom_port *icom_port)
static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port) static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
{ {
u16 count, i; struct tty_port *tport = &icom_port->uart_port.state->port;
u16 count;
if (port_int_reg & (INT_XMIT_COMPLETED)) { if (port_int_reg & (INT_XMIT_COMPLETED)) {
trace(icom_port, "XMIT_COMPLETE", 0); trace(icom_port, "XMIT_COMPLETE", 0);
@ -968,13 +961,7 @@ static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
count = le16_to_cpu(icom_port->statStg->xmit[0].leLength); count = le16_to_cpu(icom_port->statStg->xmit[0].leLength);
icom_port->uart_port.icount.tx += count; icom_port->uart_port.icount.tx += count;
for (i=0; i<count && kfifo_skip_count(&tport->xmit_fifo, count);
!uart_circ_empty(&icom_port->uart_port.state->xmit); i++) {
icom_port->uart_port.state->xmit.tail++;
icom_port->uart_port.state->xmit.tail &=
(UART_XMIT_SIZE - 1);
}
if (!icom_write(&icom_port->uart_port)) if (!icom_write(&icom_port->uart_port))
/* activate write queue */ /* activate write queue */

View File

@ -8,6 +8,7 @@
* Copyright (C) 2004 Pengutronix * Copyright (C) 2004 Pengutronix
*/ */
#include <linux/circ_buf.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
@ -521,7 +522,8 @@ static void imx_uart_dma_tx(struct imx_port *sport);
/* called with port.lock taken and irqs off */ /* called with port.lock taken and irqs off */
static inline void imx_uart_transmit_buffer(struct imx_port *sport) static inline void imx_uart_transmit_buffer(struct imx_port *sport)
{ {
struct circ_buf *xmit = &sport->port.state->xmit; struct tty_port *tport = &sport->port.state->port;
unsigned char c;
if (sport->port.x_char) { if (sport->port.x_char) {
/* Send next char */ /* Send next char */
@ -531,7 +533,8 @@ static inline void imx_uart_transmit_buffer(struct imx_port *sport)
return; return;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { if (kfifo_is_empty(&tport->xmit_fifo) ||
uart_tx_stopped(&sport->port)) {
imx_uart_stop_tx(&sport->port); imx_uart_stop_tx(&sport->port);
return; return;
} }
@ -555,26 +558,22 @@ static inline void imx_uart_transmit_buffer(struct imx_port *sport)
return; return;
} }
while (!uart_circ_empty(xmit) && while (!(imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL) &&
!(imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL)) { uart_fifo_get(&sport->port, &c))
/* send xmit->buf[xmit->tail] imx_uart_writel(sport, c, URTX0);
* out the port here */
imx_uart_writel(sport, xmit->buf[xmit->tail], URTX0);
uart_xmit_advance(&sport->port, 1);
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&sport->port); uart_write_wakeup(&sport->port);
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
imx_uart_stop_tx(&sport->port); imx_uart_stop_tx(&sport->port);
} }
static void imx_uart_dma_tx_callback(void *data) static void imx_uart_dma_tx_callback(void *data)
{ {
struct imx_port *sport = data; struct imx_port *sport = data;
struct tty_port *tport = &sport->port.state->port;
struct scatterlist *sgl = &sport->tx_sgl[0]; struct scatterlist *sgl = &sport->tx_sgl[0];
struct circ_buf *xmit = &sport->port.state->xmit;
unsigned long flags; unsigned long flags;
u32 ucr1; u32 ucr1;
@ -592,10 +591,11 @@ static void imx_uart_dma_tx_callback(void *data)
sport->dma_is_txing = 0; sport->dma_is_txing = 0;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&sport->port); uart_write_wakeup(&sport->port);
if (!uart_circ_empty(xmit) && !uart_tx_stopped(&sport->port)) if (!kfifo_is_empty(&tport->xmit_fifo) &&
!uart_tx_stopped(&sport->port))
imx_uart_dma_tx(sport); imx_uart_dma_tx(sport);
else if (sport->port.rs485.flags & SER_RS485_ENABLED) { else if (sport->port.rs485.flags & SER_RS485_ENABLED) {
u32 ucr4 = imx_uart_readl(sport, UCR4); u32 ucr4 = imx_uart_readl(sport, UCR4);
@ -609,7 +609,7 @@ static void imx_uart_dma_tx_callback(void *data)
/* called with port.lock taken and irqs off */ /* called with port.lock taken and irqs off */
static void imx_uart_dma_tx(struct imx_port *sport) static void imx_uart_dma_tx(struct imx_port *sport)
{ {
struct circ_buf *xmit = &sport->port.state->xmit; struct tty_port *tport = &sport->port.state->port;
struct scatterlist *sgl = sport->tx_sgl; struct scatterlist *sgl = sport->tx_sgl;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
struct dma_chan *chan = sport->dma_chan_tx; struct dma_chan *chan = sport->dma_chan_tx;
@ -624,18 +624,10 @@ static void imx_uart_dma_tx(struct imx_port *sport)
ucr4 &= ~UCR4_TCEN; ucr4 &= ~UCR4_TCEN;
imx_uart_writel(sport, ucr4, UCR4); imx_uart_writel(sport, ucr4, UCR4);
sport->tx_bytes = uart_circ_chars_pending(xmit); sg_init_table(sgl, ARRAY_SIZE(sport->tx_sgl));
sport->tx_bytes = kfifo_len(&tport->xmit_fifo);
if (xmit->tail < xmit->head || xmit->head == 0) { sport->dma_tx_nents = kfifo_dma_out_prepare(&tport->xmit_fifo, sgl,
sport->dma_tx_nents = 1; ARRAY_SIZE(sport->tx_sgl), sport->tx_bytes);
sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes);
} else {
sport->dma_tx_nents = 2;
sg_init_table(sgl, 2);
sg_set_buf(sgl, xmit->buf + xmit->tail,
UART_XMIT_SIZE - xmit->tail);
sg_set_buf(sgl + 1, xmit->buf, xmit->head);
}
ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
if (ret == 0) { if (ret == 0) {
@ -653,8 +645,7 @@ static void imx_uart_dma_tx(struct imx_port *sport)
desc->callback = imx_uart_dma_tx_callback; desc->callback = imx_uart_dma_tx_callback;
desc->callback_param = sport; desc->callback_param = sport;
dev_dbg(dev, "TX: prepare to send %lu bytes by DMA.\n", dev_dbg(dev, "TX: prepare to send %u bytes by DMA.\n", sport->tx_bytes);
uart_circ_chars_pending(xmit));
ucr1 = imx_uart_readl(sport, UCR1); ucr1 = imx_uart_readl(sport, UCR1);
ucr1 |= UCR1_TXDMAEN; ucr1 |= UCR1_TXDMAEN;
@ -671,9 +662,10 @@ static void imx_uart_dma_tx(struct imx_port *sport)
static void imx_uart_start_tx(struct uart_port *port) static void imx_uart_start_tx(struct uart_port *port)
{ {
struct imx_port *sport = (struct imx_port *)port; struct imx_port *sport = (struct imx_port *)port;
struct tty_port *tport = &sport->port.state->port;
u32 ucr1; u32 ucr1;
if (!sport->port.x_char && uart_circ_empty(&port->state->xmit)) if (!sport->port.x_char && kfifo_is_empty(&tport->xmit_fifo))
return; return;
/* /*
@ -749,7 +741,7 @@ static void imx_uart_start_tx(struct uart_port *port)
return; return;
} }
if (!uart_circ_empty(&port->state->xmit) && if (!kfifo_is_empty(&tport->xmit_fifo) &&
!uart_tx_stopped(port)) !uart_tx_stopped(port))
imx_uart_dma_tx(sport); imx_uart_dma_tx(sport);
return; return;

View File

@ -355,7 +355,8 @@ static void ip22zilog_status_handle(struct uart_ip22zilog_port *up,
static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up, static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up,
struct zilog_channel *channel) struct zilog_channel *channel)
{ {
struct circ_buf *xmit; struct tty_port *tport;
unsigned char c;
if (ZS_IS_CONS(up)) { if (ZS_IS_CONS(up)) {
unsigned char status = readb(&channel->control); unsigned char status = readb(&channel->control);
@ -398,20 +399,18 @@ static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up,
if (up->port.state == NULL) if (up->port.state == NULL)
goto ack_tx_int; goto ack_tx_int;
xmit = &up->port.state->xmit; tport = &up->port.state->port;
if (uart_circ_empty(xmit))
goto ack_tx_int;
if (uart_tx_stopped(&up->port)) if (uart_tx_stopped(&up->port))
goto ack_tx_int; goto ack_tx_int;
if (!uart_fifo_get(&up->port, &c))
goto ack_tx_int;
up->flags |= IP22ZILOG_FLAG_TX_ACTIVE; up->flags |= IP22ZILOG_FLAG_TX_ACTIVE;
writeb(xmit->buf[xmit->tail], &channel->data); writeb(c, &channel->data);
ZSDELAY(); ZSDELAY();
ZS_WSYNC(channel); ZS_WSYNC(channel);
uart_xmit_advance(&up->port, 1); if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&up->port); uart_write_wakeup(&up->port);
return; return;
@ -600,17 +599,16 @@ static void ip22zilog_start_tx(struct uart_port *port)
port->icount.tx++; port->icount.tx++;
port->x_char = 0; port->x_char = 0;
} else { } else {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned char c;
if (uart_circ_empty(xmit)) if (!uart_fifo_get(port, &c))
return; return;
writeb(xmit->buf[xmit->tail], &channel->data); writeb(c, &channel->data);
ZSDELAY(); ZSDELAY();
ZS_WSYNC(channel); ZS_WSYNC(channel);
uart_xmit_advance(port, 1); if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&up->port); uart_write_wakeup(&up->port);
} }
} }

View File

@ -443,20 +443,14 @@ static void cls_copy_data_from_uart_to_queue(struct jsm_channel *ch)
static void cls_copy_data_from_queue_to_uart(struct jsm_channel *ch) static void cls_copy_data_from_queue_to_uart(struct jsm_channel *ch)
{ {
u16 tail; struct tty_port *tport;
int n; int n;
int qlen;
u32 len_written = 0; u32 len_written = 0;
struct circ_buf *circ;
if (!ch) if (!ch)
return; return;
circ = &ch->uart_port.state->xmit; tport = &ch->uart_port.state->port;
/* No data to write to the UART */
if (uart_circ_empty(circ))
return;
/* If port is "stopped", don't send any data to the UART */ /* If port is "stopped", don't send any data to the UART */
if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_BREAK_SENDING)) if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_BREAK_SENDING))
@ -467,29 +461,22 @@ static void cls_copy_data_from_queue_to_uart(struct jsm_channel *ch)
return; return;
n = 32; n = 32;
/* cache tail of queue */
tail = circ->tail & (UART_XMIT_SIZE - 1);
qlen = uart_circ_chars_pending(circ);
/* Find minimum of the FIFO space, versus queue length */
n = min(n, qlen);
while (n > 0) { while (n > 0) {
writeb(circ->buf[tail], &ch->ch_cls_uart->txrx); unsigned char c;
tail = (tail + 1) & (UART_XMIT_SIZE - 1);
if (!kfifo_get(&tport->xmit_fifo, &c))
break;
writeb(c, &ch->ch_cls_uart->txrx);
n--; n--;
ch->ch_txcount++; ch->ch_txcount++;
len_written++; len_written++;
} }
/* Update the final tail */
circ->tail = tail & (UART_XMIT_SIZE - 1);
if (len_written > ch->ch_t_tlevel) if (len_written > ch->ch_t_tlevel)
ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
if (uart_circ_empty(circ)) if (kfifo_is_empty(&tport->xmit_fifo))
uart_write_wakeup(&ch->uart_port); uart_write_wakeup(&ch->uart_port);
} }

View File

@ -474,21 +474,21 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch) static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch)
{ {
u16 head; struct tty_port *tport;
u16 tail; unsigned char *tail;
unsigned char c;
int n; int n;
int s; int s;
int qlen; int qlen;
u32 len_written = 0; u32 len_written = 0;
struct circ_buf *circ;
if (!ch) if (!ch)
return; return;
circ = &ch->uart_port.state->xmit; tport = &ch->uart_port.state->port;
/* No data to write to the UART */ /* No data to write to the UART */
if (uart_circ_empty(circ)) if (kfifo_is_empty(&tport->xmit_fifo))
return; return;
/* If port is "stopped", don't send any data to the UART */ /* If port is "stopped", don't send any data to the UART */
@ -504,10 +504,9 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch)
if (ch->ch_cached_lsr & UART_LSR_THRE) { if (ch->ch_cached_lsr & UART_LSR_THRE) {
ch->ch_cached_lsr &= ~(UART_LSR_THRE); ch->ch_cached_lsr &= ~(UART_LSR_THRE);
writeb(circ->buf[circ->tail], &ch->ch_neo_uart->txrx); WARN_ON_ONCE(!kfifo_get(&tport->xmit_fifo, &c));
jsm_dbg(WRITE, &ch->ch_bd->pci_dev, writeb(c, &ch->ch_neo_uart->txrx);
"Tx data: %x\n", circ->buf[circ->tail]); jsm_dbg(WRITE, &ch->ch_bd->pci_dev, "Tx data: %x\n", c);
circ->tail = (circ->tail + 1) & (UART_XMIT_SIZE - 1);
ch->ch_txcount++; ch->ch_txcount++;
} }
return; return;
@ -520,38 +519,27 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch)
return; return;
n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel; n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel;
qlen = kfifo_len(&tport->xmit_fifo);
/* cache head and tail of queue */
head = circ->head & (UART_XMIT_SIZE - 1);
tail = circ->tail & (UART_XMIT_SIZE - 1);
qlen = uart_circ_chars_pending(circ);
/* Find minimum of the FIFO space, versus queue length */ /* Find minimum of the FIFO space, versus queue length */
n = min(n, qlen); n = min(n, qlen);
while (n > 0) { while (n > 0) {
s = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, n);
s = ((head >= tail) ? head : UART_XMIT_SIZE) - tail;
s = min(s, n);
if (s <= 0) if (s <= 0)
break; break;
memcpy_toio(&ch->ch_neo_uart->txrxburst, circ->buf + tail, s); memcpy_toio(&ch->ch_neo_uart->txrxburst, tail, s);
/* Add and flip queue if needed */ kfifo_skip_count(&tport->xmit_fifo, s);
tail = (tail + s) & (UART_XMIT_SIZE - 1);
n -= s; n -= s;
ch->ch_txcount += s; ch->ch_txcount += s;
len_written += s; len_written += s;
} }
/* Update the final tail */
circ->tail = tail & (UART_XMIT_SIZE - 1);
if (len_written >= ch->ch_t_tlevel) if (len_written >= ch->ch_t_tlevel)
ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
if (uart_circ_empty(circ)) if (kfifo_is_empty(&tport->xmit_fifo))
uart_write_wakeup(&ch->uart_port); uart_write_wakeup(&ch->uart_port);
} }

View File

@ -257,10 +257,11 @@ static int max3100_handlerx(struct max3100_port *s, u16 rx)
static void max3100_work(struct work_struct *w) static void max3100_work(struct work_struct *w)
{ {
struct max3100_port *s = container_of(w, struct max3100_port, work); struct max3100_port *s = container_of(w, struct max3100_port, work);
struct tty_port *tport = &s->port.state->port;
unsigned char ch;
int rxchars; int rxchars;
u16 tx, rx; u16 tx, rx;
int conf, cconf, crts; int conf, cconf, crts;
struct circ_buf *xmit = &s->port.state->xmit;
dev_dbg(&s->spi->dev, "%s\n", __func__); dev_dbg(&s->spi->dev, "%s\n", __func__);
@ -290,10 +291,9 @@ static void max3100_work(struct work_struct *w)
tx = s->port.x_char; tx = s->port.x_char;
s->port.icount.tx++; s->port.icount.tx++;
s->port.x_char = 0; s->port.x_char = 0;
} else if (!uart_circ_empty(xmit) && } else if (!uart_tx_stopped(&s->port) &&
!uart_tx_stopped(&s->port)) { uart_fifo_get(&s->port, &ch)) {
tx = xmit->buf[xmit->tail]; tx = ch;
uart_xmit_advance(&s->port, 1);
} }
if (tx != 0xffff) { if (tx != 0xffff) {
max3100_calc_parity(s, &tx); max3100_calc_parity(s, &tx);
@ -307,13 +307,13 @@ static void max3100_work(struct work_struct *w)
tty_flip_buffer_push(&s->port.state->port); tty_flip_buffer_push(&s->port.state->port);
rxchars = 0; rxchars = 0;
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&s->port); uart_write_wakeup(&s->port);
} while (!s->force_end_work && } while (!s->force_end_work &&
!freezing(current) && !freezing(current) &&
((rx & MAX3100_R) || ((rx & MAX3100_R) ||
(!uart_circ_empty(xmit) && (!kfifo_is_empty(&tport->xmit_fifo) &&
!uart_tx_stopped(&s->port)))); !uart_tx_stopped(&s->port))));
if (rxchars > 0) if (rxchars > 0)

View File

@ -747,8 +747,9 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
static void max310x_handle_tx(struct uart_port *port) static void max310x_handle_tx(struct uart_port *port)
{ {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned int txlen, to_send, until_end; unsigned int txlen, to_send;
unsigned char *tail;
if (unlikely(port->x_char)) { if (unlikely(port->x_char)) {
max310x_port_write(port, MAX310X_THR_REG, port->x_char); max310x_port_write(port, MAX310X_THR_REG, port->x_char);
@ -757,32 +758,26 @@ static void max310x_handle_tx(struct uart_port *port)
return; return;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port))
return; return;
/* Get length of data pending in circular buffer */ /*
to_send = uart_circ_chars_pending(xmit); * It's a circ buffer -- wrap around.
until_end = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); * We could do that in one SPI transaction, but meh.
if (likely(to_send)) { */
while (!kfifo_is_empty(&tport->xmit_fifo)) {
/* Limit to space available in TX FIFO */ /* Limit to space available in TX FIFO */
txlen = max310x_port_read(port, MAX310X_TXFIFOLVL_REG); txlen = max310x_port_read(port, MAX310X_TXFIFOLVL_REG);
txlen = port->fifosize - txlen; txlen = port->fifosize - txlen;
to_send = (to_send > txlen) ? txlen : to_send; if (!txlen)
break;
if (until_end < to_send) { to_send = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, txlen);
/* max310x_batch_write(port, tail, to_send);
* It's a circ buffer -- wrap around.
* We could do that in one SPI transaction, but meh.
*/
max310x_batch_write(port, xmit->buf + xmit->tail, until_end);
max310x_batch_write(port, xmit->buf, to_send - until_end);
} else {
max310x_batch_write(port, xmit->buf + xmit->tail, to_send);
}
uart_xmit_advance(port, to_send); uart_xmit_advance(port, to_send);
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
} }

View File

@ -293,17 +293,14 @@ static void men_z135_handle_rx(struct men_z135_port *uart)
static void men_z135_handle_tx(struct men_z135_port *uart) static void men_z135_handle_tx(struct men_z135_port *uart)
{ {
struct uart_port *port = &uart->port; struct uart_port *port = &uart->port;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned char *tail;
unsigned int n, txfree;
u32 txc; u32 txc;
u32 wptr; u32 wptr;
int qlen; int qlen;
int n;
int txfree;
int head;
int tail;
int s;
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
goto out; goto out;
if (uart_tx_stopped(port)) if (uart_tx_stopped(port))
@ -313,7 +310,7 @@ static void men_z135_handle_tx(struct men_z135_port *uart)
goto out; goto out;
/* calculate bytes to copy */ /* calculate bytes to copy */
qlen = uart_circ_chars_pending(xmit); qlen = kfifo_len(&tport->xmit_fifo);
if (qlen <= 0) if (qlen <= 0)
goto out; goto out;
@ -345,21 +342,18 @@ static void men_z135_handle_tx(struct men_z135_port *uart)
if (n <= 0) if (n <= 0)
goto irq_en; goto irq_en;
head = xmit->head & (UART_XMIT_SIZE - 1); n = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail,
tail = xmit->tail & (UART_XMIT_SIZE - 1); min_t(unsigned int, UART_XMIT_SIZE, n));
memcpy_toio(port->membase + MEN_Z135_TX_RAM, tail, n);
s = ((head >= tail) ? head : UART_XMIT_SIZE) - tail;
n = min(n, s);
memcpy_toio(port->membase + MEN_Z135_TX_RAM, &xmit->buf[xmit->tail], n);
iowrite32(n & 0x3ff, port->membase + MEN_Z135_TX_CTRL); iowrite32(n & 0x3ff, port->membase + MEN_Z135_TX_CTRL);
uart_xmit_advance(port, n); uart_xmit_advance(port, n);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
irq_en: irq_en:
if (!uart_circ_empty(xmit)) if (!kfifo_is_empty(&tport->xmit_fifo))
men_z135_reg_set(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN); men_z135_reg_set(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);
else else
men_z135_reg_clr(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN); men_z135_reg_clr(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);

View File

@ -141,8 +141,8 @@ static void meson_uart_shutdown(struct uart_port *port)
static void meson_uart_start_tx(struct uart_port *port) static void meson_uart_start_tx(struct uart_port *port)
{ {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned int ch; unsigned char ch;
u32 val; u32 val;
if (uart_tx_stopped(port)) { if (uart_tx_stopped(port)) {
@ -158,21 +158,20 @@ static void meson_uart_start_tx(struct uart_port *port)
continue; continue;
} }
if (uart_circ_empty(xmit)) if (!uart_fifo_get(port, &ch))
break; break;
ch = xmit->buf[xmit->tail];
writel(ch, port->membase + AML_UART_WFIFO); writel(ch, port->membase + AML_UART_WFIFO);
uart_xmit_advance(port, 1); uart_xmit_advance(port, 1);
} }
if (!uart_circ_empty(xmit)) { if (!kfifo_is_empty(&tport->xmit_fifo)) {
val = readl(port->membase + AML_UART_CONTROL); val = readl(port->membase + AML_UART_CONTROL);
val |= AML_UART_TX_INT_EN; val |= AML_UART_TX_INT_EN;
writel(val, port->membase + AML_UART_CONTROL); writel(val, port->membase + AML_UART_CONTROL);
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
} }

View File

@ -72,7 +72,7 @@ static void mlb_usio_stop_tx(struct uart_port *port)
static void mlb_usio_tx_chars(struct uart_port *port) static void mlb_usio_tx_chars(struct uart_port *port)
{ {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
int count; int count;
writew(readw(port->membase + MLB_USIO_REG_FCR) & ~MLB_USIO_FCR_FTIE, writew(readw(port->membase + MLB_USIO_REG_FCR) & ~MLB_USIO_FCR_FTIE,
@ -87,7 +87,7 @@ static void mlb_usio_tx_chars(struct uart_port *port)
port->x_char = 0; port->x_char = 0;
return; return;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
mlb_usio_stop_tx(port); mlb_usio_stop_tx(port);
return; return;
} }
@ -96,12 +96,13 @@ static void mlb_usio_tx_chars(struct uart_port *port)
(readw(port->membase + MLB_USIO_REG_FBYTE) & 0xff); (readw(port->membase + MLB_USIO_REG_FBYTE) & 0xff);
do { do {
writew(xmit->buf[xmit->tail], port->membase + MLB_USIO_REG_DR); unsigned char ch;
uart_xmit_advance(port, 1); if (!uart_fifo_get(port, &ch))
if (uart_circ_empty(xmit))
break; break;
writew(ch, port->membase + MLB_USIO_REG_DR);
port->icount.tx++;
} while (--count > 0); } while (--count > 0);
writew(readw(port->membase + MLB_USIO_REG_FCR) & ~MLB_USIO_FCR_FDRQ, writew(readw(port->membase + MLB_USIO_REG_FCR) & ~MLB_USIO_FCR_FDRQ,
@ -110,10 +111,10 @@ static void mlb_usio_tx_chars(struct uart_port *port)
writeb(readb(port->membase + MLB_USIO_REG_SCR) | MLB_USIO_SCR_TBIE, writeb(readb(port->membase + MLB_USIO_REG_SCR) | MLB_USIO_SCR_TBIE,
port->membase + MLB_USIO_REG_SCR); port->membase + MLB_USIO_REG_SCR);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
mlb_usio_stop_tx(port); mlb_usio_stop_tx(port);
} }

View File

@ -452,7 +452,7 @@ static void msm_complete_tx_dma(void *args)
{ {
struct msm_port *msm_port = args; struct msm_port *msm_port = args;
struct uart_port *port = &msm_port->uart; struct uart_port *port = &msm_port->uart;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
struct msm_dma *dma = &msm_port->tx_dma; struct msm_dma *dma = &msm_port->tx_dma;
struct dma_tx_state state; struct dma_tx_state state;
unsigned long flags; unsigned long flags;
@ -486,7 +486,7 @@ static void msm_complete_tx_dma(void *args)
msm_port->imr |= MSM_UART_IMR_TXLEV; msm_port->imr |= MSM_UART_IMR_TXLEV;
msm_write(port, msm_port->imr, MSM_UART_IMR); msm_write(port, msm_port->imr, MSM_UART_IMR);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
msm_handle_tx(port); msm_handle_tx(port);
@ -496,14 +496,14 @@ done:
static int msm_handle_tx_dma(struct msm_port *msm_port, unsigned int count) static int msm_handle_tx_dma(struct msm_port *msm_port, unsigned int count)
{ {
struct circ_buf *xmit = &msm_port->uart.state->xmit;
struct uart_port *port = &msm_port->uart; struct uart_port *port = &msm_port->uart;
struct tty_port *tport = &port->state->port;
struct msm_dma *dma = &msm_port->tx_dma; struct msm_dma *dma = &msm_port->tx_dma;
int ret; int ret;
u32 val; u32 val;
sg_init_table(&dma->tx_sg, 1); sg_init_table(&dma->tx_sg, 1);
sg_set_buf(&dma->tx_sg, &xmit->buf[xmit->tail], count); kfifo_dma_out_prepare(&tport->xmit_fifo, &dma->tx_sg, 1, count);
ret = dma_map_sg(port->dev, &dma->tx_sg, 1, dma->dir); ret = dma_map_sg(port->dev, &dma->tx_sg, 1, dma->dir);
if (ret) if (ret)
@ -843,8 +843,8 @@ static void msm_handle_rx(struct uart_port *port)
static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count) static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count)
{ {
struct circ_buf *xmit = &port->state->xmit;
struct msm_port *msm_port = to_msm_port(port); struct msm_port *msm_port = to_msm_port(port);
struct tty_port *tport = &port->state->port;
unsigned int num_chars; unsigned int num_chars;
unsigned int tf_pointer = 0; unsigned int tf_pointer = 0;
void __iomem *tf; void __iomem *tf;
@ -858,8 +858,7 @@ static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count)
msm_reset_dm_count(port, tx_count); msm_reset_dm_count(port, tx_count);
while (tf_pointer < tx_count) { while (tf_pointer < tx_count) {
int i; unsigned char buf[4] = { 0 };
char buf[4] = { 0 };
if (!(msm_read(port, MSM_UART_SR) & MSM_UART_SR_TX_READY)) if (!(msm_read(port, MSM_UART_SR) & MSM_UART_SR_TX_READY))
break; break;
@ -870,26 +869,23 @@ static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count)
else else
num_chars = 1; num_chars = 1;
for (i = 0; i < num_chars; i++) num_chars = uart_fifo_out(port, buf, num_chars);
buf[i] = xmit->buf[xmit->tail + i];
iowrite32_rep(tf, buf, 1); iowrite32_rep(tf, buf, 1);
uart_xmit_advance(port, num_chars);
tf_pointer += num_chars; tf_pointer += num_chars;
} }
/* disable tx interrupts if nothing more to send */ /* disable tx interrupts if nothing more to send */
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
msm_stop_tx(port); msm_stop_tx(port);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
} }
static void msm_handle_tx(struct uart_port *port) static void msm_handle_tx(struct uart_port *port)
{ {
struct msm_port *msm_port = to_msm_port(port); struct msm_port *msm_port = to_msm_port(port);
struct circ_buf *xmit = &msm_port->uart.state->xmit; struct tty_port *tport = &port->state->port;
struct msm_dma *dma = &msm_port->tx_dma; struct msm_dma *dma = &msm_port->tx_dma;
unsigned int pio_count, dma_count, dma_min; unsigned int pio_count, dma_count, dma_min;
char buf[4] = { 0 }; char buf[4] = { 0 };
@ -913,13 +909,13 @@ static void msm_handle_tx(struct uart_port *port)
return; return;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
msm_stop_tx(port); msm_stop_tx(port);
return; return;
} }
pio_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); dma_count = pio_count = kfifo_out_linear(&tport->xmit_fifo, NULL,
dma_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); UART_XMIT_SIZE);
dma_min = 1; /* Always DMA */ dma_min = 1; /* Always DMA */
if (msm_port->is_uartdm > UARTDM_1P3) { if (msm_port->is_uartdm > UARTDM_1P3) {

View File

@ -219,12 +219,10 @@ static void mvebu_uart_stop_tx(struct uart_port *port)
static void mvebu_uart_start_tx(struct uart_port *port) static void mvebu_uart_start_tx(struct uart_port *port)
{ {
unsigned int ctl; unsigned int ctl;
struct circ_buf *xmit = &port->state->xmit; unsigned char c;
if (IS_EXTENDED(port) && !uart_circ_empty(xmit)) { if (IS_EXTENDED(port) && uart_fifo_get(port, &c))
writel(xmit->buf[xmit->tail], port->membase + UART_TSH(port)); writel(c, port->membase + UART_TSH(port));
uart_xmit_advance(port, 1);
}
ctl = readl(port->membase + UART_INTR(port)); ctl = readl(port->membase + UART_INTR(port));
ctl |= CTRL_TX_RDY_INT(port); ctl |= CTRL_TX_RDY_INT(port);

View File

@ -517,7 +517,7 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s);
static void dma_tx_callback(void *param) static void dma_tx_callback(void *param)
{ {
struct mxs_auart_port *s = param; struct mxs_auart_port *s = param;
struct circ_buf *xmit = &s->port.state->xmit; struct tty_port *tport = &s->port.state->port;
dma_unmap_sg(s->dev, &s->tx_sgl, 1, DMA_TO_DEVICE); dma_unmap_sg(s->dev, &s->tx_sgl, 1, DMA_TO_DEVICE);
@ -526,7 +526,7 @@ static void dma_tx_callback(void *param)
smp_mb__after_atomic(); smp_mb__after_atomic();
/* wake up the possible processes. */ /* wake up the possible processes. */
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&s->port); uart_write_wakeup(&s->port);
mxs_auart_tx_chars(s); mxs_auart_tx_chars(s);
@ -568,33 +568,22 @@ static int mxs_auart_dma_tx(struct mxs_auart_port *s, int size)
static void mxs_auart_tx_chars(struct mxs_auart_port *s) static void mxs_auart_tx_chars(struct mxs_auart_port *s)
{ {
struct circ_buf *xmit = &s->port.state->xmit; struct tty_port *tport = &s->port.state->port;
bool pending; bool pending;
u8 ch; u8 ch;
if (auart_dma_enabled(s)) { if (auart_dma_enabled(s)) {
u32 i = 0; u32 i = 0;
int size;
void *buffer = s->tx_dma_buf; void *buffer = s->tx_dma_buf;
if (test_and_set_bit(MXS_AUART_DMA_TX_SYNC, &s->flags)) if (test_and_set_bit(MXS_AUART_DMA_TX_SYNC, &s->flags))
return; return;
while (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {
size = min_t(u32, UART_XMIT_SIZE - i,
CIRC_CNT_TO_END(xmit->head,
xmit->tail,
UART_XMIT_SIZE));
memcpy(buffer + i, xmit->buf + xmit->tail, size);
xmit->tail = (xmit->tail + size) & (UART_XMIT_SIZE - 1);
i += size;
if (i >= UART_XMIT_SIZE)
break;
}
if (uart_tx_stopped(&s->port)) if (uart_tx_stopped(&s->port))
mxs_auart_stop_tx(&s->port); mxs_auart_stop_tx(&s->port);
else
i = kfifo_out(&tport->xmit_fifo, buffer,
UART_XMIT_SIZE);
if (i) { if (i) {
mxs_auart_dma_tx(s, i); mxs_auart_dma_tx(s, i);

View File

@ -808,7 +808,7 @@ static int dma_handle_rx(struct eg20t_port *priv)
static unsigned int handle_tx(struct eg20t_port *priv) static unsigned int handle_tx(struct eg20t_port *priv)
{ {
struct uart_port *port = &priv->port; struct uart_port *port = &priv->port;
struct circ_buf *xmit = &port->state->xmit; unsigned char ch;
int fifo_size; int fifo_size;
int tx_empty; int tx_empty;
@ -830,9 +830,9 @@ static unsigned int handle_tx(struct eg20t_port *priv)
fifo_size--; fifo_size--;
} }
while (!uart_tx_stopped(port) && !uart_circ_empty(xmit) && fifo_size) { while (!uart_tx_stopped(port) && fifo_size &&
iowrite8(xmit->buf[xmit->tail], priv->membase + PCH_UART_THR); uart_fifo_get(port, &ch)) {
uart_xmit_advance(port, 1); iowrite8(ch, priv->membase + PCH_UART_THR);
fifo_size--; fifo_size--;
tx_empty = 0; tx_empty = 0;
} }
@ -850,14 +850,14 @@ static unsigned int handle_tx(struct eg20t_port *priv)
static unsigned int dma_handle_tx(struct eg20t_port *priv) static unsigned int dma_handle_tx(struct eg20t_port *priv)
{ {
struct uart_port *port = &priv->port; struct uart_port *port = &priv->port;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
struct scatterlist *sg; struct scatterlist *sg;
int nent; int nent;
int fifo_size; int fifo_size;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
unsigned int bytes, tail;
int num; int num;
int i; int i;
int bytes;
int size; int size;
int rem; int rem;
@ -886,7 +886,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
fifo_size--; fifo_size--;
} }
bytes = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); bytes = kfifo_out_linear(&tport->xmit_fifo, &tail, UART_XMIT_SIZE);
if (!bytes) { if (!bytes) {
dev_dbg(priv->port.dev, "%s 0 bytes return\n", __func__); dev_dbg(priv->port.dev, "%s 0 bytes return\n", __func__);
pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
@ -920,10 +920,10 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
for (i = 0; i < num; i++, sg++) { for (i = 0; i < num; i++, sg++) {
if (i == (num - 1)) if (i == (num - 1))
sg_set_page(sg, virt_to_page(xmit->buf), sg_set_page(sg, virt_to_page(tport->xmit_buf),
rem, fifo_size * i); rem, fifo_size * i);
else else
sg_set_page(sg, virt_to_page(xmit->buf), sg_set_page(sg, virt_to_page(tport->xmit_buf),
size, fifo_size * i); size, fifo_size * i);
} }
@ -937,8 +937,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
priv->nent = nent; priv->nent = nent;
for (i = 0; i < nent; i++, sg++) { for (i = 0; i < nent; i++, sg++) {
sg->offset = (xmit->tail & (UART_XMIT_SIZE - 1)) + sg->offset = tail + fifo_size * i;
fifo_size * i;
sg_dma_address(sg) = (sg_dma_address(sg) & sg_dma_address(sg) = (sg_dma_address(sg) &
~(UART_XMIT_SIZE - 1)) + sg->offset; ~(UART_XMIT_SIZE - 1)) + sg->offset;
if (i == (nent - 1)) if (i == (nent - 1))

View File

@ -342,7 +342,7 @@ static void pic32_uart_do_rx(struct uart_port *port)
static void pic32_uart_do_tx(struct uart_port *port) static void pic32_uart_do_tx(struct uart_port *port)
{ {
struct pic32_sport *sport = to_pic32_sport(port); struct pic32_sport *sport = to_pic32_sport(port);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned int max_count = PIC32_UART_TX_FIFO_DEPTH; unsigned int max_count = PIC32_UART_TX_FIFO_DEPTH;
if (port->x_char) { if (port->x_char) {
@ -357,7 +357,7 @@ static void pic32_uart_do_tx(struct uart_port *port)
return; return;
} }
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
goto txq_empty; goto txq_empty;
/* keep stuffing chars into uart tx buffer /* keep stuffing chars into uart tx buffer
@ -371,21 +371,20 @@ static void pic32_uart_do_tx(struct uart_port *port)
*/ */
while (!(PIC32_UART_STA_UTXBF & while (!(PIC32_UART_STA_UTXBF &
pic32_uart_readl(sport, PIC32_UART_STA))) { pic32_uart_readl(sport, PIC32_UART_STA))) {
unsigned int c = xmit->buf[xmit->tail]; unsigned char c;
if (!uart_fifo_get(port, &c))
break;
pic32_uart_writel(sport, PIC32_UART_TX, c); pic32_uart_writel(sport, PIC32_UART_TX, c);
uart_xmit_advance(port, 1);
if (uart_circ_empty(xmit))
break;
if (--max_count == 0) if (--max_count == 0)
break; break;
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
goto txq_empty; goto txq_empty;
return; return;

View File

@ -347,7 +347,8 @@ static void pmz_status_handle(struct uart_pmac_port *uap)
static void pmz_transmit_chars(struct uart_pmac_port *uap) static void pmz_transmit_chars(struct uart_pmac_port *uap)
{ {
struct circ_buf *xmit; struct tty_port *tport;
unsigned char ch;
if (ZS_IS_CONS(uap)) { if (ZS_IS_CONS(uap)) {
unsigned char status = read_zsreg(uap, R0); unsigned char status = read_zsreg(uap, R0);
@ -398,8 +399,8 @@ static void pmz_transmit_chars(struct uart_pmac_port *uap)
if (uap->port.state == NULL) if (uap->port.state == NULL)
goto ack_tx_int; goto ack_tx_int;
xmit = &uap->port.state->xmit; tport = &uap->port.state->port;
if (uart_circ_empty(xmit)) { if (kfifo_is_empty(&tport->xmit_fifo)) {
uart_write_wakeup(&uap->port); uart_write_wakeup(&uap->port);
goto ack_tx_int; goto ack_tx_int;
} }
@ -407,12 +408,11 @@ static void pmz_transmit_chars(struct uart_pmac_port *uap)
goto ack_tx_int; goto ack_tx_int;
uap->flags |= PMACZILOG_FLAG_TX_ACTIVE; uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
write_zsdata(uap, xmit->buf[xmit->tail]); WARN_ON(!uart_fifo_get(&uap->port, &ch));
write_zsdata(uap, ch);
zssync(uap); zssync(uap);
uart_xmit_advance(&uap->port, 1); if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&uap->port); uart_write_wakeup(&uap->port);
return; return;
@ -620,15 +620,15 @@ static void pmz_start_tx(struct uart_port *port)
port->icount.tx++; port->icount.tx++;
port->x_char = 0; port->x_char = 0;
} else { } else {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned char ch;
if (uart_circ_empty(xmit)) if (!uart_fifo_get(&uap->port, &ch))
return; return;
write_zsdata(uap, xmit->buf[xmit->tail]); write_zsdata(uap, ch);
zssync(uap); zssync(uap);
uart_xmit_advance(port, 1);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&uap->port); uart_write_wakeup(&uap->port);
} }
} }

View File

@ -505,7 +505,7 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
*/ */
qcom_geni_serial_poll_tx_done(uport); qcom_geni_serial_poll_tx_done(uport);
if (!uart_circ_empty(&uport->state->xmit)) { if (!kfifo_is_empty(&uport->state->port.xmit_fifo)) {
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
writel(irq_en | M_TX_FIFO_WATERMARK_EN, writel(irq_en | M_TX_FIFO_WATERMARK_EN,
uport->membase + SE_GENI_M_IRQ_EN); uport->membase + SE_GENI_M_IRQ_EN);
@ -620,22 +620,24 @@ static void qcom_geni_serial_stop_tx_dma(struct uart_port *uport)
static void qcom_geni_serial_start_tx_dma(struct uart_port *uport) static void qcom_geni_serial_start_tx_dma(struct uart_port *uport)
{ {
struct qcom_geni_serial_port *port = to_dev_port(uport); struct qcom_geni_serial_port *port = to_dev_port(uport);
struct circ_buf *xmit = &uport->state->xmit; struct tty_port *tport = &uport->state->port;
unsigned int xmit_size; unsigned int xmit_size;
u8 *tail;
int ret; int ret;
if (port->tx_dma_addr) if (port->tx_dma_addr)
return; return;
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
return; return;
xmit_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); xmit_size = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail,
UART_XMIT_SIZE);
qcom_geni_serial_setup_tx(uport, xmit_size); qcom_geni_serial_setup_tx(uport, xmit_size);
ret = geni_se_tx_dma_prep(&port->se, &xmit->buf[xmit->tail], ret = geni_se_tx_dma_prep(&port->se, tail, xmit_size,
xmit_size, &port->tx_dma_addr); &port->tx_dma_addr);
if (ret) { if (ret) {
dev_err(uport->dev, "unable to start TX SE DMA: %d\n", ret); dev_err(uport->dev, "unable to start TX SE DMA: %d\n", ret);
qcom_geni_serial_stop_tx_dma(uport); qcom_geni_serial_stop_tx_dma(uport);
@ -853,18 +855,16 @@ static void qcom_geni_serial_send_chunk_fifo(struct uart_port *uport,
unsigned int chunk) unsigned int chunk)
{ {
struct qcom_geni_serial_port *port = to_dev_port(uport); struct qcom_geni_serial_port *port = to_dev_port(uport);
struct circ_buf *xmit = &uport->state->xmit; struct tty_port *tport = &uport->state->port;
unsigned int tx_bytes, c, remaining = chunk; unsigned int tx_bytes, remaining = chunk;
u8 buf[BYTES_PER_FIFO_WORD]; u8 buf[BYTES_PER_FIFO_WORD];
while (remaining) { while (remaining) {
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
tx_bytes = min(remaining, BYTES_PER_FIFO_WORD); tx_bytes = min(remaining, BYTES_PER_FIFO_WORD);
for (c = 0; c < tx_bytes ; c++) { tx_bytes = kfifo_out(&tport->xmit_fifo, buf, tx_bytes);
buf[c] = xmit->buf[xmit->tail]; uart_xmit_advance(uport, tx_bytes);
uart_xmit_advance(uport, 1);
}
iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1); iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1);
@ -877,7 +877,7 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport,
bool done, bool active) bool done, bool active)
{ {
struct qcom_geni_serial_port *port = to_dev_port(uport); struct qcom_geni_serial_port *port = to_dev_port(uport);
struct circ_buf *xmit = &uport->state->xmit; struct tty_port *tport = &uport->state->port;
size_t avail; size_t avail;
size_t pending; size_t pending;
u32 status; u32 status;
@ -890,7 +890,7 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport,
if (active) if (active)
pending = port->tx_remaining; pending = port->tx_remaining;
else else
pending = uart_circ_chars_pending(xmit); pending = kfifo_len(&tport->xmit_fifo);
/* All data has been transmitted and acknowledged as received */ /* All data has been transmitted and acknowledged as received */
if (!pending && !status && done) { if (!pending && !status && done) {
@ -933,24 +933,24 @@ out_write_wakeup:
uport->membase + SE_GENI_M_IRQ_EN); uport->membase + SE_GENI_M_IRQ_EN);
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(uport); uart_write_wakeup(uport);
} }
static void qcom_geni_serial_handle_tx_dma(struct uart_port *uport) static void qcom_geni_serial_handle_tx_dma(struct uart_port *uport)
{ {
struct qcom_geni_serial_port *port = to_dev_port(uport); struct qcom_geni_serial_port *port = to_dev_port(uport);
struct circ_buf *xmit = &uport->state->xmit; struct tty_port *tport = &uport->state->port;
uart_xmit_advance(uport, port->tx_remaining); uart_xmit_advance(uport, port->tx_remaining);
geni_se_tx_dma_unprep(&port->se, port->tx_dma_addr, port->tx_remaining); geni_se_tx_dma_unprep(&port->se, port->tx_dma_addr, port->tx_remaining);
port->tx_dma_addr = 0; port->tx_dma_addr = 0;
port->tx_remaining = 0; port->tx_remaining = 0;
if (!uart_circ_empty(xmit)) if (!kfifo_is_empty(&tport->xmit_fifo))
qcom_geni_serial_start_tx_dma(uport); qcom_geni_serial_start_tx_dma(uport);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(uport); uart_write_wakeup(uport);
} }

View File

@ -330,8 +330,8 @@ static void rda_uart_set_termios(struct uart_port *port,
static void rda_uart_send_chars(struct uart_port *port) static void rda_uart_send_chars(struct uart_port *port)
{ {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned int ch; unsigned char ch;
u32 val; u32 val;
if (uart_tx_stopped(port)) if (uart_tx_stopped(port))
@ -347,19 +347,14 @@ static void rda_uart_send_chars(struct uart_port *port)
port->x_char = 0; port->x_char = 0;
} }
while (rda_uart_read(port, RDA_UART_STATUS) & RDA_UART_TX_FIFO_MASK) { while ((rda_uart_read(port, RDA_UART_STATUS) & RDA_UART_TX_FIFO_MASK) &&
if (uart_circ_empty(xmit)) uart_fifo_get(port, &ch))
break;
ch = xmit->buf[xmit->tail];
rda_uart_write(port, ch, RDA_UART_RXTX_BUFFER); rda_uart_write(port, ch, RDA_UART_RXTX_BUFFER);
uart_xmit_advance(port, 1);
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (!uart_circ_empty(xmit)) { if (!kfifo_is_empty(&tport->xmit_fifo)) {
/* Re-enable Tx FIFO interrupt */ /* Re-enable Tx FIFO interrupt */
val = rda_uart_read(port, RDA_UART_IRQ_MASK); val = rda_uart_read(port, RDA_UART_IRQ_MASK);
val |= RDA_UART_TX_DATA_NEEDED; val |= RDA_UART_TX_DATA_NEEDED;

View File

@ -329,7 +329,7 @@ static void s3c24xx_serial_tx_dma_complete(void *args)
{ {
struct s3c24xx_uart_port *ourport = args; struct s3c24xx_uart_port *ourport = args;
struct uart_port *port = &ourport->port; struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
struct s3c24xx_uart_dma *dma = ourport->dma; struct s3c24xx_uart_dma *dma = ourport->dma;
struct dma_tx_state state; struct dma_tx_state state;
unsigned long flags; unsigned long flags;
@ -348,7 +348,7 @@ static void s3c24xx_serial_tx_dma_complete(void *args)
uart_xmit_advance(port, count); uart_xmit_advance(port, count);
ourport->tx_in_progress = 0; ourport->tx_in_progress = 0;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
s3c24xx_serial_start_next_tx(ourport); s3c24xx_serial_start_next_tx(ourport);
@ -431,17 +431,15 @@ static void s3c24xx_serial_start_tx_pio(struct s3c24xx_uart_port *ourport)
} }
static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
unsigned int count) unsigned int count, unsigned int tail)
{ {
struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit;
struct s3c24xx_uart_dma *dma = ourport->dma; struct s3c24xx_uart_dma *dma = ourport->dma;
if (ourport->tx_mode != S3C24XX_TX_DMA) if (ourport->tx_mode != S3C24XX_TX_DMA)
enable_tx_dma(ourport); enable_tx_dma(ourport);
dma->tx_size = count & ~(dma_get_cache_alignment() - 1); dma->tx_size = count & ~(dma_get_cache_alignment() - 1);
dma->tx_transfer_addr = dma->tx_addr + xmit->tail; dma->tx_transfer_addr = dma->tx_addr + tail;
dma_sync_single_for_device(dma->tx_chan->device->dev, dma_sync_single_for_device(dma->tx_chan->device->dev,
dma->tx_transfer_addr, dma->tx_size, dma->tx_transfer_addr, dma->tx_size,
@ -468,11 +466,11 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport) static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport)
{ {
struct uart_port *port = &ourport->port; struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned long count; unsigned int count, tail;
/* Get data size up to the end of buffer */ /* Get data size up to the end of buffer */
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); count = kfifo_out_linear(&tport->xmit_fifo, &tail, UART_XMIT_SIZE);
if (!count) { if (!count) {
s3c24xx_serial_stop_tx(port); s3c24xx_serial_stop_tx(port);
@ -481,16 +479,16 @@ static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport)
if (!ourport->dma || !ourport->dma->tx_chan || if (!ourport->dma || !ourport->dma->tx_chan ||
count < ourport->min_dma_size || count < ourport->min_dma_size ||
xmit->tail & (dma_get_cache_alignment() - 1)) tail & (dma_get_cache_alignment() - 1))
s3c24xx_serial_start_tx_pio(ourport); s3c24xx_serial_start_tx_pio(ourport);
else else
s3c24xx_serial_start_tx_dma(ourport, count); s3c24xx_serial_start_tx_dma(ourport, count, tail);
} }
static void s3c24xx_serial_start_tx(struct uart_port *port) static void s3c24xx_serial_start_tx(struct uart_port *port)
{ {
struct s3c24xx_uart_port *ourport = to_ourport(port); struct s3c24xx_uart_port *ourport = to_ourport(port);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
if (!ourport->tx_enabled) { if (!ourport->tx_enabled) {
if (port->flags & UPF_CONS_FLOW) if (port->flags & UPF_CONS_FLOW)
@ -502,7 +500,8 @@ static void s3c24xx_serial_start_tx(struct uart_port *port)
} }
if (ourport->dma && ourport->dma->tx_chan) { if (ourport->dma && ourport->dma->tx_chan) {
if (!uart_circ_empty(xmit) && !ourport->tx_in_progress) if (!kfifo_is_empty(&tport->xmit_fifo) &&
!ourport->tx_in_progress)
s3c24xx_serial_start_next_tx(ourport); s3c24xx_serial_start_next_tx(ourport);
} }
} }
@ -868,18 +867,19 @@ static irqreturn_t s3c24xx_serial_rx_irq(int irq, void *dev_id)
static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport) static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
{ {
struct uart_port *port = &ourport->port; struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
int count, dma_count = 0; unsigned int count, dma_count = 0, tail;
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); count = kfifo_out_linear(&tport->xmit_fifo, &tail, UART_XMIT_SIZE);
if (ourport->dma && ourport->dma->tx_chan && if (ourport->dma && ourport->dma->tx_chan &&
count >= ourport->min_dma_size) { count >= ourport->min_dma_size) {
int align = dma_get_cache_alignment() - int align = dma_get_cache_alignment() -
(xmit->tail & (dma_get_cache_alignment() - 1)); (tail & (dma_get_cache_alignment() - 1));
if (count - align >= ourport->min_dma_size) { if (count - align >= ourport->min_dma_size) {
dma_count = count - align; dma_count = count - align;
count = align; count = align;
tail += align;
} }
} }
@ -894,7 +894,7 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
* stopped, disable the uart and exit * stopped, disable the uart and exit
*/ */
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
s3c24xx_serial_stop_tx(port); s3c24xx_serial_stop_tx(port);
return; return;
} }
@ -906,24 +906,25 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
dma_count = 0; dma_count = 0;
} }
while (!uart_circ_empty(xmit) && count > 0) { while (!(rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)) {
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull) unsigned char ch;
if (!uart_fifo_get(port, &ch))
break; break;
wr_reg(port, S3C2410_UTXH, xmit->buf[xmit->tail]); wr_reg(port, S3C2410_UTXH, ch);
uart_xmit_advance(port, 1);
count--; count--;
} }
if (!count && dma_count) { if (!count && dma_count) {
s3c24xx_serial_start_tx_dma(ourport, dma_count); s3c24xx_serial_start_tx_dma(ourport, dma_count, tail);
return; return;
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
s3c24xx_serial_stop_tx(port); s3c24xx_serial_stop_tx(port);
} }
@ -1118,7 +1119,8 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
/* TX buffer */ /* TX buffer */
dma->tx_addr = dma_map_single(dma->tx_chan->device->dev, dma->tx_addr = dma_map_single(dma->tx_chan->device->dev,
p->port.state->xmit.buf, UART_XMIT_SIZE, p->port.state->port.xmit_buf,
UART_XMIT_SIZE,
DMA_TO_DEVICE); DMA_TO_DEVICE);
if (dma_mapping_error(dma->tx_chan->device->dev, dma->tx_addr)) { if (dma_mapping_error(dma->tx_chan->device->dev, dma->tx_addr)) {
reason = "DMA mapping error for TX buffer"; reason = "DMA mapping error for TX buffer";

View File

@ -382,7 +382,8 @@ static void sbd_receive_chars(struct sbd_port *sport)
static void sbd_transmit_chars(struct sbd_port *sport) static void sbd_transmit_chars(struct sbd_port *sport)
{ {
struct uart_port *uport = &sport->port; struct uart_port *uport = &sport->port;
struct circ_buf *xmit = &sport->port.state->xmit; struct tty_port *tport = &sport->port.state->port;
unsigned char ch;
unsigned int mask; unsigned int mask;
int stop_tx; int stop_tx;
@ -395,19 +396,19 @@ static void sbd_transmit_chars(struct sbd_port *sport)
} }
/* If nothing to do or stopped or hardware stopped. */ /* If nothing to do or stopped or hardware stopped. */
stop_tx = (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)); stop_tx = uart_tx_stopped(&sport->port) ||
!uart_fifo_get(&sport->port, &ch);
/* Send char. */ /* Send char. */
if (!stop_tx) { if (!stop_tx) {
write_sbdchn(sport, R_DUART_TX_HOLD, xmit->buf[xmit->tail]); write_sbdchn(sport, R_DUART_TX_HOLD, ch);
uart_xmit_advance(&sport->port, 1);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&sport->port); uart_write_wakeup(&sport->port);
} }
/* Are we are done? */ /* Are we are done? */
if (stop_tx || uart_circ_empty(xmit)) { if (stop_tx || kfifo_is_empty(&tport->xmit_fifo)) {
/* Disable tx interrupts. */ /* Disable tx interrupts. */
mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2)); mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
mask &= ~M_DUART_IMR_TX; mask &= ~M_DUART_IMR_TX;

View File

@ -676,9 +676,9 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
static void sc16is7xx_handle_tx(struct uart_port *port) static void sc16is7xx_handle_tx(struct uart_port *port)
{ {
struct sc16is7xx_port *s = dev_get_drvdata(port->dev); struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned int txlen, to_send, i;
unsigned long flags; unsigned long flags;
unsigned int txlen;
if (unlikely(port->x_char)) { if (unlikely(port->x_char)) {
sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char); sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char);
@ -687,40 +687,30 @@ static void sc16is7xx_handle_tx(struct uart_port *port)
return; return;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
uart_port_lock_irqsave(port, &flags); uart_port_lock_irqsave(port, &flags);
sc16is7xx_stop_tx(port); sc16is7xx_stop_tx(port);
uart_port_unlock_irqrestore(port, flags); uart_port_unlock_irqrestore(port, flags);
return; return;
} }
/* Get length of data pending in circular buffer */ /* Limit to space available in TX FIFO */
to_send = uart_circ_chars_pending(xmit); txlen = sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG);
if (likely(to_send)) { if (txlen > SC16IS7XX_FIFO_SIZE) {
/* Limit to space available in TX FIFO */ dev_err_ratelimited(port->dev,
txlen = sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG); "chip reports %d free bytes in TX fifo, but it only has %d",
if (txlen > SC16IS7XX_FIFO_SIZE) { txlen, SC16IS7XX_FIFO_SIZE);
dev_err_ratelimited(port->dev, txlen = 0;
"chip reports %d free bytes in TX fifo, but it only has %d",
txlen, SC16IS7XX_FIFO_SIZE);
txlen = 0;
}
to_send = (to_send > txlen) ? txlen : to_send;
/* Convert to linear buffer */
for (i = 0; i < to_send; ++i) {
s->buf[i] = xmit->buf[xmit->tail];
uart_xmit_advance(port, 1);
}
sc16is7xx_fifo_write(port, s->buf, to_send);
} }
txlen = uart_fifo_out(port, s->buf, txlen);
sc16is7xx_fifo_write(port, s->buf, txlen);
uart_port_lock_irqsave(port, &flags); uart_port_lock_irqsave(port, &flags);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
sc16is7xx_stop_tx(port); sc16is7xx_stop_tx(port);
else else
sc16is7xx_ier_set(port, SC16IS7XX_IER_THRI_BIT); sc16is7xx_ier_set(port, SC16IS7XX_IER_THRI_BIT);

View File

@ -439,7 +439,7 @@ static void sccnxp_handle_rx(struct uart_port *port)
static void sccnxp_handle_tx(struct uart_port *port) static void sccnxp_handle_tx(struct uart_port *port)
{ {
u8 sr; u8 sr;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
struct sccnxp_port *s = dev_get_drvdata(port->dev); struct sccnxp_port *s = dev_get_drvdata(port->dev);
if (unlikely(port->x_char)) { if (unlikely(port->x_char)) {
@ -449,7 +449,7 @@ static void sccnxp_handle_tx(struct uart_port *port)
return; return;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
/* Disable TX if FIFO is empty */ /* Disable TX if FIFO is empty */
if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXEMT) { if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXEMT) {
sccnxp_disable_irq(port, IMR_TXRDY); sccnxp_disable_irq(port, IMR_TXRDY);
@ -461,16 +461,20 @@ static void sccnxp_handle_tx(struct uart_port *port)
return; return;
} }
while (!uart_circ_empty(xmit)) { while (1) {
unsigned char ch;
sr = sccnxp_port_read(port, SCCNXP_SR_REG); sr = sccnxp_port_read(port, SCCNXP_SR_REG);
if (!(sr & SR_TXRDY)) if (!(sr & SR_TXRDY))
break; break;
sccnxp_port_write(port, SCCNXP_THR_REG, xmit->buf[xmit->tail]); if (!uart_fifo_get(port, &ch))
uart_xmit_advance(port, 1); break;
sccnxp_port_write(port, SCCNXP_THR_REG, ch);
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
} }

View File

@ -484,18 +484,18 @@ static void tegra_uart_release_port(struct uart_port *u)
static void tegra_uart_fill_tx_fifo(struct tegra_uart_port *tup, int max_bytes) static void tegra_uart_fill_tx_fifo(struct tegra_uart_port *tup, int max_bytes)
{ {
struct circ_buf *xmit = &tup->uport.state->xmit; unsigned char ch;
int i; int i;
for (i = 0; i < max_bytes; i++) { for (i = 0; i < max_bytes; i++) {
BUG_ON(uart_circ_empty(xmit));
if (tup->cdata->tx_fifo_full_status) { if (tup->cdata->tx_fifo_full_status) {
unsigned long lsr = tegra_uart_read(tup, UART_LSR); unsigned long lsr = tegra_uart_read(tup, UART_LSR);
if ((lsr & TEGRA_UART_LSR_TXFIFO_FULL)) if ((lsr & TEGRA_UART_LSR_TXFIFO_FULL))
break; break;
} }
tegra_uart_write(tup, xmit->buf[xmit->tail], UART_TX); if (WARN_ON_ONCE(!uart_fifo_get(&tup->uport, &ch)))
uart_xmit_advance(&tup->uport, 1); break;
tegra_uart_write(tup, ch, UART_TX);
} }
} }
@ -514,7 +514,7 @@ static void tegra_uart_start_pio_tx(struct tegra_uart_port *tup,
static void tegra_uart_tx_dma_complete(void *args) static void tegra_uart_tx_dma_complete(void *args)
{ {
struct tegra_uart_port *tup = args; struct tegra_uart_port *tup = args;
struct circ_buf *xmit = &tup->uport.state->xmit; struct tty_port *tport = &tup->uport.state->port;
struct dma_tx_state state; struct dma_tx_state state;
unsigned long flags; unsigned long flags;
unsigned int count; unsigned int count;
@ -525,7 +525,7 @@ static void tegra_uart_tx_dma_complete(void *args)
uart_port_lock_irqsave(&tup->uport, &flags); uart_port_lock_irqsave(&tup->uport, &flags);
uart_xmit_advance(&tup->uport, count); uart_xmit_advance(&tup->uport, count);
tup->tx_in_progress = 0; tup->tx_in_progress = 0;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&tup->uport); uart_write_wakeup(&tup->uport);
tegra_uart_start_next_tx(tup); tegra_uart_start_next_tx(tup);
uart_port_unlock_irqrestore(&tup->uport, flags); uart_port_unlock_irqrestore(&tup->uport, flags);
@ -534,11 +534,14 @@ static void tegra_uart_tx_dma_complete(void *args)
static int tegra_uart_start_tx_dma(struct tegra_uart_port *tup, static int tegra_uart_start_tx_dma(struct tegra_uart_port *tup,
unsigned long count) unsigned long count)
{ {
struct circ_buf *xmit = &tup->uport.state->xmit; struct tty_port *tport = &tup->uport.state->port;
dma_addr_t tx_phys_addr; dma_addr_t tx_phys_addr;
unsigned int tail;
tup->tx_bytes = count & ~(0xF); tup->tx_bytes = count & ~(0xF);
tx_phys_addr = tup->tx_dma_buf_phys + xmit->tail; WARN_ON_ONCE(kfifo_out_linear(&tport->xmit_fifo, &tail,
UART_XMIT_SIZE) < count);
tx_phys_addr = tup->tx_dma_buf_phys + tail;
dma_sync_single_for_device(tup->uport.dev, tx_phys_addr, dma_sync_single_for_device(tup->uport.dev, tx_phys_addr,
tup->tx_bytes, DMA_TO_DEVICE); tup->tx_bytes, DMA_TO_DEVICE);
@ -562,18 +565,21 @@ static int tegra_uart_start_tx_dma(struct tegra_uart_port *tup,
static void tegra_uart_start_next_tx(struct tegra_uart_port *tup) static void tegra_uart_start_next_tx(struct tegra_uart_port *tup)
{ {
struct tty_port *tport = &tup->uport.state->port;
unsigned char *tail_ptr;
unsigned long tail; unsigned long tail;
unsigned long count; unsigned int count;
struct circ_buf *xmit = &tup->uport.state->xmit;
if (!tup->current_baud) if (!tup->current_baud)
return; return;
tail = (unsigned long)&xmit->buf[xmit->tail]; count = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail_ptr,
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); UART_XMIT_SIZE);
if (!count) if (!count)
return; return;
tail = (unsigned long)tail_ptr;
if (tup->use_tx_pio || count < TEGRA_UART_MIN_DMA) if (tup->use_tx_pio || count < TEGRA_UART_MIN_DMA)
tegra_uart_start_pio_tx(tup, count); tegra_uart_start_pio_tx(tup, count);
else if (BYTES_TO_ALIGN(tail) > 0) else if (BYTES_TO_ALIGN(tail) > 0)
@ -586,9 +592,9 @@ static void tegra_uart_start_next_tx(struct tegra_uart_port *tup)
static void tegra_uart_start_tx(struct uart_port *u) static void tegra_uart_start_tx(struct uart_port *u)
{ {
struct tegra_uart_port *tup = to_tegra_uport(u); struct tegra_uart_port *tup = to_tegra_uport(u);
struct circ_buf *xmit = &u->state->xmit; struct tty_port *tport = &u->state->port;
if (!uart_circ_empty(xmit) && !tup->tx_in_progress) if (!kfifo_is_empty(&tport->xmit_fifo) && !tup->tx_in_progress)
tegra_uart_start_next_tx(tup); tegra_uart_start_next_tx(tup);
} }
@ -628,11 +634,11 @@ static void tegra_uart_stop_tx(struct uart_port *u)
static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup) static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup)
{ {
struct circ_buf *xmit = &tup->uport.state->xmit; struct tty_port *tport = &tup->uport.state->port;
tegra_uart_fill_tx_fifo(tup, tup->tx_bytes); tegra_uart_fill_tx_fifo(tup, tup->tx_bytes);
tup->tx_in_progress = 0; tup->tx_in_progress = 0;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&tup->uport); uart_write_wakeup(&tup->uport);
tegra_uart_start_next_tx(tup); tegra_uart_start_next_tx(tup);
} }
@ -1169,15 +1175,14 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup,
tup->rx_dma_buf_virt = dma_buf; tup->rx_dma_buf_virt = dma_buf;
tup->rx_dma_buf_phys = dma_phys; tup->rx_dma_buf_phys = dma_phys;
} else { } else {
dma_buf = tup->uport.state->port.xmit_buf;
dma_phys = dma_map_single(tup->uport.dev, dma_phys = dma_map_single(tup->uport.dev,
tup->uport.state->xmit.buf, UART_XMIT_SIZE, dma_buf, UART_XMIT_SIZE, DMA_TO_DEVICE);
DMA_TO_DEVICE);
if (dma_mapping_error(tup->uport.dev, dma_phys)) { if (dma_mapping_error(tup->uport.dev, dma_phys)) {
dev_err(tup->uport.dev, "dma_map_single tx failed\n"); dev_err(tup->uport.dev, "dma_map_single tx failed\n");
dma_release_channel(dma_chan); dma_release_channel(dma_chan);
return -ENOMEM; return -ENOMEM;
} }
dma_buf = tup->uport.state->xmit.buf;
dma_sconfig.dst_addr = tup->uport.mapbase; dma_sconfig.dst_addr = tup->uport.mapbase;
dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_sconfig.dst_maxburst = 16; dma_sconfig.dst_maxburst = 16;

View File

@ -272,9 +272,10 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
return -ENOMEM; return -ENOMEM;
uart_port_lock(state, flags); uart_port_lock(state, flags);
if (!state->xmit.buf) { if (!state->port.xmit_buf) {
state->xmit.buf = (unsigned char *) page; state->port.xmit_buf = (unsigned char *)page;
uart_circ_clear(&state->xmit); kfifo_init(&state->port.xmit_fifo, state->port.xmit_buf,
PAGE_SIZE);
uart_port_unlock(uport, flags); uart_port_unlock(uport, flags);
} else { } else {
uart_port_unlock(uport, flags); uart_port_unlock(uport, flags);
@ -387,8 +388,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
* can endup in printk() recursion. * can endup in printk() recursion.
*/ */
uart_port_lock(state, flags); uart_port_lock(state, flags);
xmit_buf = state->xmit.buf; xmit_buf = port->xmit_buf;
state->xmit.buf = NULL; port->xmit_buf = NULL;
INIT_KFIFO(port->xmit_fifo);
uart_port_unlock(uport, flags); uart_port_unlock(uport, flags);
free_page((unsigned long)xmit_buf); free_page((unsigned long)xmit_buf);
@ -552,22 +554,17 @@ static int uart_put_char(struct tty_struct *tty, u8 c)
{ {
struct uart_state *state = tty->driver_data; struct uart_state *state = tty->driver_data;
struct uart_port *port; struct uart_port *port;
struct circ_buf *circ;
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
circ = &state->xmit;
port = uart_port_lock(state, flags); port = uart_port_lock(state, flags);
if (!circ->buf) { if (WARN_ON_ONCE(!state->port.xmit_buf)) {
uart_port_unlock(port, flags); uart_port_unlock(port, flags);
return 0; return 0;
} }
if (port && uart_circ_chars_free(circ) != 0) { if (port)
circ->buf[circ->head] = c; ret = kfifo_put(&state->port.xmit_fifo, c);
circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
ret = 1;
}
uart_port_unlock(port, flags); uart_port_unlock(port, flags);
return ret; return ret;
} }
@ -581,9 +578,8 @@ static ssize_t uart_write(struct tty_struct *tty, const u8 *buf, size_t count)
{ {
struct uart_state *state = tty->driver_data; struct uart_state *state = tty->driver_data;
struct uart_port *port; struct uart_port *port;
struct circ_buf *circ;
unsigned long flags; unsigned long flags;
int c, ret = 0; int ret = 0;
/* /*
* This means you called this function _after_ the port was * This means you called this function _after_ the port was
@ -593,24 +589,13 @@ static ssize_t uart_write(struct tty_struct *tty, const u8 *buf, size_t count)
return -EL3HLT; return -EL3HLT;
port = uart_port_lock(state, flags); port = uart_port_lock(state, flags);
circ = &state->xmit; if (WARN_ON_ONCE(!state->port.xmit_buf)) {
if (!circ->buf) {
uart_port_unlock(port, flags); uart_port_unlock(port, flags);
return 0; return 0;
} }
while (port) { if (port)
c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); ret = kfifo_in(&state->port.xmit_fifo, buf, count);
if (count < c)
c = count;
if (c <= 0)
break;
memcpy(circ->buf + circ->head, buf, c);
circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
buf += c;
count -= c;
ret += c;
}
__uart_start(state); __uart_start(state);
uart_port_unlock(port, flags); uart_port_unlock(port, flags);
@ -625,7 +610,7 @@ static unsigned int uart_write_room(struct tty_struct *tty)
unsigned int ret; unsigned int ret;
port = uart_port_lock(state, flags); port = uart_port_lock(state, flags);
ret = uart_circ_chars_free(&state->xmit); ret = kfifo_avail(&state->port.xmit_fifo);
uart_port_unlock(port, flags); uart_port_unlock(port, flags);
return ret; return ret;
} }
@ -638,7 +623,7 @@ static unsigned int uart_chars_in_buffer(struct tty_struct *tty)
unsigned int ret; unsigned int ret;
port = uart_port_lock(state, flags); port = uart_port_lock(state, flags);
ret = uart_circ_chars_pending(&state->xmit); ret = kfifo_len(&state->port.xmit_fifo);
uart_port_unlock(port, flags); uart_port_unlock(port, flags);
return ret; return ret;
} }
@ -661,7 +646,7 @@ static void uart_flush_buffer(struct tty_struct *tty)
port = uart_port_lock(state, flags); port = uart_port_lock(state, flags);
if (!port) if (!port)
return; return;
uart_circ_clear(&state->xmit); kfifo_reset(&state->port.xmit_fifo);
if (port->ops->flush_buffer) if (port->ops->flush_buffer)
port->ops->flush_buffer(port); port->ops->flush_buffer(port);
uart_port_unlock(port, flags); uart_port_unlock(port, flags);
@ -1064,7 +1049,7 @@ static int uart_get_lsr_info(struct tty_struct *tty,
* interrupt happens). * interrupt happens).
*/ */
if (uport->x_char || if (uport->x_char ||
((uart_circ_chars_pending(&state->xmit) > 0) && (!kfifo_is_empty(&state->port.xmit_fifo) &&
!uart_tx_stopped(uport))) !uart_tx_stopped(uport)))
result &= ~TIOCSER_TEMT; result &= ~TIOCSER_TEMT;
@ -1788,8 +1773,9 @@ static void uart_tty_port_shutdown(struct tty_port *port)
* Free the transmit buffer. * Free the transmit buffer.
*/ */
uart_port_lock_irq(uport); uart_port_lock_irq(uport);
buf = state->xmit.buf; buf = port->xmit_buf;
state->xmit.buf = NULL; port->xmit_buf = NULL;
INIT_KFIFO(port->xmit_fifo);
uart_port_unlock_irq(uport); uart_port_unlock_irq(uport);
free_page((unsigned long)buf); free_page((unsigned long)buf);

View File

@ -23,7 +23,7 @@
static int __serial_port_busy(struct uart_port *port) static int __serial_port_busy(struct uart_port *port)
{ {
return !uart_tx_stopped(port) && return !uart_tx_stopped(port) &&
uart_circ_chars_pending(&port->state->xmit); !kfifo_is_empty(&port->state->port.xmit_fifo);
} }
static int serial_port_runtime_resume(struct device *dev) static int serial_port_runtime_resume(struct device *dev)

View File

@ -585,7 +585,7 @@ static void sci_start_tx(struct uart_port *port)
sci_serial_out(port, SCSCR, new); sci_serial_out(port, SCSCR, new);
} }
if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && if (s->chan_tx && !kfifo_is_empty(&port->state->port.xmit_fifo) &&
dma_submit_error(s->cookie_tx)) { dma_submit_error(s->cookie_tx)) {
if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE)
/* Switch irq from SCIF to DMA */ /* Switch irq from SCIF to DMA */
@ -817,7 +817,7 @@ static int sci_rxfill(struct uart_port *port)
static void sci_transmit_chars(struct uart_port *port) static void sci_transmit_chars(struct uart_port *port)
{ {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned int stopped = uart_tx_stopped(port); unsigned int stopped = uart_tx_stopped(port);
unsigned short status; unsigned short status;
unsigned short ctrl; unsigned short ctrl;
@ -826,7 +826,7 @@ static void sci_transmit_chars(struct uart_port *port)
status = sci_serial_in(port, SCxSR); status = sci_serial_in(port, SCxSR);
if (!(status & SCxSR_TDxE(port))) { if (!(status & SCxSR_TDxE(port))) {
ctrl = sci_serial_in(port, SCSCR); ctrl = sci_serial_in(port, SCSCR);
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
ctrl &= ~SCSCR_TIE; ctrl &= ~SCSCR_TIE;
else else
ctrl |= SCSCR_TIE; ctrl |= SCSCR_TIE;
@ -842,15 +842,14 @@ static void sci_transmit_chars(struct uart_port *port)
if (port->x_char) { if (port->x_char) {
c = port->x_char; c = port->x_char;
port->x_char = 0; port->x_char = 0;
} else if (!uart_circ_empty(xmit) && !stopped) { } else if (stopped || !kfifo_get(&tport->xmit_fifo, &c)) {
c = xmit->buf[xmit->tail]; if (port->type == PORT_SCI &&
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); kfifo_is_empty(&tport->xmit_fifo)) {
} else if (port->type == PORT_SCI && uart_circ_empty(xmit)) { ctrl = sci_serial_in(port, SCSCR);
ctrl = sci_serial_in(port, SCSCR); ctrl &= ~SCSCR_TE;
ctrl &= ~SCSCR_TE; sci_serial_out(port, SCSCR, ctrl);
sci_serial_out(port, SCSCR, ctrl); return;
return; }
} else {
break; break;
} }
@ -861,9 +860,9 @@ static void sci_transmit_chars(struct uart_port *port)
sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port)); sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port));
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) { if (kfifo_is_empty(&tport->xmit_fifo)) {
if (port->type == PORT_SCI) { if (port->type == PORT_SCI) {
ctrl = sci_serial_in(port, SCSCR); ctrl = sci_serial_in(port, SCSCR);
ctrl &= ~SCSCR_TIE; ctrl &= ~SCSCR_TIE;
@ -1199,7 +1198,7 @@ static void sci_dma_tx_complete(void *arg)
{ {
struct sci_port *s = arg; struct sci_port *s = arg;
struct uart_port *port = &s->port; struct uart_port *port = &s->port;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned long flags; unsigned long flags;
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
@ -1208,10 +1207,10 @@ static void sci_dma_tx_complete(void *arg)
uart_xmit_advance(port, s->tx_dma_len); uart_xmit_advance(port, s->tx_dma_len);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (!uart_circ_empty(xmit)) { if (!kfifo_is_empty(&tport->xmit_fifo)) {
s->cookie_tx = 0; s->cookie_tx = 0;
schedule_work(&s->work_tx); schedule_work(&s->work_tx);
} else { } else {
@ -1424,10 +1423,10 @@ static void sci_dma_tx_work_fn(struct work_struct *work)
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
struct dma_chan *chan = s->chan_tx; struct dma_chan *chan = s->chan_tx;
struct uart_port *port = &s->port; struct uart_port *port = &s->port;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned long flags; unsigned long flags;
unsigned int tail;
dma_addr_t buf; dma_addr_t buf;
int head, tail;
/* /*
* DMA is idle now. * DMA is idle now.
@ -1437,10 +1436,9 @@ static void sci_dma_tx_work_fn(struct work_struct *work)
* consistent xmit buffer state. * consistent xmit buffer state.
*/ */
uart_port_lock_irq(port); uart_port_lock_irq(port);
head = xmit->head; s->tx_dma_len = kfifo_out_linear(&tport->xmit_fifo, &tail,
tail = xmit->tail; UART_XMIT_SIZE);
buf = s->tx_dma_addr + tail; buf = s->tx_dma_addr + tail;
s->tx_dma_len = CIRC_CNT_TO_END(head, tail, UART_XMIT_SIZE);
if (!s->tx_dma_len) { if (!s->tx_dma_len) {
/* Transmit buffer has been flushed */ /* Transmit buffer has been flushed */
uart_port_unlock_irq(port); uart_port_unlock_irq(port);
@ -1469,8 +1467,8 @@ static void sci_dma_tx_work_fn(struct work_struct *work)
} }
uart_port_unlock_irq(port); uart_port_unlock_irq(port);
dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n", dev_dbg(port->dev, "%s: %p: %u, cookie %d\n",
__func__, xmit->buf, tail, head, s->cookie_tx); __func__, tport->xmit_buf, tail, s->cookie_tx);
dma_async_issue_pending(chan); dma_async_issue_pending(chan);
return; return;
@ -1585,6 +1583,7 @@ static struct dma_chan *sci_request_dma_chan(struct uart_port *port,
static void sci_request_dma(struct uart_port *port) static void sci_request_dma(struct uart_port *port)
{ {
struct sci_port *s = to_sci_port(port); struct sci_port *s = to_sci_port(port);
struct tty_port *tport = &port->state->port;
struct dma_chan *chan; struct dma_chan *chan;
dev_dbg(port->dev, "%s: port %d\n", __func__, port->line); dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
@ -1613,7 +1612,7 @@ static void sci_request_dma(struct uart_port *port)
if (chan) { if (chan) {
/* UART circular tx buffer is an aligned page. */ /* UART circular tx buffer is an aligned page. */
s->tx_dma_addr = dma_map_single(chan->device->dev, s->tx_dma_addr = dma_map_single(chan->device->dev,
port->state->xmit.buf, tport->xmit_buf,
UART_XMIT_SIZE, UART_XMIT_SIZE,
DMA_TO_DEVICE); DMA_TO_DEVICE);
if (dma_mapping_error(chan->device->dev, s->tx_dma_addr)) { if (dma_mapping_error(chan->device->dev, s->tx_dma_addr)) {
@ -1622,7 +1621,7 @@ static void sci_request_dma(struct uart_port *port)
} else { } else {
dev_dbg(port->dev, "%s: mapped %lu@%p to %pad\n", dev_dbg(port->dev, "%s: mapped %lu@%p to %pad\n",
__func__, UART_XMIT_SIZE, __func__, UART_XMIT_SIZE,
port->state->xmit.buf, &s->tx_dma_addr); tport->xmit_buf, &s->tx_dma_addr);
INIT_WORK(&s->work_tx, sci_dma_tx_work_fn); INIT_WORK(&s->work_tx, sci_dma_tx_work_fn);
s->chan_tx_saved = s->chan_tx = chan; s->chan_tx_saved = s->chan_tx = chan;

View File

@ -227,13 +227,13 @@ static int sprd_tx_buf_remap(struct uart_port *port)
{ {
struct sprd_uart_port *sp = struct sprd_uart_port *sp =
container_of(port, struct sprd_uart_port, port); container_of(port, struct sprd_uart_port, port);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned char *tail;
sp->tx_dma.trans_len = sp->tx_dma.trans_len = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail,
CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); UART_XMIT_SIZE);
sp->tx_dma.phys_addr = dma_map_single(port->dev, sp->tx_dma.phys_addr = dma_map_single(port->dev, tail,
(void *)&(xmit->buf[xmit->tail]),
sp->tx_dma.trans_len, sp->tx_dma.trans_len,
DMA_TO_DEVICE); DMA_TO_DEVICE);
return dma_mapping_error(port->dev, sp->tx_dma.phys_addr); return dma_mapping_error(port->dev, sp->tx_dma.phys_addr);
@ -244,7 +244,7 @@ static void sprd_complete_tx_dma(void *data)
struct uart_port *port = (struct uart_port *)data; struct uart_port *port = (struct uart_port *)data;
struct sprd_uart_port *sp = struct sprd_uart_port *sp =
container_of(port, struct sprd_uart_port, port); container_of(port, struct sprd_uart_port, port);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned long flags; unsigned long flags;
uart_port_lock_irqsave(port, &flags); uart_port_lock_irqsave(port, &flags);
@ -253,10 +253,10 @@ static void sprd_complete_tx_dma(void *data)
uart_xmit_advance(port, sp->tx_dma.trans_len); uart_xmit_advance(port, sp->tx_dma.trans_len);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit) || sprd_tx_buf_remap(port) || if (kfifo_is_empty(&tport->xmit_fifo) || sprd_tx_buf_remap(port) ||
sprd_tx_dma_config(port)) sprd_tx_dma_config(port))
sp->tx_dma.trans_len = 0; sp->tx_dma.trans_len = 0;
@ -319,7 +319,7 @@ static void sprd_start_tx_dma(struct uart_port *port)
{ {
struct sprd_uart_port *sp = struct sprd_uart_port *sp =
container_of(port, struct sprd_uart_port, port); container_of(port, struct sprd_uart_port, port);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
if (port->x_char) { if (port->x_char) {
serial_out(port, SPRD_TXD, port->x_char); serial_out(port, SPRD_TXD, port->x_char);
@ -328,7 +328,7 @@ static void sprd_start_tx_dma(struct uart_port *port)
return; return;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
sprd_stop_tx_dma(port); sprd_stop_tx_dma(port);
return; return;
} }

View File

@ -387,9 +387,9 @@ static unsigned int asc_get_mctrl(struct uart_port *port)
/* There are probably characters waiting to be transmitted. */ /* There are probably characters waiting to be transmitted. */
static void asc_start_tx(struct uart_port *port) static void asc_start_tx(struct uart_port *port)
{ {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
if (!uart_circ_empty(xmit)) if (!kfifo_is_empty(&tport->xmit_fifo))
asc_enable_tx_interrupts(port); asc_enable_tx_interrupts(port);
} }

View File

@ -696,18 +696,23 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port)
{ {
struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
while (1) {
unsigned char ch;
while (!uart_circ_empty(xmit)) {
/* Check that TDR is empty before filling FIFO */ /* Check that TDR is empty before filling FIFO */
if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE))
break; break;
writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr);
uart_xmit_advance(port, 1); if (!uart_fifo_get(port, &ch))
break;
writel_relaxed(ch, port->membase + ofs->tdr);
} }
/* rely on TXE irq (mask or unmask) for sending remaining data */ /* rely on TXE irq (mask or unmask) for sending remaining data */
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
stm32_usart_tx_interrupt_disable(port); stm32_usart_tx_interrupt_disable(port);
else else
stm32_usart_tx_interrupt_enable(port); stm32_usart_tx_interrupt_enable(port);
@ -716,7 +721,7 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port)
static void stm32_usart_transmit_chars_dma(struct uart_port *port) static void stm32_usart_transmit_chars_dma(struct uart_port *port)
{ {
struct stm32_port *stm32port = to_stm32_port(port); struct stm32_port *stm32port = to_stm32_port(port);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
struct dma_async_tx_descriptor *desc = NULL; struct dma_async_tx_descriptor *desc = NULL;
unsigned int count; unsigned int count;
int ret; int ret;
@ -728,25 +733,8 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port)
return; return;
} }
count = uart_circ_chars_pending(xmit); count = kfifo_out_peek(&tport->xmit_fifo, &stm32port->tx_buf[0],
TX_BUF_L);
if (count > TX_BUF_L)
count = TX_BUF_L;
if (xmit->tail < xmit->head) {
memcpy(&stm32port->tx_buf[0], &xmit->buf[xmit->tail], count);
} else {
size_t one = UART_XMIT_SIZE - xmit->tail;
size_t two;
if (one > count)
one = count;
two = count - one;
memcpy(&stm32port->tx_buf[0], &xmit->buf[xmit->tail], one);
if (two)
memcpy(&stm32port->tx_buf[one], &xmit->buf[0], two);
}
desc = dmaengine_prep_slave_single(stm32port->tx_ch, desc = dmaengine_prep_slave_single(stm32port->tx_ch,
stm32port->tx_dma_buf, stm32port->tx_dma_buf,
@ -792,14 +780,14 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
{ {
struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
u32 isr; u32 isr;
int ret; int ret;
if (!stm32_port->hw_flow_control && if (!stm32_port->hw_flow_control &&
port->rs485.flags & SER_RS485_ENABLED && port->rs485.flags & SER_RS485_ENABLED &&
(port->x_char || (port->x_char ||
!(uart_circ_empty(xmit) || uart_tx_stopped(port)))) { !(kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)))) {
stm32_usart_tc_interrupt_disable(port); stm32_usart_tc_interrupt_disable(port);
stm32_usart_rs485_rts_enable(port); stm32_usart_rs485_rts_enable(port);
} }
@ -826,7 +814,7 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
return; return;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
stm32_usart_tx_interrupt_disable(port); stm32_usart_tx_interrupt_disable(port);
return; return;
} }
@ -841,10 +829,10 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
else else
stm32_usart_transmit_chars_pio(port); stm32_usart_transmit_chars_pio(port);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) { if (kfifo_is_empty(&tport->xmit_fifo)) {
stm32_usart_tx_interrupt_disable(port); stm32_usart_tx_interrupt_disable(port);
if (!stm32_port->hw_flow_control && if (!stm32_port->hw_flow_control &&
port->rs485.flags & SER_RS485_ENABLED) { port->rs485.flags & SER_RS485_ENABLED) {
@ -967,9 +955,9 @@ static void stm32_usart_stop_tx(struct uart_port *port)
/* There are probably characters waiting to be transmitted. */ /* There are probably characters waiting to be transmitted. */
static void stm32_usart_start_tx(struct uart_port *port) static void stm32_usart_start_tx(struct uart_port *port)
{ {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
if (uart_circ_empty(xmit) && !port->x_char) { if (kfifo_is_empty(&tport->xmit_fifo) && !port->x_char) {
stm32_usart_rs485_rts_disable(port); stm32_usart_rs485_rts_disable(port);
return; return;
} }

View File

@ -39,10 +39,13 @@ static char *con_read_page;
static int hung_up = 0; static int hung_up = 0;
static void transmit_chars_putchar(struct uart_port *port, struct circ_buf *xmit) static void transmit_chars_putchar(struct uart_port *port,
struct tty_port *tport)
{ {
while (!uart_circ_empty(xmit)) { unsigned char ch;
long status = sun4v_con_putchar(xmit->buf[xmit->tail]);
while (kfifo_peek(&tport->xmit_fifo, &ch)) {
long status = sun4v_con_putchar(ch);
if (status != HV_EOK) if (status != HV_EOK)
break; break;
@ -51,14 +54,16 @@ static void transmit_chars_putchar(struct uart_port *port, struct circ_buf *xmit
} }
} }
static void transmit_chars_write(struct uart_port *port, struct circ_buf *xmit) static void transmit_chars_write(struct uart_port *port, struct tty_port *tport)
{ {
while (!uart_circ_empty(xmit)) { while (!kfifo_is_empty(&tport->xmit_fifo)) {
unsigned long ra = __pa(xmit->buf + xmit->tail); unsigned long len, ra, status, sent;
unsigned long len, status, sent; unsigned char *tail;
len = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail,
UART_XMIT_SIZE);
ra = __pa(tail);
len = CIRC_CNT_TO_END(xmit->head, xmit->tail,
UART_XMIT_SIZE);
status = sun4v_con_write(ra, len, &sent); status = sun4v_con_write(ra, len, &sent);
if (status != HV_EOK) if (status != HV_EOK)
break; break;
@ -165,7 +170,7 @@ static int receive_chars_read(struct uart_port *port)
} }
struct sunhv_ops { struct sunhv_ops {
void (*transmit_chars)(struct uart_port *port, struct circ_buf *xmit); void (*transmit_chars)(struct uart_port *port, struct tty_port *tport);
int (*receive_chars)(struct uart_port *port); int (*receive_chars)(struct uart_port *port);
}; };
@ -196,18 +201,18 @@ static struct tty_port *receive_chars(struct uart_port *port)
static void transmit_chars(struct uart_port *port) static void transmit_chars(struct uart_port *port)
{ {
struct circ_buf *xmit; struct tty_port *tport;
if (!port->state) if (!port->state)
return; return;
xmit = &port->state->xmit; tport = &port->state->port;
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port))
return; return;
sunhv_ops->transmit_chars(port, xmit); sunhv_ops->transmit_chars(port, tport);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
} }

View File

@ -200,7 +200,7 @@ static void sunplus_break_ctl(struct uart_port *port, int ctl)
static void transmit_chars(struct uart_port *port) static void transmit_chars(struct uart_port *port)
{ {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
if (port->x_char) { if (port->x_char) {
sp_uart_put_char(port, port->x_char); sp_uart_put_char(port, port->x_char);
@ -209,22 +209,24 @@ static void transmit_chars(struct uart_port *port)
return; return;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
sunplus_stop_tx(port); sunplus_stop_tx(port);
return; return;
} }
do { do {
sp_uart_put_char(port, xmit->buf[xmit->tail]); unsigned char ch;
uart_xmit_advance(port, 1);
if (uart_circ_empty(xmit)) if (!uart_fifo_get(port, &ch))
break; break;
sp_uart_put_char(port, ch);
} while (sunplus_tx_buf_not_full(port)); } while (sunplus_tx_buf_not_full(port));
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
sunplus_stop_tx(port); sunplus_stop_tx(port);
} }

View File

@ -232,7 +232,7 @@ static void sunsab_tx_idle(struct uart_sunsab_port *);
static void transmit_chars(struct uart_sunsab_port *up, static void transmit_chars(struct uart_sunsab_port *up,
union sab82532_irq_status *stat) union sab82532_irq_status *stat)
{ {
struct circ_buf *xmit = &up->port.state->xmit; struct tty_port *tport = &up->port.state->port;
int i; int i;
if (stat->sreg.isr1 & SAB82532_ISR1_ALLS) { if (stat->sreg.isr1 & SAB82532_ISR1_ALLS) {
@ -252,7 +252,7 @@ static void transmit_chars(struct uart_sunsab_port *up,
set_bit(SAB82532_XPR, &up->irqflags); set_bit(SAB82532_XPR, &up->irqflags);
sunsab_tx_idle(up); sunsab_tx_idle(up);
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(&up->port)) {
up->interrupt_mask1 |= SAB82532_IMR1_XPR; up->interrupt_mask1 |= SAB82532_IMR1_XPR;
writeb(up->interrupt_mask1, &up->regs->w.imr1); writeb(up->interrupt_mask1, &up->regs->w.imr1);
return; return;
@ -265,21 +265,22 @@ static void transmit_chars(struct uart_sunsab_port *up,
/* Stuff 32 bytes into Transmit FIFO. */ /* Stuff 32 bytes into Transmit FIFO. */
clear_bit(SAB82532_XPR, &up->irqflags); clear_bit(SAB82532_XPR, &up->irqflags);
for (i = 0; i < up->port.fifosize; i++) { for (i = 0; i < up->port.fifosize; i++) {
writeb(xmit->buf[xmit->tail], unsigned char ch;
&up->regs->w.xfifo[i]);
uart_xmit_advance(&up->port, 1); if (!uart_fifo_get(&up->port, &ch))
if (uart_circ_empty(xmit))
break; break;
writeb(ch, &up->regs->w.xfifo[i]);
} }
/* Issue a Transmit Frame command. */ /* Issue a Transmit Frame command. */
sunsab_cec_wait(up); sunsab_cec_wait(up);
writeb(SAB82532_CMDR_XF, &up->regs->w.cmdr); writeb(SAB82532_CMDR_XF, &up->regs->w.cmdr);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&up->port); uart_write_wakeup(&up->port);
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
sunsab_stop_tx(&up->port); sunsab_stop_tx(&up->port);
} }
@ -435,10 +436,10 @@ static void sunsab_start_tx(struct uart_port *port)
{ {
struct uart_sunsab_port *up = struct uart_sunsab_port *up =
container_of(port, struct uart_sunsab_port, port); container_of(port, struct uart_sunsab_port, port);
struct circ_buf *xmit = &up->port.state->xmit; struct tty_port *tport = &up->port.state->port;
int i; int i;
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port))
return; return;
up->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS|SAB82532_IMR1_XPR); up->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS|SAB82532_IMR1_XPR);
@ -451,11 +452,12 @@ static void sunsab_start_tx(struct uart_port *port)
clear_bit(SAB82532_XPR, &up->irqflags); clear_bit(SAB82532_XPR, &up->irqflags);
for (i = 0; i < up->port.fifosize; i++) { for (i = 0; i < up->port.fifosize; i++) {
writeb(xmit->buf[xmit->tail], unsigned char ch;
&up->regs->w.xfifo[i]);
uart_xmit_advance(&up->port, 1); if (!uart_fifo_get(&up->port, &ch))
if (uart_circ_empty(xmit))
break; break;
writeb(ch, &up->regs->w.xfifo[i]);
} }
/* Issue a Transmit Frame command. */ /* Issue a Transmit Frame command. */

View File

@ -396,7 +396,8 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status)
static void transmit_chars(struct uart_sunsu_port *up) static void transmit_chars(struct uart_sunsu_port *up)
{ {
struct circ_buf *xmit = &up->port.state->xmit; struct tty_port *tport = &up->port.state->port;
unsigned char ch;
int count; int count;
if (up->port.x_char) { if (up->port.x_char) {
@ -409,23 +410,23 @@ static void transmit_chars(struct uart_sunsu_port *up)
sunsu_stop_tx(&up->port); sunsu_stop_tx(&up->port);
return; return;
} }
if (uart_circ_empty(xmit)) { if (kfifo_is_empty(&tport->xmit_fifo)) {
__stop_tx(up); __stop_tx(up);
return; return;
} }
count = up->port.fifosize; count = up->port.fifosize;
do { do {
serial_out(up, UART_TX, xmit->buf[xmit->tail]); if (!uart_fifo_get(&up->port, &ch))
uart_xmit_advance(&up->port, 1);
if (uart_circ_empty(xmit))
break; break;
serial_out(up, UART_TX, ch);
} while (--count > 0); } while (--count > 0);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&up->port); uart_write_wakeup(&up->port);
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
__stop_tx(up); __stop_tx(up);
} }

View File

@ -453,7 +453,8 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
static void sunzilog_transmit_chars(struct uart_sunzilog_port *up, static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
struct zilog_channel __iomem *channel) struct zilog_channel __iomem *channel)
{ {
struct circ_buf *xmit; struct tty_port *tport;
unsigned char ch;
if (ZS_IS_CONS(up)) { if (ZS_IS_CONS(up)) {
unsigned char status = readb(&channel->control); unsigned char status = readb(&channel->control);
@ -496,21 +497,20 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
if (up->port.state == NULL) if (up->port.state == NULL)
goto ack_tx_int; goto ack_tx_int;
xmit = &up->port.state->xmit; tport = &up->port.state->port;
if (uart_circ_empty(xmit))
goto ack_tx_int;
if (uart_tx_stopped(&up->port)) if (uart_tx_stopped(&up->port))
goto ack_tx_int; goto ack_tx_int;
if (!uart_fifo_get(&up->port, &ch))
goto ack_tx_int;
up->flags |= SUNZILOG_FLAG_TX_ACTIVE; up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
writeb(xmit->buf[xmit->tail], &channel->data); writeb(ch, &channel->data);
ZSDELAY(); ZSDELAY();
ZS_WSYNC(channel); ZS_WSYNC(channel);
uart_xmit_advance(&up->port, 1); if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&up->port); uart_write_wakeup(&up->port);
return; return;
@ -700,17 +700,16 @@ static void sunzilog_start_tx(struct uart_port *port)
port->icount.tx++; port->icount.tx++;
port->x_char = 0; port->x_char = 0;
} else { } else {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned char ch;
if (uart_circ_empty(xmit)) if (!uart_fifo_get(&up->port, &ch))
return; return;
writeb(xmit->buf[xmit->tail], &channel->data); writeb(ch, &channel->data);
ZSDELAY(); ZSDELAY();
ZS_WSYNC(channel); ZS_WSYNC(channel);
uart_xmit_advance(port, 1); if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&up->port); uart_write_wakeup(&up->port);
} }
} }

View File

@ -91,15 +91,17 @@ static void tegra_tcu_write(struct tegra_tcu *tcu, const char *s,
static void tegra_tcu_uart_start_tx(struct uart_port *port) static void tegra_tcu_uart_start_tx(struct uart_port *port)
{ {
struct tegra_tcu *tcu = port->private_data; struct tegra_tcu *tcu = port->private_data;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned long count; unsigned char *tail;
unsigned int count;
for (;;) { for (;;) {
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); count = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail,
UART_XMIT_SIZE);
if (!count) if (!count)
break; break;
tegra_tcu_write(tcu, &xmit->buf[xmit->tail], count); tegra_tcu_write(tcu, tail, count);
uart_xmit_advance(port, count); uart_xmit_advance(port, count);
} }

View File

@ -95,14 +95,11 @@ static void timbuart_rx_chars(struct uart_port *port)
static void timbuart_tx_chars(struct uart_port *port) static void timbuart_tx_chars(struct uart_port *port)
{ {
struct circ_buf *xmit = &port->state->xmit; unsigned char ch;
while (!(ioread32(port->membase + TIMBUART_ISR) & TXBF) && while (!(ioread32(port->membase + TIMBUART_ISR) & TXBF) &&
!uart_circ_empty(xmit)) { uart_fifo_get(port, &ch))
iowrite8(xmit->buf[xmit->tail], iowrite8(ch, port->membase + TIMBUART_TXFIFO);
port->membase + TIMBUART_TXFIFO);
uart_xmit_advance(port, 1);
}
dev_dbg(port->dev, dev_dbg(port->dev,
"%s - total written %d bytes, CTL: %x, RTS: %x, baud: %x\n", "%s - total written %d bytes, CTL: %x, RTS: %x, baud: %x\n",
@ -117,9 +114,9 @@ static void timbuart_handle_tx_port(struct uart_port *port, u32 isr, u32 *ier)
{ {
struct timbuart_port *uart = struct timbuart_port *uart =
container_of(port, struct timbuart_port, port); container_of(port, struct timbuart_port, port);
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port))
return; return;
if (port->x_char) if (port->x_char)
@ -130,7 +127,7 @@ static void timbuart_handle_tx_port(struct uart_port *port, u32 isr, u32 *ier)
/* clear all TX interrupts */ /* clear all TX interrupts */
iowrite32(TXFLAGS, port->membase + TIMBUART_ISR); iowrite32(TXFLAGS, port->membase + TIMBUART_ISR);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
} else } else
/* Re-enable any tx interrupt */ /* Re-enable any tx interrupt */
@ -141,7 +138,7 @@ static void timbuart_handle_tx_port(struct uart_port *port, u32 isr, u32 *ier)
* we wake up the upper layer later when we got the interrupt * we wake up the upper layer later when we got the interrupt
* to give it some time to go out... * to give it some time to go out...
*/ */
if (!uart_circ_empty(xmit)) if (!kfifo_is_empty(&tport->xmit_fifo))
*ier |= TXBAE; *ier |= TXBAE;
dev_dbg(port->dev, "%s - leaving\n", __func__); dev_dbg(port->dev, "%s - leaving\n", __func__);

View File

@ -189,7 +189,8 @@ static int ulite_receive(struct uart_port *port, int stat)
static int ulite_transmit(struct uart_port *port, int stat) static int ulite_transmit(struct uart_port *port, int stat)
{ {
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned char ch;
if (stat & ULITE_STATUS_TXFULL) if (stat & ULITE_STATUS_TXFULL)
return 0; return 0;
@ -201,14 +202,16 @@ static int ulite_transmit(struct uart_port *port, int stat)
return 1; return 1;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) if (uart_tx_stopped(port))
return 0; return 0;
uart_out32(xmit->buf[xmit->tail], ULITE_TX, port); if (!uart_fifo_get(port, &ch))
uart_xmit_advance(port, 1); return 0;
uart_out32(ch, ULITE_TX, port);
/* wake up */ /* wake up */
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
return 1; return 1;

View File

@ -334,7 +334,7 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port)
unsigned char *p; unsigned char *p;
unsigned int count; unsigned int count;
struct uart_port *port = &qe_port->port; struct uart_port *port = &qe_port->port;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
/* Handle xon/xoff */ /* Handle xon/xoff */
if (port->x_char) { if (port->x_char) {
@ -358,7 +358,7 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port)
return 1; return 1;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
qe_uart_stop_tx(port); qe_uart_stop_tx(port);
return 0; return 0;
} }
@ -366,16 +366,10 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port)
/* Pick next descriptor and fill from buffer */ /* Pick next descriptor and fill from buffer */
bdp = qe_port->tx_cur; bdp = qe_port->tx_cur;
while (!(ioread16be(&bdp->status) & BD_SC_READY) && !uart_circ_empty(xmit)) { while (!(ioread16be(&bdp->status) & BD_SC_READY) &&
count = 0; !kfifo_is_empty(&tport->xmit_fifo)) {
p = qe2cpu_addr(ioread32be(&bdp->buf), qe_port); p = qe2cpu_addr(ioread32be(&bdp->buf), qe_port);
while (count < qe_port->tx_fifosize) { count = uart_fifo_out(port, p, qe_port->tx_fifosize);
*p++ = xmit->buf[xmit->tail];
uart_xmit_advance(port, 1);
count++;
if (uart_circ_empty(xmit))
break;
}
iowrite16be(count, &bdp->length); iowrite16be(count, &bdp->length);
qe_setbits_be16(&bdp->status, BD_SC_READY); qe_setbits_be16(&bdp->status, BD_SC_READY);
@ -388,10 +382,10 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port)
} }
qe_port->tx_cur = bdp; qe_port->tx_cur = bdp;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) { if (kfifo_is_empty(&tport->xmit_fifo)) {
/* The kernel buffer is empty, so turn off TX interrupts. We /* The kernel buffer is empty, so turn off TX interrupts. We
don't need to be told when the QE is finished transmitting don't need to be told when the QE is finished transmitting
the data. */ the data. */

View File

@ -425,32 +425,32 @@ static void cdns_uart_handle_tx(void *dev_id)
{ {
struct uart_port *port = (struct uart_port *)dev_id; struct uart_port *port = (struct uart_port *)dev_id;
struct cdns_uart *cdns_uart = port->private_data; struct cdns_uart *cdns_uart = port->private_data;
struct circ_buf *xmit = &port->state->xmit; struct tty_port *tport = &port->state->port;
unsigned int numbytes; unsigned int numbytes;
unsigned char ch;
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
/* Disable the TX Empty interrupt */ /* Disable the TX Empty interrupt */
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR); writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR);
return; return;
} }
numbytes = port->fifosize; numbytes = port->fifosize;
while (numbytes && !uart_circ_empty(xmit) && while (numbytes &&
!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)) { !(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL) &&
uart_fifo_get(port, &ch)) {
writel(xmit->buf[xmit->tail], port->membase + CDNS_UART_FIFO); writel(ch, port->membase + CDNS_UART_FIFO);
uart_xmit_advance(port, 1);
numbytes--; numbytes--;
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
/* Enable the TX Empty interrupt */ /* Enable the TX Empty interrupt */
writel(CDNS_UART_IXR_TXEMPTY, cdns_uart->port->membase + CDNS_UART_IER); writel(CDNS_UART_IXR_TXEMPTY, cdns_uart->port->membase + CDNS_UART_IER);
if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED && if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED &&
(uart_circ_empty(xmit) || uart_tx_stopped(port))) { (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port))) {
cdns_uart->tx_timer.function = &cdns_rs485_rx_callback; cdns_uart->tx_timer.function = &cdns_rs485_rx_callback;
hrtimer_start(&cdns_uart->tx_timer, hrtimer_start(&cdns_uart->tx_timer,
ns_to_ktime(cdns_calc_after_tx_delay(cdns_uart)), HRTIMER_MODE_REL); ns_to_ktime(cdns_calc_after_tx_delay(cdns_uart)), HRTIMER_MODE_REL);
@ -723,7 +723,7 @@ static void cdns_uart_start_tx(struct uart_port *port)
status |= CDNS_UART_CR_TX_EN; status |= CDNS_UART_CR_TX_EN;
writel(status, port->membase + CDNS_UART_CR); writel(status, port->membase + CDNS_UART_CR);
if (uart_circ_empty(&port->state->xmit)) if (kfifo_is_empty(&port->state->port.xmit_fifo))
return; return;
/* Clear the TX Empty interrupt */ /* Clear the TX Empty interrupt */

View File

@ -606,7 +606,8 @@ static void zs_receive_chars(struct zs_port *zport)
static void zs_raw_transmit_chars(struct zs_port *zport) static void zs_raw_transmit_chars(struct zs_port *zport)
{ {
struct circ_buf *xmit = &zport->port.state->xmit; struct tty_port *tport = &zport->port.state->port;
unsigned char ch;
/* XON/XOFF chars. */ /* XON/XOFF chars. */
if (zport->port.x_char) { if (zport->port.x_char) {
@ -617,20 +618,20 @@ static void zs_raw_transmit_chars(struct zs_port *zport)
} }
/* If nothing to do or stopped or hardware stopped. */ /* If nothing to do or stopped or hardware stopped. */
if (uart_circ_empty(xmit) || uart_tx_stopped(&zport->port)) { if (uart_tx_stopped(&zport->port) ||
!uart_fifo_get(&zport->port, &ch)) {
zs_raw_stop_tx(zport); zs_raw_stop_tx(zport);
return; return;
} }
/* Send char. */ /* Send char. */
write_zsdata(zport, xmit->buf[xmit->tail]); write_zsdata(zport, ch);
uart_xmit_advance(&zport->port, 1);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&zport->port); uart_write_wakeup(&zport->port);
/* Are we are done? */ /* Are we are done? */
if (uart_circ_empty(xmit)) if (kfifo_is_empty(&tport->xmit_fifo))
zs_raw_stop_tx(zport); zs_raw_stop_tx(zport);
} }

View File

@ -11,7 +11,6 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/circ_buf.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/tty.h> #include <linux/tty.h>
@ -699,7 +698,6 @@ struct uart_state {
struct tty_port port; struct tty_port port;
enum uart_pm_state pm_state; enum uart_pm_state pm_state;
struct circ_buf xmit;
atomic_t refcount; atomic_t refcount;
wait_queue_head_t remove_wait; wait_queue_head_t remove_wait;
@ -723,12 +721,35 @@ struct uart_state {
*/ */
static inline void uart_xmit_advance(struct uart_port *up, unsigned int chars) static inline void uart_xmit_advance(struct uart_port *up, unsigned int chars)
{ {
struct circ_buf *xmit = &up->state->xmit; struct tty_port *tport = &up->state->port;
xmit->tail = (xmit->tail + chars) & (UART_XMIT_SIZE - 1); kfifo_skip_count(&tport->xmit_fifo, chars);
up->icount.tx += chars; up->icount.tx += chars;
} }
static inline unsigned int uart_fifo_out(struct uart_port *up,
unsigned char *buf, unsigned int chars)
{
struct tty_port *tport = &up->state->port;
chars = kfifo_out(&tport->xmit_fifo, buf, chars);
up->icount.tx += chars;
return chars;
}
static inline unsigned int uart_fifo_get(struct uart_port *up,
unsigned char *ch)
{
struct tty_port *tport = &up->state->port;
unsigned int chars;
chars = kfifo_get(&tport->xmit_fifo, ch);
up->icount.tx += chars;
return chars;
}
struct module; struct module;
struct tty_driver; struct tty_driver;
@ -764,7 +785,7 @@ enum UART_TX_FLAGS {
for_test, for_post) \ for_test, for_post) \
({ \ ({ \
struct uart_port *__port = (uport); \ struct uart_port *__port = (uport); \
struct circ_buf *xmit = &__port->state->xmit; \ struct tty_port *__tport = &__port->state->port; \
unsigned int pending; \ unsigned int pending; \
\ \
for (; (for_test) && (tx_ready); (for_post), __port->icount.tx++) { \ for (; (for_test) && (tx_ready); (for_post), __port->icount.tx++) { \
@ -775,17 +796,18 @@ enum UART_TX_FLAGS {
continue; \ continue; \
} \ } \
\ \
if (uart_circ_empty(xmit) || uart_tx_stopped(__port)) \ if (uart_tx_stopped(__port)) \
break; \
\
if (!kfifo_get(&__tport->xmit_fifo, &(ch))) \
break; \ break; \
\ \
(ch) = xmit->buf[xmit->tail]; \
(put_char); \ (put_char); \
xmit->tail = (xmit->tail + 1) % UART_XMIT_SIZE; \
} \ } \
\ \
(tx_done); \ (tx_done); \
\ \
pending = uart_circ_chars_pending(xmit); \ pending = kfifo_len(&__tport->xmit_fifo); \
if (pending < WAKEUP_CHARS) { \ if (pending < WAKEUP_CHARS) { \
uart_write_wakeup(__port); \ uart_write_wakeup(__port); \
\ \
@ -974,15 +996,6 @@ bool uart_match_port(const struct uart_port *port1,
int uart_suspend_port(struct uart_driver *reg, struct uart_port *port); int uart_suspend_port(struct uart_driver *reg, struct uart_port *port);
int uart_resume_port(struct uart_driver *reg, struct uart_port *port); int uart_resume_port(struct uart_driver *reg, struct uart_port *port);
#define uart_circ_empty(circ) ((circ)->head == (circ)->tail)
#define uart_circ_clear(circ) ((circ)->head = (circ)->tail = 0)
#define uart_circ_chars_pending(circ) \
(CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
#define uart_circ_chars_free(circ) \
(CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
static inline int uart_tx_stopped(struct uart_port *port) static inline int uart_tx_stopped(struct uart_port *port)
{ {
struct tty_struct *tty = port->state->port.tty; struct tty_struct *tty = port->state->port.tty;