mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
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:
committed by
Greg Kroah-Hartman
parent
f8fef2fa41
commit
1788cf6a91
@@ -413,20 +413,18 @@ static int stop_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 circ_buf *xmit = &p->port.state->xmit;
|
||||
struct tty_port *tport = &p->port.state->port;
|
||||
u32 tx_size;
|
||||
|
||||
if (uart_tx_stopped(&p->port) || priv->tx_running ||
|
||||
uart_circ_empty(xmit)) {
|
||||
kfifo_is_empty(&tport->xmit_fifo)) {
|
||||
return 0;
|
||||
}
|
||||
tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
||||
|
||||
priv->dma.tx_err = 0;
|
||||
memcpy(priv->tx_buf, &xmit->buf[xmit->tail], tx_size);
|
||||
uart_xmit_advance(&p->port, tx_size);
|
||||
tx_size = uart_fifo_out(&p->port, priv->tx_buf, UART_XMIT_SIZE);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&p->port);
|
||||
|
||||
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 device *dev = up->dev;
|
||||
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 (priv->tx_running)
|
||||
@@ -548,7 +546,7 @@ static void brcmuart_tx_isr(struct uart_port *up, u32 isr)
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -280,7 +280,8 @@ static void serial8250_backup_timeout(struct timer_list *t)
|
||||
*/
|
||||
lsr = serial_lsr_in(up);
|
||||
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)) {
|
||||
iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
|
||||
iir |= UART_IIR_THRI;
|
||||
|
||||
@@ -15,7 +15,7 @@ static void __dma_tx_complete(void *param)
|
||||
{
|
||||
struct uart_8250_port *p = param;
|
||||
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;
|
||||
int ret;
|
||||
|
||||
@@ -28,7 +28,7 @@ static void __dma_tx_complete(void *param)
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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 uart_port *up = &p->port;
|
||||
struct scatterlist sg;
|
||||
@@ -103,18 +103,23 @@ int serial8250_tx_dma(struct uart_8250_port *p)
|
||||
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() */
|
||||
return 0;
|
||||
}
|
||||
|
||||
dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
||||
|
||||
serial8250_do_prepare_tx_dma(p);
|
||||
|
||||
sg_init_table(&sg, 1);
|
||||
sg_dma_address(&sg) = dma->tx_addr + xmit->tail;
|
||||
sg_dma_len(&sg) = dma->tx_size;
|
||||
/* kfifo can do more than one sg, we don't (quite yet) */
|
||||
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,
|
||||
DMA_MEM_TO_DEV,
|
||||
@@ -257,7 +262,7 @@ int serial8250_request_dma(struct uart_8250_port *p)
|
||||
|
||||
/* TX buffer */
|
||||
dma->tx_addr = dma_map_single(dma->txchan->device->dev,
|
||||
p->port.state->xmit.buf,
|
||||
p->port.state->port.xmit_buf,
|
||||
UART_XMIT_SIZE,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dma->txchan->device->dev, dma->tx_addr)) {
|
||||
|
||||
@@ -214,7 +214,7 @@ static void exar_shutdown(struct uart_port *port)
|
||||
{
|
||||
bool tx_complete = false;
|
||||
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;
|
||||
u16 lsr;
|
||||
|
||||
@@ -225,7 +225,8 @@ static void exar_shutdown(struct uart_port *port)
|
||||
else
|
||||
tx_complete = false;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ static int mtk8250_startup(struct uart_port *port)
|
||||
|
||||
if (up->dma) {
|
||||
data->rx_status = DMA_RX_START;
|
||||
uart_circ_clear(&port->state->xmit);
|
||||
kfifo_reset(&port->state->port.xmit_fifo);
|
||||
}
|
||||
#endif
|
||||
memset(&port->icount, 0, sizeof(port->icount));
|
||||
|
||||
@@ -1094,7 +1094,7 @@ static void omap_8250_dma_tx_complete(void *param)
|
||||
{
|
||||
struct uart_8250_port *p = param;
|
||||
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;
|
||||
bool en_thri = false;
|
||||
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);
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
|
||||
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;
|
||||
|
||||
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 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 scatterlist sg;
|
||||
unsigned int skip_byte = 0;
|
||||
int skip_byte = -1;
|
||||
int ret;
|
||||
|
||||
if (dma->tx_running)
|
||||
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
|
||||
@@ -1161,8 +1161,18 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
|
||||
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) {
|
||||
unsigned char c;
|
||||
u8 tx_lvl;
|
||||
|
||||
/*
|
||||
@@ -1189,13 +1199,16 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
|
||||
ret = -EINVAL;
|
||||
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,
|
||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
if (!desc) {
|
||||
@@ -1218,11 +1231,13 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
|
||||
dma->tx_err = 0;
|
||||
|
||||
serial8250_clear_THRI(p);
|
||||
if (skip_byte)
|
||||
serial_out(p, UART_TX, xmit->buf[xmit->tail]);
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto out_skip;
|
||||
err:
|
||||
dma->tx_err = 1;
|
||||
out_skip:
|
||||
if (skip_byte >= 0)
|
||||
serial_out(p, UART_TX, skip_byte);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1311,7 +1326,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
|
||||
serial8250_modem_status(up);
|
||||
if (status & UART_LSR_THRE && up->dma->tx_err) {
|
||||
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;
|
||||
serial8250_tx_chars(up);
|
||||
} else {
|
||||
|
||||
@@ -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,
|
||||
struct circ_buf *xmit,
|
||||
int *data_empty_count,
|
||||
u32 *valid_byte_count)
|
||||
{
|
||||
struct tty_port *tport = &port->state->port;
|
||||
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.
|
||||
*/
|
||||
while (valid_burst_count) {
|
||||
u32 c;
|
||||
|
||||
if (*data_empty_count - UART_BURST_SIZE < 0)
|
||||
break;
|
||||
if (xmit->tail > (UART_XMIT_SIZE - UART_BURST_SIZE))
|
||||
if (kfifo_len(&tport->xmit_fifo) < UART_BURST_SIZE)
|
||||
break;
|
||||
writel(*(unsigned int *)&xmit->buf[xmit->tail],
|
||||
port->membase + UART_TX_BURST_FIFO);
|
||||
if (WARN_ON(kfifo_out(&tport->xmit_fifo, (u8 *)&c, sizeof(c)) !=
|
||||
sizeof(c)))
|
||||
break;
|
||||
writel(c, port->membase + UART_TX_BURST_FIFO);
|
||||
*valid_byte_count -= UART_BURST_SIZE;
|
||||
*data_empty_count -= UART_BURST_SIZE;
|
||||
valid_burst_count -= UART_BYTE_SIZE;
|
||||
|
||||
xmit->tail = (xmit->tail + UART_BURST_SIZE) &
|
||||
(UART_XMIT_SIZE - 1);
|
||||
}
|
||||
|
||||
while (*valid_byte_count) {
|
||||
if (*data_empty_count - UART_BYTE_SIZE < 0)
|
||||
u8 c;
|
||||
|
||||
if (!kfifo_get(&tport->xmit_fifo, &c))
|
||||
break;
|
||||
writeb(xmit->buf[xmit->tail], port->membase +
|
||||
UART_TX_BYTE_FIFO);
|
||||
writeb(c, port->membase + UART_TX_BYTE_FIFO);
|
||||
*data_empty_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
|
||||
* transmitting DWORDs at a time.
|
||||
*/
|
||||
if (valid_burst_count && (xmit->tail <
|
||||
(UART_XMIT_SIZE - UART_BURST_SIZE)))
|
||||
if (valid_burst_count &&
|
||||
kfifo_len(&tport->xmit_fifo) >= UART_BURST_SIZE)
|
||||
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)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
struct tty_port *tport = &port->state->port;
|
||||
u32 valid_byte_count;
|
||||
int data_empty_count;
|
||||
struct circ_buf *xmit;
|
||||
|
||||
xmit = &port->state->xmit;
|
||||
|
||||
if (port->x_char) {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
data_empty_count = (pci1xxxx_read_burst_status(port) &
|
||||
UART_BST_STAT_TX_COUNT_MASK) >> 8;
|
||||
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,
|
||||
&valid_byte_count);
|
||||
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
if (kfifo_is_empty(&tport->xmit_fifo))
|
||||
break;
|
||||
} 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);
|
||||
|
||||
/*
|
||||
@@ -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
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1630,7 +1630,7 @@ static void serial8250_start_tx(struct uart_port *port)
|
||||
/* Port locked to synchronize UART_IER access against the console. */
|
||||
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;
|
||||
|
||||
serial8250_rpm_get_tx(up);
|
||||
@@ -1778,7 +1778,7 @@ EXPORT_SYMBOL_GPL(serial8250_rx_chars);
|
||||
void serial8250_tx_chars(struct uart_8250_port *up)
|
||||
{
|
||||
struct uart_port *port = &up->port;
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
struct tty_port *tport = &port->state->port;
|
||||
int count;
|
||||
|
||||
if (port->x_char) {
|
||||
@@ -1789,14 +1789,19 @@ void serial8250_tx_chars(struct uart_8250_port *up)
|
||||
serial8250_stop_tx(port);
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty(xmit)) {
|
||||
if (kfifo_is_empty(&tport->xmit_fifo)) {
|
||||
__stop_tx(up);
|
||||
return;
|
||||
}
|
||||
|
||||
count = up->tx_loadsz;
|
||||
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) {
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
uart_xmit_advance(port, 1);
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
|
||||
if ((up->capabilities & UART_CAP_HFIFO) &&
|
||||
!uart_lsr_tx_empty(serial_in(up, UART_LSR)))
|
||||
break;
|
||||
@@ -1821,7 +1824,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
|
||||
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
|
||||
* 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);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serial8250_tx_chars);
|
||||
|
||||
@@ -535,6 +535,7 @@ static void pl011_start_tx_pio(struct uart_amba_port *uap);
|
||||
static void pl011_dma_tx_callback(void *data)
|
||||
{
|
||||
struct uart_amba_port *uap = data;
|
||||
struct tty_port *tport = &uap->port.state->port;
|
||||
struct pl011_dmatx_data *dmatx = &uap->dmatx;
|
||||
unsigned long flags;
|
||||
u16 dmacr;
|
||||
@@ -558,7 +559,7 @@ static void pl011_dma_tx_callback(void *data)
|
||||
* get further refills (hence we check dmacr).
|
||||
*/
|
||||
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;
|
||||
uart_port_unlock_irqrestore(&uap->port, flags);
|
||||
return;
|
||||
@@ -588,7 +589,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
|
||||
struct dma_chan *chan = dmatx->chan;
|
||||
struct dma_device *dma_dev = chan->device;
|
||||
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;
|
||||
|
||||
/*
|
||||
@@ -597,7 +598,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
|
||||
* the standard interrupt handling. This ensures that we
|
||||
* 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)) {
|
||||
uap->dmatx.queued = false;
|
||||
return 0;
|
||||
@@ -613,21 +614,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
|
||||
if (count > PL011_DMA_BUFFER_SIZE)
|
||||
count = PL011_DMA_BUFFER_SIZE;
|
||||
|
||||
if (xmit->tail < xmit->head) {
|
||||
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);
|
||||
}
|
||||
|
||||
count = kfifo_out_peek(&tport->xmit_fifo, dmatx->buf, count);
|
||||
dmatx->len = count;
|
||||
dmatx->dma = dma_map_single(dma_dev->dev, dmatx->buf, count,
|
||||
DMA_TO_DEVICE);
|
||||
@@ -670,7 +657,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
|
||||
*/
|
||||
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);
|
||||
|
||||
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 */
|
||||
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;
|
||||
|
||||
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;
|
||||
--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);
|
||||
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))
|
||||
return true;
|
||||
|
||||
do {
|
||||
while (1) {
|
||||
unsigned char c;
|
||||
|
||||
if (likely(from_irq) && count-- == 0)
|
||||
break;
|
||||
|
||||
if (!pl011_tx_char(uap, xmit->buf[xmit->tail], from_irq))
|
||||
if (!kfifo_peek(&tport->xmit_fifo, &c))
|
||||
break;
|
||||
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
} while (!uart_circ_empty(xmit));
|
||||
if (!pl011_tx_char(uap, c, from_irq))
|
||||
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);
|
||||
|
||||
if (uart_circ_empty(xmit)) {
|
||||
if (kfifo_is_empty(&tport->xmit_fifo)) {
|
||||
pl011_stop_tx(&uap->port);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
struct circ_buf *xmit = &up->port.state->xmit;
|
||||
struct tty_port *tport = &up->port.state->port;
|
||||
struct serial_rs485 *rs485conf = &up->port.rs485;
|
||||
int count;
|
||||
bool half_duplex_send = false;
|
||||
@@ -399,7 +399,7 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
|
||||
return;
|
||||
|
||||
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);
|
||||
gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_ON_SEND));
|
||||
half_duplex_send = true;
|
||||
@@ -408,6 +408,7 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
|
||||
count = up->port.fifosize;
|
||||
do {
|
||||
unsigned int rdata;
|
||||
unsigned char c;
|
||||
|
||||
rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG);
|
||||
if ((rdata & AR933X_UART_DATA_TX_CSR) == 0)
|
||||
@@ -420,18 +421,16 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
if (!uart_fifo_get(&up->port, &c))
|
||||
break;
|
||||
|
||||
ar933x_uart_putc(up, xmit->buf[xmit->tail]);
|
||||
|
||||
uart_xmit_advance(&up->port, 1);
|
||||
ar933x_uart_putc(up, c);
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&up->port);
|
||||
|
||||
if (!uart_circ_empty(xmit)) {
|
||||
if (!kfifo_is_empty(&tport->xmit_fifo)) {
|
||||
ar933x_uart_start_tx_interrupt(up);
|
||||
} else if (half_duplex_send) {
|
||||
ar933x_uart_wait_tx_complete(up);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
struct tty_port *tport = &port->state->port;
|
||||
int sent = 0;
|
||||
unsigned char ch;
|
||||
|
||||
@@ -164,9 +164,7 @@ static void arc_serial_tx_chars(struct uart_port *port)
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
sent = 1;
|
||||
} else if (!uart_circ_empty(xmit)) {
|
||||
ch = xmit->buf[xmit->tail];
|
||||
uart_xmit_advance(port, 1);
|
||||
} else if (uart_fifo_get(port, &ch)) {
|
||||
while (!(UART_GET_STATUS(port) & TXEMPTY))
|
||||
cpu_relax();
|
||||
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.
|
||||
* 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);
|
||||
|
||||
if (sent)
|
||||
|
||||
@@ -857,7 +857,7 @@ static void atmel_complete_tx_dma(void *arg)
|
||||
{
|
||||
struct atmel_uart_port *atmel_port = arg;
|
||||
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;
|
||||
unsigned long flags;
|
||||
|
||||
@@ -873,15 +873,15 @@ static void atmel_complete_tx_dma(void *arg)
|
||||
atmel_port->desc_tx = NULL;
|
||||
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);
|
||||
|
||||
/*
|
||||
* xmit is a circular buffer so, if we have just send data from
|
||||
* xmit->tail to the end of xmit->buf, now we have to transmit the
|
||||
* remaining data from the beginning of xmit->buf to xmit->head.
|
||||
* xmit is a circular buffer so, if we have just send data from the
|
||||
* tail to the end, now we have to transmit the remaining data from the
|
||||
* 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);
|
||||
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)
|
||||
{
|
||||
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_async_tx_descriptor *desc;
|
||||
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;
|
||||
|
||||
/* Make sure we have an idle channel */
|
||||
if (atmel_port->desc_tx != NULL)
|
||||
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.
|
||||
* 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
|
||||
* consistent xmit buffer state.
|
||||
*/
|
||||
tx_len = CIRC_CNT_TO_END(xmit->head,
|
||||
xmit->tail,
|
||||
UART_XMIT_SIZE);
|
||||
tx_len = kfifo_out_linear(&tport->xmit_fifo, &tail,
|
||||
UART_XMIT_SIZE);
|
||||
|
||||
if (atmel_port->fifo_size) {
|
||||
/* multi data mode */
|
||||
@@ -956,7 +955,7 @@ static void atmel_tx_dma(struct uart_port *port)
|
||||
|
||||
sg_init_table(sgl, 2);
|
||||
sg_len = 0;
|
||||
phys_addr = sg_dma_address(sg_tx) + xmit->tail;
|
||||
phys_addr = sg_dma_address(sg_tx) + tail;
|
||||
if (part1_len) {
|
||||
sg = &sgl[sg_len++];
|
||||
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
|
||||
* xmit->tail correctly
|
||||
* tail correctly
|
||||
*/
|
||||
atmel_port->tx_len = tx_len;
|
||||
|
||||
@@ -1003,13 +1002,14 @@ static void atmel_tx_dma(struct uart_port *port)
|
||||
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);
|
||||
}
|
||||
|
||||
static int atmel_prepare_tx_dma(struct 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;
|
||||
dma_cap_mask_t mask;
|
||||
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);
|
||||
sg_init_table(&atmel_port->sg_tx, 1);
|
||||
/* 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,
|
||||
virt_to_page(port->state->xmit.buf),
|
||||
virt_to_page(tport->xmit_buf),
|
||||
UART_XMIT_SIZE,
|
||||
offset_in_page(port->state->xmit.buf));
|
||||
offset_in_page(tport->xmit_buf));
|
||||
nent = dma_map_sg(port->dev,
|
||||
&atmel_port->sg_tx,
|
||||
1,
|
||||
@@ -1047,7 +1047,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
|
||||
} else {
|
||||
dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__,
|
||||
sg_dma_len(&atmel_port->sg_tx),
|
||||
port->state->xmit.buf,
|
||||
tport->xmit_buf,
|
||||
&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)
|
||||
{
|
||||
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;
|
||||
int count;
|
||||
|
||||
/* nothing left to transmit? */
|
||||
if (atmel_uart_readl(port, ATMEL_PDC_TCR))
|
||||
@@ -1474,17 +1473,19 @@ static void atmel_tx_pdc(struct uart_port *port)
|
||||
/* disable PDC transmit */
|
||||
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,
|
||||
pdc->dma_addr,
|
||||
pdc->dma_size,
|
||||
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;
|
||||
|
||||
atmel_uart_writel(port, ATMEL_PDC_TPR,
|
||||
pdc->dma_addr + xmit->tail);
|
||||
atmel_uart_writel(port, ATMEL_PDC_TPR, pdc->dma_addr + tail);
|
||||
atmel_uart_writel(port, ATMEL_PDC_TCR, count);
|
||||
/* re-enable PDC transmit */
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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_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->buf,
|
||||
UART_XMIT_SIZE,
|
||||
|
||||
@@ -146,7 +146,8 @@ static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
|
||||
if (s->tx_enabled) {
|
||||
disable_irq_nosync(port->irq);
|
||||
s->tx_enabled = 0;
|
||||
@@ -163,18 +164,17 @@ static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
while (!uart_circ_empty(xmit)) {
|
||||
while (uart_fifo_get(port, &c)) {
|
||||
u32 sysflg = 0;
|
||||
|
||||
writew(xmit->buf[xmit->tail], port->membase + UARTDR_OFFSET);
|
||||
uart_xmit_advance(port, 1);
|
||||
writew(c, port->membase + UARTDR_OFFSET);
|
||||
|
||||
regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
|
||||
if (sysflg & SYSFLG_UTXFF)
|
||||
break;
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
||||
@@ -648,7 +648,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
|
||||
int count;
|
||||
struct uart_cpm_port *pinfo =
|
||||
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 */
|
||||
if (port->x_char) {
|
||||
@@ -673,7 +673,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
@@ -681,16 +681,10 @@ static int cpm_uart_tx_pump(struct uart_port *port)
|
||||
/* Pick next descriptor and fill from buffer */
|
||||
bdp = pinfo->tx_cur;
|
||||
|
||||
while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) && !uart_circ_empty(xmit)) {
|
||||
count = 0;
|
||||
while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) &&
|
||||
!kfifo_is_empty(&tport->xmit_fifo)) {
|
||||
p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
|
||||
while (count < pinfo->tx_fifosize) {
|
||||
*p++ = xmit->buf[xmit->tail];
|
||||
uart_xmit_advance(port, 1);
|
||||
count++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
}
|
||||
count = uart_fifo_out(port, p, pinfo->tx_fifosize);
|
||||
out_be16(&bdp->cbd_datlen, count);
|
||||
setbits16(&bdp->cbd_sc, BD_SC_READY);
|
||||
/* Get next BD. */
|
||||
@@ -701,10 +695,10 @@ static int cpm_uart_tx_pump(struct uart_port *port)
|
||||
}
|
||||
pinfo->tx_cur = bdp;
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit)) {
|
||||
if (kfifo_is_empty(&tport->xmit_fifo)) {
|
||||
cpm_uart_stop_tx(port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -179,8 +179,9 @@ static void digicolor_uart_rx(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 char c;
|
||||
|
||||
if (digicolor_uart_tx_full(port))
|
||||
return;
|
||||
@@ -194,20 +195,19 @@ static void digicolor_uart_tx(struct uart_port *port)
|
||||
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);
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (!uart_circ_empty(xmit)) {
|
||||
writeb(xmit->buf[xmit->tail], port->membase + UA_EMI_REC);
|
||||
uart_xmit_advance(port, 1);
|
||||
while (uart_fifo_get(port, &c)) {
|
||||
writeb(c, port->membase + UA_EMI_REC);
|
||||
|
||||
if (digicolor_uart_tx_full(port))
|
||||
break;
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
out:
|
||||
|
||||
@@ -252,13 +252,13 @@ static inline void dz_receive_chars(struct dz_mux *mux)
|
||||
static inline void dz_transmit_chars(struct dz_mux *mux)
|
||||
{
|
||||
struct dz_port *dport = &mux->dport[0];
|
||||
struct circ_buf *xmit;
|
||||
struct tty_port *tport;
|
||||
unsigned char tmp;
|
||||
u16 status;
|
||||
|
||||
status = dz_in(dport, DZ_CSR);
|
||||
dport = &mux->dport[LINE(status)];
|
||||
xmit = &dport->port.state->xmit;
|
||||
tport = &dport->port.state->port;
|
||||
|
||||
if (dport->port.x_char) { /* XON/XOFF chars */
|
||||
dz_out(dport, DZ_TDR, dport->port.x_char);
|
||||
@@ -267,7 +267,8 @@ static inline void dz_transmit_chars(struct dz_mux *mux)
|
||||
return;
|
||||
}
|
||||
/* 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);
|
||||
dz_stop_tx(&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,
|
||||
* so we go one char at a time) :-<
|
||||
*/
|
||||
tmp = xmit->buf[xmit->tail];
|
||||
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);
|
||||
|
||||
/* Are we are done. */
|
||||
if (uart_circ_empty(xmit)) {
|
||||
if (kfifo_is_empty(&tport->xmit_fifo)) {
|
||||
uart_port_lock(&dport->port);
|
||||
dz_stop_tx(&dport->port);
|
||||
uart_port_unlock(&dport->port);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
struct circ_buf *xmit = &sport->state->xmit;
|
||||
struct tty_port *tport = &sport->state->port;
|
||||
unsigned char c;
|
||||
|
||||
while (!uart_circ_empty(xmit)) {
|
||||
linflex_put_char(sport, xmit->buf[xmit->tail]);
|
||||
uart_xmit_advance(sport, 1);
|
||||
while (uart_fifo_get(sport, &c)) {
|
||||
linflex_put_char(sport, c);
|
||||
sport->icount.tx++;
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(sport);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
if (kfifo_is_empty(&tport->xmit_fifo))
|
||||
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)
|
||||
{
|
||||
struct uart_port *sport = dev_id;
|
||||
struct circ_buf *xmit = &sport->state->xmit;
|
||||
struct tty_port *tport = &sport->state->port;
|
||||
unsigned long flags;
|
||||
|
||||
uart_port_lock_irqsave(sport, &flags);
|
||||
@@ -210,7 +211,7 @@ static irqreturn_t linflex_txint(int irq, void *dev_id)
|
||||
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);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/console.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)
|
||||
{
|
||||
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||
struct tty_port *tport = &sport->port.state->port;
|
||||
struct scatterlist *sgl = sport->tx_sgl;
|
||||
struct device *dev = sport->port.dev;
|
||||
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)
|
||||
return;
|
||||
|
||||
sport->dma_tx_bytes = uart_circ_chars_pending(xmit);
|
||||
|
||||
if (xmit->tail < xmit->head || xmit->head == 0) {
|
||||
sport->dma_tx_nents = 1;
|
||||
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);
|
||||
}
|
||||
sg_init_table(sgl, ARRAY_SIZE(sport->tx_sgl));
|
||||
sport->dma_tx_bytes = kfifo_len(&tport->xmit_fifo);
|
||||
sport->dma_tx_nents = kfifo_dma_out_prepare(&tport->xmit_fifo, sgl,
|
||||
ARRAY_SIZE(sport->tx_sgl), sport->dma_tx_bytes);
|
||||
|
||||
ret = dma_map_sg(chan->device->dev, sgl, sport->dma_tx_nents,
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
struct lpuart_port *sport = arg;
|
||||
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;
|
||||
unsigned long flags;
|
||||
|
||||
@@ -545,7 +539,7 @@ static void lpuart_dma_tx_complete(void *arg)
|
||||
sport->dma_tx_in_progress = false;
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||
struct tty_port *tport = &sport->port.state->port;
|
||||
unsigned long txcnt;
|
||||
unsigned char c;
|
||||
|
||||
if (sport->port.x_char) {
|
||||
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 = txcnt >> UARTWATER_TXCNT_OFF;
|
||||
txcnt &= UARTWATER_COUNT_MASK;
|
||||
while (!uart_circ_empty(xmit) && (txcnt < sport->txfifo_size)) {
|
||||
lpuart32_write(&sport->port, xmit->buf[xmit->tail], UARTDATA);
|
||||
uart_xmit_advance(&sport->port, 1);
|
||||
while (txcnt < sport->txfifo_size &&
|
||||
uart_fifo_get(&sport->port, &c)) {
|
||||
lpuart32_write(&sport->port, c, UARTDATA);
|
||||
txcnt = lpuart32_read(&sport->port, UARTWATER);
|
||||
txcnt = txcnt >> UARTWATER_TXCNT_OFF;
|
||||
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);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
if (kfifo_is_empty(&tport->xmit_fifo))
|
||||
lpuart32_stop_tx(&sport->port);
|
||||
}
|
||||
|
||||
|
||||
@@ -877,10 +877,10 @@ unlock:
|
||||
static int icom_write(struct uart_port *port)
|
||||
{
|
||||
struct icom_port *icom_port = to_icom_port(port);
|
||||
struct tty_port *tport = &port->state->port;
|
||||
unsigned long data_count;
|
||||
unsigned char cmdReg;
|
||||
unsigned long offset;
|
||||
int temp_tail = port->state->xmit.tail;
|
||||
|
||||
trace(icom_port, "WRITE", 0);
|
||||
|
||||
@@ -890,16 +890,8 @@ static int icom_write(struct uart_port *port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
data_count = 0;
|
||||
while ((port->state->xmit.head != temp_tail) &&
|
||||
(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);
|
||||
}
|
||||
data_count = kfifo_out_peek(&tport->xmit_fifo, icom_port->xmit_buf,
|
||||
XMIT_BUFF_SZ);
|
||||
|
||||
if (data_count) {
|
||||
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)
|
||||
{
|
||||
u16 count, i;
|
||||
struct tty_port *tport = &icom_port->uart_port.state->port;
|
||||
u16 count;
|
||||
|
||||
if (port_int_reg & (INT_XMIT_COMPLETED)) {
|
||||
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);
|
||||
icom_port->uart_port.icount.tx += count;
|
||||
|
||||
for (i=0; i<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);
|
||||
}
|
||||
kfifo_skip_count(&tport->xmit_fifo, count);
|
||||
|
||||
if (!icom_write(&icom_port->uart_port))
|
||||
/* activate write queue */
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* Copyright (C) 2004 Pengutronix
|
||||
*/
|
||||
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.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 */
|
||||
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) {
|
||||
/* Send next char */
|
||||
@@ -531,7 +533,8 @@ static inline void imx_uart_transmit_buffer(struct imx_port *sport)
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@@ -555,26 +558,22 @@ static inline void imx_uart_transmit_buffer(struct imx_port *sport)
|
||||
return;
|
||||
}
|
||||
|
||||
while (!uart_circ_empty(xmit) &&
|
||||
!(imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL)) {
|
||||
/* send xmit->buf[xmit->tail]
|
||||
* out the port here */
|
||||
imx_uart_writel(sport, xmit->buf[xmit->tail], URTX0);
|
||||
uart_xmit_advance(&sport->port, 1);
|
||||
}
|
||||
while (!(imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL) &&
|
||||
uart_fifo_get(&sport->port, &c))
|
||||
imx_uart_writel(sport, c, URTX0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&sport->port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
if (kfifo_is_empty(&tport->xmit_fifo))
|
||||
imx_uart_stop_tx(&sport->port);
|
||||
}
|
||||
|
||||
static void imx_uart_dma_tx_callback(void *data)
|
||||
{
|
||||
struct imx_port *sport = data;
|
||||
struct tty_port *tport = &sport->port.state->port;
|
||||
struct scatterlist *sgl = &sport->tx_sgl[0];
|
||||
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||
unsigned long flags;
|
||||
u32 ucr1;
|
||||
|
||||
@@ -592,10 +591,11 @@ static void imx_uart_dma_tx_callback(void *data)
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
else if (sport->port.rs485.flags & SER_RS485_ENABLED) {
|
||||
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 */
|
||||
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 dma_async_tx_descriptor *desc;
|
||||
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;
|
||||
imx_uart_writel(sport, ucr4, UCR4);
|
||||
|
||||
sport->tx_bytes = uart_circ_chars_pending(xmit);
|
||||
|
||||
if (xmit->tail < xmit->head || xmit->head == 0) {
|
||||
sport->dma_tx_nents = 1;
|
||||
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);
|
||||
}
|
||||
sg_init_table(sgl, ARRAY_SIZE(sport->tx_sgl));
|
||||
sport->tx_bytes = kfifo_len(&tport->xmit_fifo);
|
||||
sport->dma_tx_nents = kfifo_dma_out_prepare(&tport->xmit_fifo, sgl,
|
||||
ARRAY_SIZE(sport->tx_sgl), sport->tx_bytes);
|
||||
|
||||
ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
|
||||
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_param = sport;
|
||||
|
||||
dev_dbg(dev, "TX: prepare to send %lu bytes by DMA.\n",
|
||||
uart_circ_chars_pending(xmit));
|
||||
dev_dbg(dev, "TX: prepare to send %u bytes by DMA.\n", sport->tx_bytes);
|
||||
|
||||
ucr1 = imx_uart_readl(sport, UCR1);
|
||||
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)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct tty_port *tport = &sport->port.state->port;
|
||||
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;
|
||||
|
||||
/*
|
||||
@@ -749,7 +741,7 @@ static void imx_uart_start_tx(struct uart_port *port)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uart_circ_empty(&port->state->xmit) &&
|
||||
if (!kfifo_is_empty(&tport->xmit_fifo) &&
|
||||
!uart_tx_stopped(port))
|
||||
imx_uart_dma_tx(sport);
|
||||
return;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user