mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +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:
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)
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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)) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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))
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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";
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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. */
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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__);
|
||||||
|
@ -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;
|
||||||
|
@ -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. */
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user