From nobody Sun Feb 8 16:50:37 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F8107D091; Tue, 19 Mar 2024 09:54:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710842040; cv=none; b=JfGN/gSYSeoAxZB/+n6Z2ug4trn1TfxHL0h9DKDpBp+u2YLjVaUDkkt3EJIqdIyuxlYXDx9NqS24SJIVoO1Zj9/CeS6t2wG42PNFurISN8iMiMfPc+ZoZMUii3TfbDGAkzXRkUVsPT9g4bhNG5+1mdkP+vKn1W1xwy1ZgK8ERYc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710842040; c=relaxed/simple; bh=e0A4EO6OUKrqvI2n/Yb8Br4HspOFmW8kbPg/wvSZGoA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aX8Ohuh6O1056Zvz7Zapyt7Dz+n0TUenGuSqwdpG49y33tscf31kpvBrXCaj5UCN99hOZ9zdDO/cKO+QhcONVih/kLa+WTpTcjCbjYWdY7fLB5fGiibbGwymsxQF9xGJUHQpVk4loNHG93gZN5dzrcqA21nSs6piCTT5epf09UQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EHCm3eY0; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EHCm3eY0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 54487C43399; Tue, 19 Mar 2024 09:53:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1710842040; bh=e0A4EO6OUKrqvI2n/Yb8Br4HspOFmW8kbPg/wvSZGoA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EHCm3eY01B8b7iIAzqAGELEzpK+C+fYdvWcRIXwQGKz0gUBCSnOePKFO+1ZU492Dq GcbdcUDv63Q6PsRnXuLMcmt8LZs57C+Kcw2tj02BFu3YBAM48JPFXfAbhyHPBPfxKX 07Ln+Wro1RHtbSlte21aNd1bsGuKzYDs+2lKS2CxHzYuSjeNIBGI6QIWYNzEpoSkuI HfIkz0gPV6bmHsnVvNMtCdid8AFBxh1iXyvx32kTMNhkyDiJWn/9pnq/MQd0mDNht0 kOJQHhhl/VhghqN4uYBGDgH+001yEpYwxUJ77uoy4ZjQRdaSBaSziYN7yeuTioUqPF A6IGMZ0/ao+jw== From: "Jiri Slaby (SUSE)" To: linux-serial@vger.kernel.org Cc: linux-kernel@vger.kernel.org, "Jiri Slaby (SUSE)" , Al Cooper , Matthias Brugger , AngeloGioacchino Del Regno , Kumaravel Thiagarajan , Tharun Kumar P , Russell King , Vineet Gupta , Richard Genoud , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Alexander Shiyan , Baruch Siach , "Maciej W. Rozycki" , Shawn Guo , Sascha Hauer , Fabio Estevam , Neil Armstrong , Kevin Hilman , Jerome Brunet , Martin Blumenstingl , Taichi Sugaya , Takao Orito , Bjorn Andersson , Konrad Dybcio , =?UTF-8?q?Pali=20Roh=C3=A1r?= , Michael Ellerman , Nicholas Piggin , Christophe Leroy , "Aneesh Kumar K.V" , "Naveen N. Rao" , Manivannan Sadhasivam , Krzysztof Kozlowski , Alim Akhtar , Laxman Dewangan , Thierry Reding , Jonathan Hunter , Orson Zhai , Baolin Wang , Chunyan Zhang , Patrice Chotard , Maxime Coquelin , Alexandre Torgue , "David S. Miller" , Hammer Hsieh , Peter Korsgaard , Timur Tabi , Michal Simek , Sumit Semwal , =?UTF-8?q?Christian=20K=C3=B6nig?= Subject: [RFT 12/15] tty: serial: switch from circ_buf to kfifo Date: Tue, 19 Mar 2024 10:53:12 +0100 Message-ID: <20240319095315.27624-14-jirislaby@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240319095315.27624-1-jirislaby@kernel.org> References: <20240319095315.27624-1-jirislaby@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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 >=3D 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) Cc: Al Cooper Cc: Matthias Brugger Cc: AngeloGioacchino Del Regno Cc: Kumaravel Thiagarajan Cc: Tharun Kumar P Cc: Russell King Cc: Vineet Gupta Cc: Richard Genoud Cc: Nicolas Ferre Cc: Alexandre Belloni Cc: Claudiu Beznea Cc: Alexander Shiyan Cc: Baruch Siach Cc: "Maciej W. Rozycki" Cc: Shawn Guo Cc: Sascha Hauer Cc: Fabio Estevam Cc: Neil Armstrong Cc: Kevin Hilman Cc: Jerome Brunet Cc: Martin Blumenstingl Cc: Taichi Sugaya Cc: Takao Orito Cc: Bjorn Andersson Cc: Konrad Dybcio Cc: "Pali Roh=C3=A1r" Cc: Michael Ellerman Cc: Nicholas Piggin Cc: Christophe Leroy Cc: "Aneesh Kumar K.V" Cc: "Naveen N. Rao" Cc: Manivannan Sadhasivam Cc: Krzysztof Kozlowski Cc: Alim Akhtar Cc: Laxman Dewangan Cc: Thierry Reding Cc: Jonathan Hunter Cc: Orson Zhai Cc: Baolin Wang Cc: Chunyan Zhang Cc: Patrice Chotard Cc: Maxime Coquelin Cc: Alexandre Torgue Cc: "David S. Miller" Cc: Hammer Hsieh Cc: Peter Korsgaard Cc: Timur Tabi Cc: Michal Simek Cc: Sumit Semwal Cc: "Christian K=C3=B6nig" --- drivers/tty/serial/8250/8250_bcm7271.c | 14 +++--- drivers/tty/serial/8250/8250_core.c | 3 +- drivers/tty/serial/8250/8250_dma.c | 23 ++++++---- drivers/tty/serial/8250/8250_exar.c | 5 ++- drivers/tty/serial/8250/8250_mtk.c | 2 +- drivers/tty/serial/8250/8250_omap.c | 47 +++++++++++++------- drivers/tty/serial/8250/8250_pci1xxxx.c | 50 ++++++++++------------ drivers/tty/serial/8250/8250_port.c | 22 ++++++---- drivers/tty/serial/amba-pl011.c | 46 +++++++++----------- drivers/tty/serial/ar933x_uart.c | 15 +++---- drivers/tty/serial/arc_uart.c | 8 ++-- drivers/tty/serial/atmel_serial.c | 57 +++++++++++++------------ drivers/tty/serial/clps711x.c | 12 +++--- drivers/tty/serial/cpm_uart.c | 20 +++------ drivers/tty/serial/digicolor-usart.c | 12 +++--- drivers/tty/serial/dz.c | 13 +++--- drivers/tty/serial/fsl_linflexuart.c | 17 ++++---- drivers/tty/serial/fsl_lpuart.c | 39 ++++++++--------- drivers/tty/serial/icom.c | 25 +++-------- drivers/tty/serial/imx.c | 54 ++++++++++------------- drivers/tty/serial/ip22zilog.c | 26 ++++++----- drivers/tty/serial/jsm/jsm_cls.c | 29 ++++--------- drivers/tty/serial/jsm/jsm_neo.c | 38 ++++++----------- drivers/tty/serial/max3100.c | 14 +++--- drivers/tty/serial/max310x.c | 35 +++++++-------- drivers/tty/serial/men_z135_uart.c | 26 +++++------ drivers/tty/serial/meson_uart.c | 11 +++-- drivers/tty/serial/milbeaut_usio.c | 15 ++++--- drivers/tty/serial/msm_serial.c | 30 ++++++------- drivers/tty/serial/mvebu-uart.c | 8 ++-- drivers/tty/serial/mxs-auart.c | 23 +++------- drivers/tty/serial/pch_uart.c | 21 +++++---- drivers/tty/serial/pic32_uart.c | 15 +++---- drivers/tty/serial/pmac_zilog.c | 24 +++++------ drivers/tty/serial/qcom_geni_serial.c | 36 ++++++++-------- drivers/tty/serial/rda-uart.c | 17 +++----- drivers/tty/serial/samsung_tty.c | 54 ++++++++++++----------- drivers/tty/serial/sb1250-duart.c | 13 +++--- drivers/tty/serial/sc16is7xx.c | 40 +++++++---------- drivers/tty/serial/sccnxp.c | 16 ++++--- drivers/tty/serial/serial-tegra.c | 43 ++++++++++--------- drivers/tty/serial/serial_core.c | 56 +++++++++--------------- drivers/tty/serial/serial_port.c | 2 +- drivers/tty/serial/sh-sci.c | 51 +++++++++++----------- drivers/tty/serial/sprd_serial.c | 20 ++++----- drivers/tty/serial/st-asc.c | 4 +- drivers/tty/serial/stm32-usart.c | 52 +++++++++------------- drivers/tty/serial/sunhv.c | 35 ++++++++------- drivers/tty/serial/sunplus-uart.c | 16 ++++--- drivers/tty/serial/sunsab.c | 30 +++++++------ drivers/tty/serial/sunsu.c | 15 ++++--- drivers/tty/serial/sunzilog.c | 27 ++++++------ drivers/tty/serial/tegra-tcu.c | 10 +++-- drivers/tty/serial/timbuart.c | 17 +++----- drivers/tty/serial/uartlite.c | 13 +++--- drivers/tty/serial/ucc_uart.c | 20 +++------ drivers/tty/serial/xilinx_uartps.c | 20 ++++----- drivers/tty/serial/zs.c | 13 +++--- include/linux/serial_core.h | 49 +++++++++++++-------- 59 files changed, 688 insertions(+), 780 deletions(-) diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/82= 50/8250_bcm7271.c index 5daa38d9c64e..de270863eb5e 100644 --- a/drivers/tty/serial/8250/8250_bcm7271.c +++ b/drivers/tty/serial/8250/8250_bcm7271.c @@ -413,20 +413,18 @@ static int stop_tx_dma(struct uart_8250_port *p) static int brcmuart_tx_dma(struct uart_8250_port *p) { struct brcmuart_priv *priv =3D p->port.private_data; - struct circ_buf *xmit =3D &p->port.state->xmit; + struct tty_port *tport =3D &p->port.state->port; u32 tx_size; =20 if (uart_tx_stopped(&p->port) || priv->tx_running || - uart_circ_empty(xmit)) { + kfifo_is_empty(&tport->xmit_fifo)) { return 0; } - tx_size =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); =20 priv->dma.tx_err =3D 0; - memcpy(priv->tx_buf, &xmit->buf[xmit->tail], tx_size); - uart_xmit_advance(&p->port, tx_size); + tx_size =3D uart_fifo_out(&p->port, priv->tx_buf, UART_XMIT_SIZE); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&p->port); =20 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 i= sr) struct brcmuart_priv *priv =3D up->private_data; struct device *dev =3D up->dev; struct uart_8250_port *port_8250 =3D up_to_u8250p(up); - struct circ_buf *xmit =3D &port_8250->port.state->xmit; + struct tty_port *tport =3D &port_8250->port.state->port; =20 if (isr & UDMA_INTR_TX_ABORT) { if (priv->tx_running) @@ -548,7 +546,7 @@ static void brcmuart_tx_isr(struct uart_port *up, u32 i= sr) return; } priv->tx_running =3D 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); } =20 diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/= 8250_core.c index b62ad9006780..3a1936b7f05f 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -280,7 +280,8 @@ static void serial8250_backup_timeout(struct timer_list= *t) */ lsr =3D serial_lsr_in(up); if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) && - (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) && + (!kfifo_is_empty(&up->port.state->port.xmit_fifo) || + up->port.x_char) && (lsr & UART_LSR_THRE)) { iir &=3D ~(UART_IIR_ID | UART_IIR_NO_INT); iir |=3D UART_IIR_THRI; diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8= 250_dma.c index 8b2c3f478b17..8a353e3cc3dd 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -15,7 +15,7 @@ static void __dma_tx_complete(void *param) { struct uart_8250_port *p =3D param; struct uart_8250_dma *dma =3D p->dma; - struct circ_buf *xmit =3D &p->port.state->xmit; + struct tty_port *tport =3D &p->port.state->port; unsigned long flags; int ret; =20 @@ -28,7 +28,7 @@ static void __dma_tx_complete(void *param) =20 uart_xmit_advance(&p->port, dma->tx_size); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&p->port); =20 ret =3D serial8250_tx_dma(p); @@ -86,7 +86,7 @@ static void dma_rx_complete(void *param) int serial8250_tx_dma(struct uart_8250_port *p) { struct uart_8250_dma *dma =3D p->dma; - struct circ_buf *xmit =3D &p->port.state->xmit; + struct tty_port *tport =3D &p->port.state->port; struct dma_async_tx_descriptor *desc; struct uart_port *up =3D &p->port; struct scatterlist sg; @@ -103,18 +103,23 @@ int serial8250_tx_dma(struct uart_8250_port *p) uart_xchar_out(up, UART_TX); } =20 - if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) { + if (uart_tx_stopped(&p->port) || kfifo_is_empty(&tport->xmit_fifo)) { /* We have been called from __dma_tx_complete() */ return 0; } =20 - dma->tx_size =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); - serial8250_do_prepare_tx_dma(p); =20 sg_init_table(&sg, 1); - sg_dma_address(&sg) =3D dma->tx_addr + xmit->tail; - sg_dma_len(&sg) =3D dma->tx_size; + /* kfifo can do more than one sg, we don't (quite yet) */ + ret =3D 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 !=3D 1)) + return 0; + + dma->tx_size =3D sg_dma_len(&sg); =20 desc =3D dmaengine_prep_slave_sg(dma->txchan, &sg, 1, DMA_MEM_TO_DEV, @@ -257,7 +262,7 @@ int serial8250_request_dma(struct uart_8250_port *p) =20 /* TX buffer */ dma->tx_addr =3D dma_map_single(dma->txchan->device->dev, - p->port.state->xmit.buf, + p->port.state->port.xmit_buf, UART_XMIT_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(dma->txchan->device->dev, dma->tx_addr)) { diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/= 8250_exar.c index 0440df7de1ed..f89dabfc0f97 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -214,7 +214,7 @@ static void exar_shutdown(struct uart_port *port) { bool tx_complete =3D false; struct uart_8250_port *up =3D up_to_u8250p(port); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; int i =3D 0; u16 lsr; =20 @@ -225,7 +225,8 @@ static void exar_shutdown(struct uart_port *port) else tx_complete =3D false; usleep_range(1000, 1100); - } while (!uart_circ_empty(xmit) && !tx_complete && i++ < 1000); + } while (!kfifo_is_empty(&tport->xmit_fifo) && + !tx_complete && i++ < 1000); =20 serial8250_do_shutdown(port); } diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8= 250_mtk.c index 9ff6bbe9c086..c365a349421a 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -199,7 +199,7 @@ static int mtk8250_startup(struct uart_port *port) =20 if (up->dma) { data->rx_status =3D DMA_RX_START; - uart_circ_clear(&port->state->xmit); + kfifo_reset(&port->state->port.xmit_fifo); } #endif memset(&port->icount, 0, sizeof(port->icount)); diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/= 8250_omap.c index 879e77b30701..c07d924d5add 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -1094,7 +1094,7 @@ static void omap_8250_dma_tx_complete(void *param) { struct uart_8250_port *p =3D param; struct uart_8250_dma *dma =3D p->dma; - struct circ_buf *xmit =3D &p->port.state->xmit; + struct tty_port *tport =3D &p->port.state->port; unsigned long flags; bool en_thri =3D false; struct omap8250_priv *priv =3D p->port.private_data; @@ -1113,10 +1113,10 @@ static void omap_8250_dma_tx_complete(void *param) omap8250_restore_regs(p); } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&p->port); =20 - if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) { + if (!kfifo_is_empty(&tport->xmit_fifo) && !uart_tx_stopped(&p->port)) { int ret; =20 ret =3D 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 =3D p->dma; struct omap8250_priv *priv =3D p->port.private_data; - struct circ_buf *xmit =3D &p->port.state->xmit; + struct tty_port *tport =3D &p->port.state->port; struct dma_async_tx_descriptor *desc; struct scatterlist sg; - unsigned int skip_byte =3D 0; + int skip_byte =3D -1; int ret; =20 if (dma->tx_running) return 0; - if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) { + if (uart_tx_stopped(&p->port) || kfifo_is_empty(&tport->xmit_fifo)) { =20 /* * 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; } =20 - dma->tx_size =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + sg_init_table(&sg, 1); + ret =3D kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1, + UART_XMIT_SIZE, dma->tx_addr); + if (ret !=3D 1) { + serial8250_clear_THRI(p); + return 0; + } + + dma->tx_size =3D sg_dma_len(&sg); + if (priv->habit & OMAP_DMA_TX_KICK) { + unsigned char c; u8 tx_lvl; =20 /* @@ -1189,13 +1199,16 @@ static int omap_8250_tx_dma(struct uart_8250_port *= p) ret =3D -EINVAL; goto err; } - skip_byte =3D 1; + if (!kfifo_get(&tport->xmit_fifo, &c)) { + ret =3D -EINVAL; + goto err; + } + skip_byte =3D 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); } =20 - sg_init_table(&sg, 1); - sg_dma_address(&sg) =3D dma->tx_addr + xmit->tail + skip_byte; - sg_dma_len(&sg) =3D dma->tx_size - skip_byte; - desc =3D dmaengine_prep_slave_sg(dma->txchan, &sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { @@ -1218,11 +1231,13 @@ static int omap_8250_tx_dma(struct uart_8250_port *= p) dma->tx_err =3D 0; =20 serial8250_clear_THRI(p); - if (skip_byte) - serial_out(p, UART_TX, xmit->buf[xmit->tail]); - return 0; + ret =3D 0; + goto out_skip; err: dma->tx_err =3D 1; +out_skip: + if (skip_byte >=3D 0) + serial_out(p, UART_TX, skip_byte); return ret; } =20 @@ -1311,7 +1326,7 @@ static int omap_8250_dma_handle_irq(struct uart_port = *port) serial8250_modem_status(up); if (status & UART_LSR_THRE && up->dma->tx_err) { if (uart_tx_stopped(&up->port) || - uart_circ_empty(&up->port.state->xmit)) { + kfifo_is_empty(&up->port.state->port.xmit_fifo)) { up->dma->tx_err =3D 0; serial8250_tx_chars(up); } else { diff --git a/drivers/tty/serial/8250/8250_pci1xxxx.c b/drivers/tty/serial/8= 250/8250_pci1xxxx.c index 2fbb5851f788..d3930bf32fe4 100644 --- a/drivers/tty/serial/8250/8250_pci1xxxx.c +++ b/drivers/tty/serial/8250/8250_pci1xxxx.c @@ -382,10 +382,10 @@ static void pci1xxxx_rx_burst(struct uart_port *port,= u32 uart_status) } =20 static void pci1xxxx_process_write_data(struct uart_port *port, - struct circ_buf *xmit, int *data_empty_count, u32 *valid_byte_count) { + struct tty_port *tport =3D &port->state->port; u32 valid_burst_count =3D *valid_byte_count / UART_BURST_SIZE; =20 /* @@ -395,41 +395,36 @@ static void pci1xxxx_process_write_data(struct uart_p= ort *port, * one byte at a time. */ while (valid_burst_count) { + u32 c; + if (*data_empty_count - UART_BURST_SIZE < 0) break; - if (xmit->tail > (UART_XMIT_SIZE - UART_BURST_SIZE)) + if (kfifo_len(&tport->xmit_fifo) < UART_BURST_SIZE) + break; + if (WARN_ON(kfifo_out(&tport->xmit_fifo, (u8 *)&c, sizeof(c)) !=3D + sizeof(c))) break; - writel(*(unsigned int *)&xmit->buf[xmit->tail], - port->membase + UART_TX_BURST_FIFO); + writel(c, port->membase + UART_TX_BURST_FIFO); *valid_byte_count -=3D UART_BURST_SIZE; *data_empty_count -=3D UART_BURST_SIZE; valid_burst_count -=3D UART_BYTE_SIZE; - - xmit->tail =3D (xmit->tail + UART_BURST_SIZE) & - (UART_XMIT_SIZE - 1); } =20 while (*valid_byte_count) { - if (*data_empty_count - UART_BYTE_SIZE < 0) + u8 c; + + if (!kfifo_get(&tport->xmit_fifo, &c)) break; - writeb(xmit->buf[xmit->tail], port->membase + - UART_TX_BYTE_FIFO); + writeb(c, port->membase + UART_TX_BYTE_FIFO); *data_empty_count -=3D UART_BYTE_SIZE; *valid_byte_count -=3D UART_BYTE_SIZE; =20 - /* - * When the tail of the circular buffer is reached, the next - * byte is transferred to the beginning of the buffer. - */ - xmit->tail =3D (xmit->tail + UART_BYTE_SIZE) & - (UART_XMIT_SIZE - 1); - /* * If there are any pending burst count, data is handled by * transmitting DWORDs at a time. */ - if (valid_burst_count && (xmit->tail < - (UART_XMIT_SIZE - UART_BURST_SIZE))) + if (valid_burst_count && + kfifo_len(&tport->xmit_fifo) >=3D UART_BURST_SIZE) break; } } @@ -437,11 +432,9 @@ static void pci1xxxx_process_write_data(struct uart_po= rt *port, static void pci1xxxx_tx_burst(struct uart_port *port, u32 uart_status) { struct uart_8250_port *up =3D up_to_u8250p(port); + struct tty_port *tport =3D &port->state->port; u32 valid_byte_count; int data_empty_count; - struct circ_buf *xmit; - - xmit =3D &port->state->xmit; =20 if (port->x_char) { writeb(port->x_char, port->membase + UART_TX); @@ -450,25 +443,25 @@ static void pci1xxxx_tx_burst(struct uart_port *port,= u32 uart_status) return; } =20 - if ((uart_tx_stopped(port)) || (uart_circ_empty(xmit))) { + if ((uart_tx_stopped(port)) || kfifo_is_empty(&tport->xmit_fifo)) { port->ops->stop_tx(port); } else { data_empty_count =3D (pci1xxxx_read_burst_status(port) & UART_BST_STAT_TX_COUNT_MASK) >> 8; do { - valid_byte_count =3D uart_circ_chars_pending(xmit); + valid_byte_count =3D kfifo_len(&tport->xmit_fifo); =20 - pci1xxxx_process_write_data(port, xmit, + pci1xxxx_process_write_data(port, &data_empty_count, &valid_byte_count); =20 port->icount.tx++; - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) break; } while (data_empty_count && valid_byte_count); } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 /* @@ -476,7 +469,8 @@ static void pci1xxxx_tx_burst(struct uart_port *port, u= 32 uart_status) * the HW can go idle. So we get here once again with empty FIFO and * disable the interrupt and RPM in __stop_tx() */ - if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM)) + if (kfifo_is_empty(&tport->xmit_fifo) && + !(up->capabilities & UART_CAP_RPM)) port->ops->stop_tx(port); } =20 diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/= 8250_port.c index fc9dd5d45295..0c19451d0332 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1630,7 +1630,7 @@ static void serial8250_start_tx(struct uart_port *por= t) /* Port locked to synchronize UART_IER access against the console. */ lockdep_assert_held_once(&port->lock); =20 - if (!port->x_char && uart_circ_empty(&port->state->xmit)) + if (!port->x_char && kfifo_is_empty(&port->state->port.xmit_fifo)) return; =20 serial8250_rpm_get_tx(up); @@ -1778,7 +1778,7 @@ EXPORT_SYMBOL_GPL(serial8250_rx_chars); void serial8250_tx_chars(struct uart_8250_port *up) { struct uart_port *port =3D &up->port; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; int count; =20 if (port->x_char) { @@ -1789,14 +1789,19 @@ void serial8250_tx_chars(struct uart_8250_port *up) serial8250_stop_tx(port); return; } - if (uart_circ_empty(xmit)) { + if (kfifo_is_empty(&tport->xmit_fifo)) { __stop_tx(up); return; } =20 count =3D up->tx_loadsz; do { - serial_out(up, UART_TX, xmit->buf[xmit->tail]); + unsigned char c; + + if (!uart_fifo_get(port, &c)) + break; + + serial_out(up, UART_TX, c); if (up->bugs & UART_BUG_TXRACE) { /* * The Aspeed BMC virtual UARTs have a bug where data @@ -1809,9 +1814,7 @@ void serial8250_tx_chars(struct uart_8250_port *up) */ serial_in(up, UART_SCR); } - uart_xmit_advance(port, 1); - if (uart_circ_empty(xmit)) - break; + if ((up->capabilities & UART_CAP_HFIFO) && !uart_lsr_tx_empty(serial_in(up, UART_LSR))) break; @@ -1821,7 +1824,7 @@ void serial8250_tx_chars(struct uart_8250_port *up) break; } while (--count > 0); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 /* @@ -1829,7 +1832,8 @@ void serial8250_tx_chars(struct uart_8250_port *up) * HW can go idle. So we get here once again with empty FIFO and disable * the interrupt and RPM in __stop_tx() */ - if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM)) + if (kfifo_is_empty(&tport->xmit_fifo) && + !(up->capabilities & UART_CAP_RPM)) __stop_tx(up); } EXPORT_SYMBOL_GPL(serial8250_tx_chars); diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl01= 1.c index 2fa3fb30dc6c..51b202eb8296 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -535,6 +535,7 @@ static void pl011_start_tx_pio(struct uart_amba_port *u= ap); static void pl011_dma_tx_callback(void *data) { struct uart_amba_port *uap =3D data; + struct tty_port *tport =3D &uap->port.state->port; struct pl011_dmatx_data *dmatx =3D &uap->dmatx; unsigned long flags; u16 dmacr; @@ -558,7 +559,7 @@ static void pl011_dma_tx_callback(void *data) * get further refills (hence we check dmacr). */ if (!(dmacr & UART011_TXDMAE) || uart_tx_stopped(&uap->port) || - uart_circ_empty(&uap->port.state->xmit)) { + kfifo_is_empty(&tport->xmit_fifo)) { uap->dmatx.queued =3D false; uart_port_unlock_irqrestore(&uap->port, flags); return; @@ -588,7 +589,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *u= ap) struct dma_chan *chan =3D dmatx->chan; struct dma_device *dma_dev =3D chan->device; struct dma_async_tx_descriptor *desc; - struct circ_buf *xmit =3D &uap->port.state->xmit; + struct tty_port *tport =3D &uap->port.state->port; unsigned int count; =20 /* @@ -597,7 +598,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *u= ap) * the standard interrupt handling. This ensures that we * issue a uart_write_wakeup() at the appropriate time. */ - count =3D uart_circ_chars_pending(xmit); + count =3D kfifo_len(&tport->xmit_fifo); if (count < (uap->fifosize >> 1)) { uap->dmatx.queued =3D false; return 0; @@ -613,21 +614,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *= uap) if (count > PL011_DMA_BUFFER_SIZE) count =3D PL011_DMA_BUFFER_SIZE; =20 - if (xmit->tail < xmit->head) { - memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], count); - } else { - size_t first =3D UART_XMIT_SIZE - xmit->tail; - size_t second; - - if (first > count) - first =3D count; - second =3D count - first; - - memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], first); - if (second) - memcpy(&dmatx->buf[first], &xmit->buf[0], second); - } - + count =3D kfifo_out_peek(&tport->xmit_fifo, dmatx->buf, count); dmatx->len =3D count; dmatx->dma =3D dma_map_single(dma_dev->dev, dmatx->buf, count, DMA_TO_DEVICE); @@ -670,7 +657,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *u= ap) */ uart_xmit_advance(&uap->port, count); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&uap->port); =20 return 1; @@ -1454,7 +1441,7 @@ static bool pl011_tx_char(struct uart_amba_port *uap,= unsigned char c, /* Returns true if tx interrupts have to be (kept) enabled */ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq) { - struct circ_buf *xmit =3D &uap->port.state->xmit; + struct tty_port *tport =3D &uap->port.state->port; int count =3D uap->fifosize >> 1; =20 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 =3D 0; --count; } - if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(&uap->port)) { pl011_stop_tx(&uap->port); return false; } @@ -1472,20 +1459,25 @@ static bool pl011_tx_chars(struct uart_amba_port *u= ap, bool from_irq) if (pl011_dma_tx_irq(uap)) return true; =20 - do { + while (1) { + unsigned char c; + if (likely(from_irq) && count-- =3D=3D 0) break; =20 - if (!pl011_tx_char(uap, xmit->buf[xmit->tail], from_irq)) + if (!kfifo_peek(&tport->xmit_fifo, &c)) + break; + + if (!pl011_tx_char(uap, c, from_irq)) break; =20 - xmit->tail =3D (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - } while (!uart_circ_empty(xmit)); + kfifo_skip(&tport->xmit_fifo); + } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&uap->port); =20 - if (uart_circ_empty(xmit)) { + if (kfifo_is_empty(&tport->xmit_fifo)) { pl011_stop_tx(&uap->port); return false; } diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_u= art.c index 7790cbc57391..f2836ecc5c19 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -390,7 +390,7 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_por= t *up) =20 static void ar933x_uart_tx_chars(struct ar933x_uart_port *up) { - struct circ_buf *xmit =3D &up->port.state->xmit; + struct tty_port *tport =3D &up->port.state->port; struct serial_rs485 *rs485conf =3D &up->port.rs485; int count; bool half_duplex_send =3D false; @@ -399,7 +399,7 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_por= t *up) return; =20 if ((rs485conf->flags & SER_RS485_ENABLED) && - (up->port.x_char || !uart_circ_empty(xmit))) { + (up->port.x_char || !kfifo_is_empty(&tport->xmit_fifo))) { ar933x_uart_stop_rx_interrupt(up); gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_ON_SE= ND)); half_duplex_send =3D true; @@ -408,6 +408,7 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_por= t *up) count =3D up->port.fifosize; do { unsigned int rdata; + unsigned char c; =20 rdata =3D ar933x_uart_read(up, AR933X_UART_DATA_REG); if ((rdata & AR933X_UART_DATA_TX_CSR) =3D=3D 0) @@ -420,18 +421,16 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_p= ort *up) continue; } =20 - if (uart_circ_empty(xmit)) + if (!uart_fifo_get(&up->port, &c)) break; =20 - ar933x_uart_putc(up, xmit->buf[xmit->tail]); - - uart_xmit_advance(&up->port, 1); + ar933x_uart_putc(up, c); } while (--count > 0); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&up->port); =20 - if (!uart_circ_empty(xmit)) { + if (!kfifo_is_empty(&tport->xmit_fifo)) { ar933x_uart_start_tx_interrupt(up); } else if (half_duplex_send) { ar933x_uart_wait_tx_complete(up); diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 1aa5b2b49c26..5c4895d154c0 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -155,7 +155,7 @@ static unsigned int arc_serial_tx_empty(struct uart_por= t *port) */ static void arc_serial_tx_chars(struct uart_port *port) { - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; int sent =3D 0; unsigned char ch; =20 @@ -164,9 +164,7 @@ static void arc_serial_tx_chars(struct uart_port *port) port->icount.tx++; port->x_char =3D 0; sent =3D 1; - } else if (!uart_circ_empty(xmit)) { - ch =3D xmit->buf[xmit->tail]; - uart_xmit_advance(port, 1); + } else if (uart_fifo_get(port, &ch)) { while (!(UART_GET_STATUS(port) & TXEMPTY)) cpu_relax(); UART_SET_DATA(port, ch); @@ -177,7 +175,7 @@ static void arc_serial_tx_chars(struct uart_port *port) * If num chars in xmit buffer are too few, ask tty layer for more. * By Hard ISR to schedule processing in software interrupt part */ - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 if (sent) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_s= erial.c index 85667f709515..5bb5e4303754 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -857,7 +857,7 @@ static void atmel_complete_tx_dma(void *arg) { struct atmel_uart_port *atmel_port =3D arg; struct uart_port *port =3D &atmel_port->uart; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; struct dma_chan *chan =3D atmel_port->chan_tx; unsigned long flags; =20 @@ -873,15 +873,15 @@ static void atmel_complete_tx_dma(void *arg) atmel_port->desc_tx =3D NULL; spin_unlock(&atmel_port->lock_tx); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 /* - * xmit is a circular buffer so, if we have just send data from - * xmit->tail to the end of xmit->buf, now we have to transmit the - * remaining data from the beginning of xmit->buf to xmit->head. + * xmit is a circular buffer so, if we have just send data from the + * tail to the end, now we have to transmit the remaining data from the + * beginning to the head. */ - if (!uart_circ_empty(xmit)) + if (!kfifo_is_empty(&tport->xmit_fifo)) atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx); else if (atmel_uart_is_half_duplex(port)) { /* @@ -919,18 +919,18 @@ static void atmel_release_tx_dma(struct uart_port *po= rt) static void atmel_tx_dma(struct uart_port *port) { struct atmel_uart_port *atmel_port =3D to_atmel_uart_port(port); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; struct dma_chan *chan =3D atmel_port->chan_tx; struct dma_async_tx_descriptor *desc; struct scatterlist sgl[2], *sg, *sg_tx =3D &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; =20 /* Make sure we have an idle channel */ if (atmel_port->desc_tx !=3D NULL) return; =20 - if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) { + if (!kfifo_is_empty(&tport->xmit_fifo) && !uart_tx_stopped(port)) { /* * DMA is idle now. * Port xmit buffer is already mapped, @@ -940,9 +940,8 @@ static void atmel_tx_dma(struct uart_port *port) * Take the port lock to get a * consistent xmit buffer state. */ - tx_len =3D CIRC_CNT_TO_END(xmit->head, - xmit->tail, - UART_XMIT_SIZE); + tx_len =3D kfifo_out_linear(&tport->xmit_fifo, &tail, + UART_XMIT_SIZE); =20 if (atmel_port->fifo_size) { /* multi data mode */ @@ -956,7 +955,7 @@ static void atmel_tx_dma(struct uart_port *port) =20 sg_init_table(sgl, 2); sg_len =3D 0; - phys_addr =3D sg_dma_address(sg_tx) + xmit->tail; + phys_addr =3D sg_dma_address(sg_tx) + tail; if (part1_len) { sg =3D &sgl[sg_len++]; sg_dma_address(sg) =3D phys_addr; @@ -973,7 +972,7 @@ static void atmel_tx_dma(struct uart_port *port) =20 /* * save tx_len so atmel_complete_tx_dma() will increase - * xmit->tail correctly + * tail correctly */ atmel_port->tx_len =3D tx_len; =20 @@ -1003,13 +1002,14 @@ static void atmel_tx_dma(struct uart_port *port) dma_async_issue_pending(chan); } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); } =20 static int atmel_prepare_tx_dma(struct uart_port *port) { struct atmel_uart_port *atmel_port =3D to_atmel_uart_port(port); + struct tty_port *tport =3D &port->state->port; struct device *mfd_dev =3D port->dev->parent; dma_cap_mask_t mask; struct dma_slave_config config; @@ -1031,11 +1031,11 @@ static int atmel_prepare_tx_dma(struct uart_port *p= ort) spin_lock_init(&atmel_port->lock_tx); sg_init_table(&atmel_port->sg_tx, 1); /* UART circular tx buffer is an aligned page. */ - BUG_ON(!PAGE_ALIGNED(port->state->xmit.buf)); + BUG_ON(!PAGE_ALIGNED(tport->xmit_buf)); sg_set_page(&atmel_port->sg_tx, - virt_to_page(port->state->xmit.buf), + virt_to_page(tport->xmit_buf), UART_XMIT_SIZE, - offset_in_page(port->state->xmit.buf)); + offset_in_page(tport->xmit_buf)); nent =3D dma_map_sg(port->dev, &atmel_port->sg_tx, 1, @@ -1047,7 +1047,7 @@ static int atmel_prepare_tx_dma(struct uart_port *por= t) } else { dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__, sg_dma_len(&atmel_port->sg_tx), - port->state->xmit.buf, + tport->xmit_buf, &sg_dma_address(&atmel_port->sg_tx)); } =20 @@ -1459,9 +1459,8 @@ static void atmel_release_tx_pdc(struct uart_port *po= rt) static void atmel_tx_pdc(struct uart_port *port) { struct atmel_uart_port *atmel_port =3D to_atmel_uart_port(port); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; struct atmel_dma_buffer *pdc =3D &atmel_port->pdc_tx; - int count; =20 /* nothing left to transmit? */ if (atmel_uart_readl(port, ATMEL_PDC_TCR)) @@ -1474,17 +1473,19 @@ static void atmel_tx_pdc(struct uart_port *port) /* disable PDC transmit */ atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS); =20 - if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) { + if (!kfifo_is_empty(&tport->xmit_fifo) && !uart_tx_stopped(port)) { + unsigned int count, tail; + dma_sync_single_for_device(port->dev, pdc->dma_addr, pdc->dma_size, DMA_TO_DEVICE); =20 - count =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + count =3D kfifo_out_linear(&tport->xmit_fifo, &tail, + UART_XMIT_SIZE); pdc->ofs =3D count; =20 - atmel_uart_writel(port, ATMEL_PDC_TPR, - pdc->dma_addr + xmit->tail); + atmel_uart_writel(port, ATMEL_PDC_TPR, pdc->dma_addr + tail); atmel_uart_writel(port, ATMEL_PDC_TCR, count); /* re-enable PDC transmit */ atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN); @@ -1498,7 +1499,7 @@ static void atmel_tx_pdc(struct uart_port *port) } } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); } =20 @@ -1506,9 +1507,9 @@ static int atmel_prepare_tx_pdc(struct uart_port *por= t) { struct atmel_uart_port *atmel_port =3D to_atmel_uart_port(port); struct atmel_dma_buffer *pdc =3D &atmel_port->pdc_tx; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; =20 - pdc->buf =3D xmit->buf; + pdc->buf =3D tport->xmit_buf; pdc->dma_addr =3D dma_map_single(port->dev, pdc->buf, UART_XMIT_SIZE, diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index 7927725b8957..30425a3d19fb 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -146,7 +146,8 @@ static irqreturn_t uart_clps711x_int_tx(int irq, void *= dev_id) { struct uart_port *port =3D dev_id; struct clps711x_port *s =3D dev_get_drvdata(port->dev); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; + unsigned char c; =20 if (port->x_char) { writew(port->x_char, port->membase + UARTDR_OFFSET); @@ -155,7 +156,7 @@ static irqreturn_t uart_clps711x_int_tx(int irq, void *= dev_id) return IRQ_HANDLED; } =20 - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) { if (s->tx_enabled) { disable_irq_nosync(port->irq); s->tx_enabled =3D 0; @@ -163,18 +164,17 @@ static irqreturn_t uart_clps711x_int_tx(int irq, void= *dev_id) return IRQ_HANDLED; } =20 - while (!uart_circ_empty(xmit)) { + while (uart_fifo_get(port, &c)) { u32 sysflg =3D 0; =20 - writew(xmit->buf[xmit->tail], port->membase + UARTDR_OFFSET); - uart_xmit_advance(port, 1); + writew(c, port->membase + UARTDR_OFFSET); =20 regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); if (sysflg & SYSFLG_UTXFF) break; } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 return IRQ_HANDLED; diff --git a/drivers/tty/serial/cpm_uart.c b/drivers/tty/serial/cpm_uart.c index df56c6c5afd0..a927478f581d 100644 --- a/drivers/tty/serial/cpm_uart.c +++ b/drivers/tty/serial/cpm_uart.c @@ -648,7 +648,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) int count; struct uart_cpm_port *pinfo =3D container_of(port, struct uart_cpm_port, port); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; =20 /* Handle xon/xoff */ if (port->x_char) { @@ -673,7 +673,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) return 1; } =20 - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) { cpm_uart_stop_tx(port); return 0; } @@ -681,16 +681,10 @@ static int cpm_uart_tx_pump(struct uart_port *port) /* Pick next descriptor and fill from buffer */ bdp =3D pinfo->tx_cur; =20 - while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) && !uart_circ_empty(xmit)) { - count =3D 0; + while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) && + !kfifo_is_empty(&tport->xmit_fifo)) { p =3D cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo); - while (count < pinfo->tx_fifosize) { - *p++ =3D xmit->buf[xmit->tail]; - uart_xmit_advance(port, 1); - count++; - if (uart_circ_empty(xmit)) - break; - } + count =3D uart_fifo_out(port, p, pinfo->tx_fifosize); out_be16(&bdp->cbd_datlen, count); setbits16(&bdp->cbd_sc, BD_SC_READY); /* Get next BD. */ @@ -701,10 +695,10 @@ static int cpm_uart_tx_pump(struct uart_port *port) } pinfo->tx_cur =3D bdp; =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 - if (uart_circ_empty(xmit)) { + if (kfifo_is_empty(&tport->xmit_fifo)) { cpm_uart_stop_tx(port); return 0; } diff --git a/drivers/tty/serial/digicolor-usart.c b/drivers/tty/serial/digi= color-usart.c index e419c4bde8b7..2ccd13cc0a89 100644 --- a/drivers/tty/serial/digicolor-usart.c +++ b/drivers/tty/serial/digicolor-usart.c @@ -179,8 +179,9 @@ static void digicolor_uart_rx(struct uart_port *port) =20 static void digicolor_uart_tx(struct uart_port *port) { - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; unsigned long flags; + unsigned char c; =20 if (digicolor_uart_tx_full(port)) return; @@ -194,20 +195,19 @@ static void digicolor_uart_tx(struct uart_port *port) goto out; } =20 - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) { digicolor_uart_stop_tx(port); goto out; } =20 - while (!uart_circ_empty(xmit)) { - writeb(xmit->buf[xmit->tail], port->membase + UA_EMI_REC); - uart_xmit_advance(port, 1); + while (uart_fifo_get(port, &c)) { + writeb(c, port->membase + UA_EMI_REC); =20 if (digicolor_uart_tx_full(port)) break; } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 out: diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c index 6df7af9edc1c..eba91daedef8 100644 --- a/drivers/tty/serial/dz.c +++ b/drivers/tty/serial/dz.c @@ -252,13 +252,13 @@ static inline void dz_receive_chars(struct dz_mux *mu= x) static inline void dz_transmit_chars(struct dz_mux *mux) { struct dz_port *dport =3D &mux->dport[0]; - struct circ_buf *xmit; + struct tty_port *tport; unsigned char tmp; u16 status; =20 status =3D dz_in(dport, DZ_CSR); dport =3D &mux->dport[LINE(status)]; - xmit =3D &dport->port.state->xmit; + tport =3D &dport->port.state->port; =20 if (dport->port.x_char) { /* XON/XOFF chars */ dz_out(dport, DZ_TDR, dport->port.x_char); @@ -267,7 +267,8 @@ static inline void dz_transmit_chars(struct dz_mux *mux) return; } /* If nothing to do or stopped or hardware stopped. */ - if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { + if (uart_tx_stopped(&dport->port) || + !uart_fifo_get(&dport->port, &tmp)) { uart_port_lock(&dport->port); dz_stop_tx(&dport->port); uart_port_unlock(&dport->port); @@ -278,15 +279,13 @@ static inline void dz_transmit_chars(struct dz_mux *m= ux) * If something to do... (remember the dz has no output fifo, * so we go one char at a time) :-< */ - tmp =3D xmit->buf[xmit->tail]; dz_out(dport, DZ_TDR, tmp); - uart_xmit_advance(&dport->port, 1); =20 - if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < DZ_WAKEUP_CHARS) uart_write_wakeup(&dport->port); =20 /* Are we are done. */ - if (uart_circ_empty(xmit)) { + if (kfifo_is_empty(&tport->xmit_fifo)) { uart_port_lock(&dport->port); dz_stop_tx(&dport->port); uart_port_unlock(&dport->port); diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_= linflexuart.c index 5426322b5f0c..e972df4b188d 100644 --- a/drivers/tty/serial/fsl_linflexuart.c +++ b/drivers/tty/serial/fsl_linflexuart.c @@ -174,17 +174,18 @@ static void linflex_put_char(struct uart_port *sport,= unsigned char c) =20 static inline void linflex_transmit_buffer(struct uart_port *sport) { - struct circ_buf *xmit =3D &sport->state->xmit; + struct tty_port *tport =3D &sport->state->port; + unsigned char c; =20 - while (!uart_circ_empty(xmit)) { - linflex_put_char(sport, xmit->buf[xmit->tail]); - uart_xmit_advance(sport, 1); + while (uart_fifo_get(sport, &c)) { + linflex_put_char(sport, c); + sport->icount.tx++; } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(sport); =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) linflex_stop_tx(sport); } =20 @@ -200,7 +201,7 @@ static void linflex_start_tx(struct uart_port *port) static irqreturn_t linflex_txint(int irq, void *dev_id) { struct uart_port *sport =3D dev_id; - struct circ_buf *xmit =3D &sport->state->xmit; + struct tty_port *tport =3D &sport->state->port; unsigned long flags; =20 uart_port_lock_irqsave(sport, &flags); @@ -210,7 +211,7 @@ static irqreturn_t linflex_txint(int irq, void *dev_id) goto out; } =20 - if (uart_circ_empty(xmit) || uart_tx_stopped(sport)) { + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(sport)) { linflex_stop_tx(sport); goto out; } diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuar= t.c index bbcbc91482af..ae5e1ecc48fc 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -7,6 +7,7 @@ =20 #include #include +#include #include #include #include @@ -473,7 +474,7 @@ static void lpuart32_stop_rx(struct uart_port *port) =20 static void lpuart_dma_tx(struct lpuart_port *sport) { - struct circ_buf *xmit =3D &sport->port.state->xmit; + struct tty_port *tport =3D &sport->port.state->port; struct scatterlist *sgl =3D sport->tx_sgl; struct device *dev =3D sport->port.dev; struct dma_chan *chan =3D sport->dma_tx_chan; @@ -482,18 +483,10 @@ static void lpuart_dma_tx(struct lpuart_port *sport) if (sport->dma_tx_in_progress) return; =20 - sport->dma_tx_bytes =3D uart_circ_chars_pending(xmit); - - if (xmit->tail < xmit->head || xmit->head =3D=3D 0) { - sport->dma_tx_nents =3D 1; - sg_init_one(sgl, xmit->buf + xmit->tail, sport->dma_tx_bytes); - } else { - sport->dma_tx_nents =3D 2; - sg_init_table(sgl, 2); - sg_set_buf(sgl, xmit->buf + xmit->tail, - UART_XMIT_SIZE - xmit->tail); - sg_set_buf(sgl + 1, xmit->buf, xmit->head); - } + sg_init_table(sgl, ARRAY_SIZE(sport->tx_sgl)); + sport->dma_tx_bytes =3D kfifo_len(&tport->xmit_fifo); + sport->dma_tx_nents =3D kfifo_dma_out_prepare(&tport->xmit_fifo, sgl, + ARRAY_SIZE(sport->tx_sgl), sport->dma_tx_bytes); =20 ret =3D dma_map_sg(chan->device->dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); @@ -521,14 +514,15 @@ static void lpuart_dma_tx(struct lpuart_port *sport) =20 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); } =20 static void lpuart_dma_tx_complete(void *arg) { struct lpuart_port *sport =3D arg; struct scatterlist *sgl =3D &sport->tx_sgl[0]; - struct circ_buf *xmit =3D &sport->port.state->xmit; + struct tty_port *tport =3D &sport->port.state->port; struct dma_chan *chan =3D sport->dma_tx_chan; unsigned long flags; =20 @@ -545,7 +539,7 @@ static void lpuart_dma_tx_complete(void *arg) sport->dma_tx_in_progress =3D false; uart_port_unlock_irqrestore(&sport->port, flags); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&sport->port); =20 if (waitqueue_active(&sport->dma_wait)) { @@ -756,8 +750,9 @@ static inline void lpuart_transmit_buffer(struct lpuart= _port *sport) =20 static inline void lpuart32_transmit_buffer(struct lpuart_port *sport) { - struct circ_buf *xmit =3D &sport->port.state->xmit; + struct tty_port *tport =3D &sport->port.state->port; unsigned long txcnt; + unsigned char c; =20 if (sport->port.x_char) { lpuart32_write(&sport->port, sport->port.x_char, UARTDATA); @@ -774,18 +769,18 @@ static inline void lpuart32_transmit_buffer(struct lp= uart_port *sport) txcnt =3D lpuart32_read(&sport->port, UARTWATER); txcnt =3D txcnt >> UARTWATER_TXCNT_OFF; txcnt &=3D UARTWATER_COUNT_MASK; - while (!uart_circ_empty(xmit) && (txcnt < sport->txfifo_size)) { - lpuart32_write(&sport->port, xmit->buf[xmit->tail], UARTDATA); - uart_xmit_advance(&sport->port, 1); + while (txcnt < sport->txfifo_size && + uart_fifo_get(&sport->port, &c)) { + lpuart32_write(&sport->port, c, UARTDATA); txcnt =3D lpuart32_read(&sport->port, UARTWATER); txcnt =3D txcnt >> UARTWATER_TXCNT_OFF; txcnt &=3D UARTWATER_COUNT_MASK; } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&sport->port); =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) lpuart32_stop_tx(&sport->port); } =20 diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c index a75eafbcbea3..29e42831df39 100644 --- a/drivers/tty/serial/icom.c +++ b/drivers/tty/serial/icom.c @@ -877,10 +877,10 @@ static void shutdown(struct icom_port *icom_port) static int icom_write(struct uart_port *port) { struct icom_port *icom_port =3D to_icom_port(port); + struct tty_port *tport =3D &port->state->port; unsigned long data_count; unsigned char cmdReg; unsigned long offset; - int temp_tail =3D port->state->xmit.tail; =20 trace(icom_port, "WRITE", 0); =20 @@ -890,16 +890,8 @@ static int icom_write(struct uart_port *port) return 0; } =20 - data_count =3D 0; - while ((port->state->xmit.head !=3D temp_tail) && - (data_count <=3D XMIT_BUFF_SZ)) { - - icom_port->xmit_buf[data_count++] =3D - port->state->xmit.buf[temp_tail]; - - temp_tail++; - temp_tail &=3D (UART_XMIT_SIZE - 1); - } + data_count =3D kfifo_out_peek(&tport->xmit_fifo, icom_port->xmit_buf, + XMIT_BUFF_SZ); =20 if (data_count) { icom_port->statStg->xmit[0].flags =3D @@ -956,7 +948,8 @@ static inline void check_modem_status(struct icom_port = *icom_port) =20 static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port) { - u16 count, i; + struct tty_port *tport =3D &icom_port->uart_port.state->port; + u16 count; =20 if (port_int_reg & (INT_XMIT_COMPLETED)) { trace(icom_port, "XMIT_COMPLETE", 0); @@ -968,13 +961,7 @@ static void xmit_interrupt(u16 port_int_reg, struct ic= om_port *icom_port) count =3D le16_to_cpu(icom_port->statStg->xmit[0].leLength); icom_port->uart_port.icount.tx +=3D count; =20 - for (i=3D0; iuart_port.state->xmit); i++) { - - icom_port->uart_port.state->xmit.tail++; - icom_port->uart_port.state->xmit.tail &=3D - (UART_XMIT_SIZE - 1); - } + kfifo_skip_count(&tport->xmit_fifo, count); =20 if (!icom_write(&icom_port->uart_port)) /* activate write queue */ diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index e14813250616..56b76a221082 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -8,6 +8,7 @@ * Copyright (C) 2004 Pengutronix */ =20 +#include #include #include #include @@ -521,7 +522,8 @@ static void imx_uart_dma_tx(struct imx_port *sport); /* called with port.lock taken and irqs off */ static inline void imx_uart_transmit_buffer(struct imx_port *sport) { - struct circ_buf *xmit =3D &sport->port.state->xmit; + struct tty_port *tport =3D &sport->port.state->port; + unsigned char c; =20 if (sport->port.x_char) { /* Send next char */ @@ -531,7 +533,8 @@ static inline void imx_uart_transmit_buffer(struct imx_= port *sport) return; } =20 - if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { + if (kfifo_is_empty(&tport->xmit_fifo) || + uart_tx_stopped(&sport->port)) { imx_uart_stop_tx(&sport->port); return; } @@ -555,26 +558,22 @@ static inline void imx_uart_transmit_buffer(struct im= x_port *sport) return; } =20 - while (!uart_circ_empty(xmit) && - !(imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL)) { - /* send xmit->buf[xmit->tail] - * out the port here */ - imx_uart_writel(sport, xmit->buf[xmit->tail], URTX0); - uart_xmit_advance(&sport->port, 1); - } + while (!(imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL) && + uart_fifo_get(&sport->port, &c)) + imx_uart_writel(sport, c, URTX0); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&sport->port); =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) imx_uart_stop_tx(&sport->port); } =20 static void imx_uart_dma_tx_callback(void *data) { struct imx_port *sport =3D data; + struct tty_port *tport =3D &sport->port.state->port; struct scatterlist *sgl =3D &sport->tx_sgl[0]; - struct circ_buf *xmit =3D &sport->port.state->xmit; unsigned long flags; u32 ucr1; =20 @@ -592,10 +591,11 @@ static void imx_uart_dma_tx_callback(void *data) =20 sport->dma_is_txing =3D 0; =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&sport->port); =20 - if (!uart_circ_empty(xmit) && !uart_tx_stopped(&sport->port)) + if (!kfifo_is_empty(&tport->xmit_fifo) && + !uart_tx_stopped(&sport->port)) imx_uart_dma_tx(sport); else if (sport->port.rs485.flags & SER_RS485_ENABLED) { u32 ucr4 =3D imx_uart_readl(sport, UCR4); @@ -609,7 +609,7 @@ static void imx_uart_dma_tx_callback(void *data) /* called with port.lock taken and irqs off */ static void imx_uart_dma_tx(struct imx_port *sport) { - struct circ_buf *xmit =3D &sport->port.state->xmit; + struct tty_port *tport =3D &sport->port.state->port; struct scatterlist *sgl =3D sport->tx_sgl; struct dma_async_tx_descriptor *desc; struct dma_chan *chan =3D sport->dma_chan_tx; @@ -624,18 +624,10 @@ static void imx_uart_dma_tx(struct imx_port *sport) ucr4 &=3D ~UCR4_TCEN; imx_uart_writel(sport, ucr4, UCR4); =20 - sport->tx_bytes =3D uart_circ_chars_pending(xmit); - - if (xmit->tail < xmit->head || xmit->head =3D=3D 0) { - sport->dma_tx_nents =3D 1; - sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes); - } else { - sport->dma_tx_nents =3D 2; - sg_init_table(sgl, 2); - sg_set_buf(sgl, xmit->buf + xmit->tail, - UART_XMIT_SIZE - xmit->tail); - sg_set_buf(sgl + 1, xmit->buf, xmit->head); - } + sg_init_table(sgl, ARRAY_SIZE(sport->tx_sgl)); + sport->tx_bytes =3D kfifo_len(&tport->xmit_fifo); + sport->dma_tx_nents =3D kfifo_dma_out_prepare(&tport->xmit_fifo, sgl, + ARRAY_SIZE(sport->tx_sgl), sport->tx_bytes); =20 ret =3D dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); if (ret =3D=3D 0) { @@ -653,8 +645,7 @@ static void imx_uart_dma_tx(struct imx_port *sport) desc->callback =3D imx_uart_dma_tx_callback; desc->callback_param =3D sport; =20 - dev_dbg(dev, "TX: prepare to send %lu bytes by DMA.\n", - uart_circ_chars_pending(xmit)); + dev_dbg(dev, "TX: prepare to send %u bytes by DMA.\n", sport->tx_bytes); =20 ucr1 =3D imx_uart_readl(sport, UCR1); ucr1 |=3D UCR1_TXDMAEN; @@ -671,9 +662,10 @@ static void imx_uart_dma_tx(struct imx_port *sport) static void imx_uart_start_tx(struct uart_port *port) { struct imx_port *sport =3D (struct imx_port *)port; + struct tty_port *tport =3D &sport->port.state->port; u32 ucr1; =20 - if (!sport->port.x_char && uart_circ_empty(&port->state->xmit)) + if (!sport->port.x_char && kfifo_is_empty(&tport->xmit_fifo)) return; =20 /* @@ -749,7 +741,7 @@ static void imx_uart_start_tx(struct uart_port *port) return; } =20 - if (!uart_circ_empty(&port->state->xmit) && + if (!kfifo_is_empty(&tport->xmit_fifo) && !uart_tx_stopped(port)) imx_uart_dma_tx(sport); return; diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c index 320b29cd4683..c2cae50f06f3 100644 --- a/drivers/tty/serial/ip22zilog.c +++ b/drivers/tty/serial/ip22zilog.c @@ -355,7 +355,8 @@ static void ip22zilog_status_handle(struct uart_ip22zil= og_port *up, static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up, struct zilog_channel *channel) { - struct circ_buf *xmit; + struct tty_port *tport; + unsigned char c; =20 if (ZS_IS_CONS(up)) { unsigned char status =3D readb(&channel->control); @@ -398,20 +399,18 @@ static void ip22zilog_transmit_chars(struct uart_ip22= zilog_port *up, =20 if (up->port.state =3D=3D NULL) goto ack_tx_int; - xmit =3D &up->port.state->xmit; - if (uart_circ_empty(xmit)) - goto ack_tx_int; + tport =3D &up->port.state->port; if (uart_tx_stopped(&up->port)) goto ack_tx_int; + if (!uart_fifo_get(&up->port, &c)) + goto ack_tx_int; =20 up->flags |=3D IP22ZILOG_FLAG_TX_ACTIVE; - writeb(xmit->buf[xmit->tail], &channel->data); + writeb(c, &channel->data); ZSDELAY(); ZS_WSYNC(channel); =20 - uart_xmit_advance(&up->port, 1); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&up->port); =20 return; @@ -600,17 +599,16 @@ static void ip22zilog_start_tx(struct uart_port *port) port->icount.tx++; port->x_char =3D 0; } else { - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; + unsigned char c; =20 - if (uart_circ_empty(xmit)) + if (!uart_fifo_get(port, &c)) return; - writeb(xmit->buf[xmit->tail], &channel->data); + writeb(c, &channel->data); ZSDELAY(); ZS_WSYNC(channel); =20 - uart_xmit_advance(port, 1); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&up->port); } } diff --git a/drivers/tty/serial/jsm/jsm_cls.c b/drivers/tty/serial/jsm/jsm_= cls.c index ddbd42c09637..6e40792f92cf 100644 --- a/drivers/tty/serial/jsm/jsm_cls.c +++ b/drivers/tty/serial/jsm/jsm_cls.c @@ -443,20 +443,14 @@ static void cls_copy_data_from_uart_to_queue(struct j= sm_channel *ch) =20 static void cls_copy_data_from_queue_to_uart(struct jsm_channel *ch) { - u16 tail; + struct tty_port *tport; int n; - int qlen; u32 len_written =3D 0; - struct circ_buf *circ; =20 if (!ch) return; =20 - circ =3D &ch->uart_port.state->xmit; - - /* No data to write to the UART */ - if (uart_circ_empty(circ)) - return; + tport =3D &ch->uart_port.state->port; =20 /* If port is "stopped", don't send any data to the UART */ 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 j= sm_channel *ch) return; =20 n =3D 32; + while (n > 0) { + unsigned char c; =20 - /* cache tail of queue */ - tail =3D circ->tail & (UART_XMIT_SIZE - 1); - qlen =3D uart_circ_chars_pending(circ); - - /* Find minimum of the FIFO space, versus queue length */ - n =3D min(n, qlen); + if (!kfifo_get(&tport->xmit_fifo, &c)) + break; =20 - while (n > 0) { - writeb(circ->buf[tail], &ch->ch_cls_uart->txrx); - tail =3D (tail + 1) & (UART_XMIT_SIZE - 1); + writeb(c, &ch->ch_cls_uart->txrx); n--; ch->ch_txcount++; len_written++; } =20 - /* Update the final tail */ - circ->tail =3D tail & (UART_XMIT_SIZE - 1); - if (len_written > ch->ch_t_tlevel) ch->ch_flags &=3D ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); =20 - if (uart_circ_empty(circ)) + if (kfifo_is_empty(&tport->xmit_fifo)) uart_write_wakeup(&ch->uart_port); } =20 diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_= neo.c index 1fa10f19368f..e8e13bf056e2 100644 --- a/drivers/tty/serial/jsm/jsm_neo.c +++ b/drivers/tty/serial/jsm/jsm_neo.c @@ -474,21 +474,21 @@ static void neo_copy_data_from_uart_to_queue(struct j= sm_channel *ch) =20 static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch) { - u16 head; - u16 tail; + struct tty_port *tport; + unsigned char *tail; + unsigned char c; int n; int s; int qlen; u32 len_written =3D 0; - struct circ_buf *circ; =20 if (!ch) return; =20 - circ =3D &ch->uart_port.state->xmit; + tport =3D &ch->uart_port.state->port; =20 /* No data to write to the UART */ - if (uart_circ_empty(circ)) + if (kfifo_is_empty(&tport->xmit_fifo)) return; =20 /* 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 js= m_channel *ch) if (ch->ch_cached_lsr & UART_LSR_THRE) { ch->ch_cached_lsr &=3D ~(UART_LSR_THRE); =20 - writeb(circ->buf[circ->tail], &ch->ch_neo_uart->txrx); - jsm_dbg(WRITE, &ch->ch_bd->pci_dev, - "Tx data: %x\n", circ->buf[circ->tail]); - circ->tail =3D (circ->tail + 1) & (UART_XMIT_SIZE - 1); + WARN_ON_ONCE(!kfifo_get(&tport->xmit_fifo, &c)); + writeb(c, &ch->ch_neo_uart->txrx); + jsm_dbg(WRITE, &ch->ch_bd->pci_dev, "Tx data: %x\n", c); ch->ch_txcount++; } return; @@ -520,38 +519,27 @@ static void neo_copy_data_from_queue_to_uart(struct j= sm_channel *ch) return; =20 n =3D UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel; - - /* cache head and tail of queue */ - head =3D circ->head & (UART_XMIT_SIZE - 1); - tail =3D circ->tail & (UART_XMIT_SIZE - 1); - qlen =3D uart_circ_chars_pending(circ); + qlen =3D kfifo_len(&tport->xmit_fifo); =20 /* Find minimum of the FIFO space, versus queue length */ n =3D min(n, qlen); =20 while (n > 0) { - - s =3D ((head >=3D tail) ? head : UART_XMIT_SIZE) - tail; - s =3D min(s, n); - + s =3D kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, n); if (s <=3D 0) break; =20 - memcpy_toio(&ch->ch_neo_uart->txrxburst, circ->buf + tail, s); - /* Add and flip queue if needed */ - tail =3D (tail + s) & (UART_XMIT_SIZE - 1); + memcpy_toio(&ch->ch_neo_uart->txrxburst, tail, s); + kfifo_skip_count(&tport->xmit_fifo, s); n -=3D s; ch->ch_txcount +=3D s; len_written +=3D s; } =20 - /* Update the final tail */ - circ->tail =3D tail & (UART_XMIT_SIZE - 1); - if (len_written >=3D ch->ch_t_tlevel) ch->ch_flags &=3D ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); =20 - if (uart_circ_empty(circ)) + if (kfifo_is_empty(&tport->xmit_fifo)) uart_write_wakeup(&ch->uart_port); } =20 diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index 5efb2b593be3..b83eee37c17d 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c @@ -257,10 +257,11 @@ static int max3100_handlerx(struct max3100_port *s, u= 16 rx) static void max3100_work(struct work_struct *w) { struct max3100_port *s =3D container_of(w, struct max3100_port, work); + struct tty_port *tport =3D &s->port.state->port; + unsigned char ch; int rxchars; u16 tx, rx; int conf, cconf, crts; - struct circ_buf *xmit =3D &s->port.state->xmit; =20 dev_dbg(&s->spi->dev, "%s\n", __func__); =20 @@ -290,10 +291,9 @@ static void max3100_work(struct work_struct *w) tx =3D s->port.x_char; s->port.icount.tx++; s->port.x_char =3D 0; - } else if (!uart_circ_empty(xmit) && - !uart_tx_stopped(&s->port)) { - tx =3D xmit->buf[xmit->tail]; - uart_xmit_advance(&s->port, 1); + } else if (!uart_tx_stopped(&s->port) && + uart_fifo_get(&s->port, &ch)) { + tx =3D ch; } if (tx !=3D 0xffff) { 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); rxchars =3D 0; } - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&s->port); =20 } while (!s->force_end_work && !freezing(current) && ((rx & MAX3100_R) || - (!uart_circ_empty(xmit) && + (!kfifo_is_empty(&tport->xmit_fifo) && !uart_tx_stopped(&s->port)))); =20 if (rxchars > 0) diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 14dd9cfaa9f7..f0eb96429dae 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -747,8 +747,9 @@ static void max310x_handle_rx(struct uart_port *port, u= nsigned int rxlen) =20 static void max310x_handle_tx(struct uart_port *port) { - struct circ_buf *xmit =3D &port->state->xmit; - unsigned int txlen, to_send, until_end; + struct tty_port *tport =3D &port->state->port; + unsigned int txlen, to_send; + unsigned char *tail; =20 if (unlikely(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; } =20 - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) return; =20 - /* Get length of data pending in circular buffer */ - to_send =3D uart_circ_chars_pending(xmit); - until_end =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); - if (likely(to_send)) { + /* + * It's a circ buffer -- wrap around. + * We could do that in one SPI transaction, but meh. + */ + while (!kfifo_is_empty(&tport->xmit_fifo)) { /* Limit to space available in TX FIFO */ txlen =3D max310x_port_read(port, MAX310X_TXFIFOLVL_REG); txlen =3D port->fifosize - txlen; - to_send =3D (to_send > txlen) ? txlen : to_send; - - if (until_end < 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); - } + if (!txlen) + break; + + to_send =3D kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, txlen); + max310x_batch_write(port, tail, to_send); uart_xmit_advance(port, to_send); } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); } =20 diff --git a/drivers/tty/serial/men_z135_uart.c b/drivers/tty/serial/men_z1= 35_uart.c index 8048fa542fc4..4bff422bb1bc 100644 --- a/drivers/tty/serial/men_z135_uart.c +++ b/drivers/tty/serial/men_z135_uart.c @@ -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) { struct uart_port *port =3D &uart->port; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; + unsigned char *tail; + unsigned int n, txfree; u32 txc; u32 wptr; int qlen; - int n; - int txfree; - int head; - int tail; - int s; =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) goto out; =20 if (uart_tx_stopped(port)) @@ -313,7 +310,7 @@ static void men_z135_handle_tx(struct men_z135_port *ua= rt) goto out; =20 /* calculate bytes to copy */ - qlen =3D uart_circ_chars_pending(xmit); + qlen =3D kfifo_len(&tport->xmit_fifo); if (qlen <=3D 0) goto out; =20 @@ -345,21 +342,18 @@ static void men_z135_handle_tx(struct men_z135_port *= uart) if (n <=3D 0) goto irq_en; =20 - head =3D xmit->head & (UART_XMIT_SIZE - 1); - tail =3D xmit->tail & (UART_XMIT_SIZE - 1); - - s =3D ((head >=3D tail) ? head : UART_XMIT_SIZE) - tail; - n =3D min(n, s); + n =3D kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, + min_t(unsigned int, UART_XMIT_SIZE, n)); + memcpy_toio(port->membase + MEN_Z135_TX_RAM, tail, n); =20 - memcpy_toio(port->membase + MEN_Z135_TX_RAM, &xmit->buf[xmit->tail], n); iowrite32(n & 0x3ff, port->membase + MEN_Z135_TX_CTRL); uart_xmit_advance(port, n); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 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); else men_z135_reg_clr(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN); diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uar= t.c index 6feac459c0cf..4587ed4d4d5d 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -141,8 +141,8 @@ static void meson_uart_shutdown(struct uart_port *port) =20 static void meson_uart_start_tx(struct uart_port *port) { - struct circ_buf *xmit =3D &port->state->xmit; - unsigned int ch; + struct tty_port *tport =3D &port->state->port; + unsigned char ch; u32 val; =20 if (uart_tx_stopped(port)) { @@ -158,21 +158,20 @@ static void meson_uart_start_tx(struct uart_port *por= t) continue; } =20 - if (uart_circ_empty(xmit)) + if (!uart_fifo_get(port, &ch)) break; =20 - ch =3D xmit->buf[xmit->tail]; writel(ch, port->membase + AML_UART_WFIFO); uart_xmit_advance(port, 1); } =20 - if (!uart_circ_empty(xmit)) { + if (!kfifo_is_empty(&tport->xmit_fifo)) { val =3D readl(port->membase + AML_UART_CONTROL); val |=3D AML_UART_TX_INT_EN; writel(val, port->membase + AML_UART_CONTROL); } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); } =20 diff --git a/drivers/tty/serial/milbeaut_usio.c b/drivers/tty/serial/milbea= ut_usio.c index da4c6f7e2a30..fb082ee73d5b 100644 --- a/drivers/tty/serial/milbeaut_usio.c +++ b/drivers/tty/serial/milbeaut_usio.c @@ -72,7 +72,7 @@ static void mlb_usio_stop_tx(struct uart_port *port) =20 static void mlb_usio_tx_chars(struct uart_port *port) { - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; int count; =20 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 =3D 0; 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); return; } @@ -96,12 +96,13 @@ static void mlb_usio_tx_chars(struct uart_port *port) (readw(port->membase + MLB_USIO_REG_FBYTE) & 0xff); =20 do { - writew(xmit->buf[xmit->tail], port->membase + MLB_USIO_REG_DR); + unsigned char ch; =20 - uart_xmit_advance(port, 1); - if (uart_circ_empty(xmit)) + if (!uart_fifo_get(port, &ch)) break; =20 + writew(ch, port->membase + MLB_USIO_REG_DR); + port->icount.tx++; } while (--count > 0); =20 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, port->membase + MLB_USIO_REG_SCR); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) mlb_usio_stop_tx(port); } =20 diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_seria= l.c index 7bf30e632313..ae7a8e3cf467 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -452,7 +452,7 @@ static void msm_complete_tx_dma(void *args) { struct msm_port *msm_port =3D args; struct uart_port *port =3D &msm_port->uart; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; struct msm_dma *dma =3D &msm_port->tx_dma; struct dma_tx_state state; unsigned long flags; @@ -486,7 +486,7 @@ static void msm_complete_tx_dma(void *args) msm_port->imr |=3D MSM_UART_IMR_TXLEV; msm_write(port, msm_port->imr, MSM_UART_IMR); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 msm_handle_tx(port); @@ -496,14 +496,14 @@ static void msm_complete_tx_dma(void *args) =20 static int msm_handle_tx_dma(struct msm_port *msm_port, unsigned int count) { - struct circ_buf *xmit =3D &msm_port->uart.state->xmit; struct uart_port *port =3D &msm_port->uart; + struct tty_port *tport =3D &port->state->port; struct msm_dma *dma =3D &msm_port->tx_dma; int ret; u32 val; =20 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); =20 ret =3D dma_map_sg(port->dev, &dma->tx_sg, 1, dma->dir); if (ret) @@ -843,8 +843,8 @@ static void msm_handle_rx(struct uart_port *port) =20 static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_coun= t) { - struct circ_buf *xmit =3D &port->state->xmit; struct msm_port *msm_port =3D to_msm_port(port); + struct tty_port *tport =3D &port->state->port; unsigned int num_chars; unsigned int tf_pointer =3D 0; void __iomem *tf; @@ -858,8 +858,7 @@ static void msm_handle_tx_pio(struct uart_port *port, u= nsigned int tx_count) msm_reset_dm_count(port, tx_count); =20 while (tf_pointer < tx_count) { - int i; - char buf[4] =3D { 0 }; + unsigned char buf[4] =3D { 0 }; =20 if (!(msm_read(port, MSM_UART_SR) & MSM_UART_SR_TX_READY)) break; @@ -870,26 +869,23 @@ static void msm_handle_tx_pio(struct uart_port *port,= unsigned int tx_count) else num_chars =3D 1; =20 - for (i =3D 0; i < num_chars; i++) - buf[i] =3D xmit->buf[xmit->tail + i]; - + num_chars =3D uart_fifo_out(port, buf, num_chars); iowrite32_rep(tf, buf, 1); - uart_xmit_advance(port, num_chars); tf_pointer +=3D num_chars; } =20 /* disable tx interrupts if nothing more to send */ - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) msm_stop_tx(port); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); } =20 static void msm_handle_tx(struct uart_port *port) { struct msm_port *msm_port =3D to_msm_port(port); - struct circ_buf *xmit =3D &msm_port->uart.state->xmit; + struct tty_port *tport =3D &port->state->port; struct msm_dma *dma =3D &msm_port->tx_dma; unsigned int pio_count, dma_count, dma_min; char buf[4] =3D { 0 }; @@ -913,13 +909,13 @@ static void msm_handle_tx(struct uart_port *port) return; } =20 - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) { msm_stop_tx(port); return; } =20 - pio_count =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); - dma_count =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + dma_count =3D pio_count =3D kfifo_out_linear(&tport->xmit_fifo, NULL, + UART_XMIT_SIZE); =20 dma_min =3D 1; /* Always DMA */ if (msm_port->is_uartdm > UARTDM_1P3) { diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uar= t.c index 0255646bc175..5de57b77abdb 100644 --- a/drivers/tty/serial/mvebu-uart.c +++ b/drivers/tty/serial/mvebu-uart.c @@ -219,12 +219,10 @@ static void mvebu_uart_stop_tx(struct uart_port *port) static void mvebu_uart_start_tx(struct uart_port *port) { unsigned int ctl; - struct circ_buf *xmit =3D &port->state->xmit; + unsigned char c; =20 - if (IS_EXTENDED(port) && !uart_circ_empty(xmit)) { - writel(xmit->buf[xmit->tail], port->membase + UART_TSH(port)); - uart_xmit_advance(port, 1); - } + if (IS_EXTENDED(port) && uart_fifo_get(port, &c)) + writel(c, port->membase + UART_TSH(port)); =20 ctl =3D readl(port->membase + UART_INTR(port)); ctl |=3D CTRL_TX_RDY_INT(port); diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 4749331fe618..144b35d31497 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -517,7 +517,7 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s= ); static void dma_tx_callback(void *param) { struct mxs_auart_port *s =3D param; - struct circ_buf *xmit =3D &s->port.state->xmit; + struct tty_port *tport =3D &s->port.state->port; =20 dma_unmap_sg(s->dev, &s->tx_sgl, 1, DMA_TO_DEVICE); =20 @@ -526,7 +526,7 @@ static void dma_tx_callback(void *param) smp_mb__after_atomic(); =20 /* 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); =20 mxs_auart_tx_chars(s); @@ -568,33 +568,22 @@ static int mxs_auart_dma_tx(struct mxs_auart_port *s,= int size) =20 static void mxs_auart_tx_chars(struct mxs_auart_port *s) { - struct circ_buf *xmit =3D &s->port.state->xmit; + struct tty_port *tport =3D &s->port.state->port; bool pending; u8 ch; =20 if (auart_dma_enabled(s)) { u32 i =3D 0; - int size; void *buffer =3D s->tx_dma_buf; =20 if (test_and_set_bit(MXS_AUART_DMA_TX_SYNC, &s->flags)) return; =20 - while (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) { - size =3D 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 =3D (xmit->tail + size) & (UART_XMIT_SIZE - 1); - - i +=3D size; - if (i >=3D UART_XMIT_SIZE) - break; - } - if (uart_tx_stopped(&s->port)) mxs_auart_stop_tx(&s->port); + else + i =3D kfifo_out(&tport->xmit_fifo, buffer, + UART_XMIT_SIZE); =20 if (i) { mxs_auart_dma_tx(s, i); diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 89257cddf540..c7cee5fee603 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -808,7 +808,7 @@ static int dma_handle_rx(struct eg20t_port *priv) static unsigned int handle_tx(struct eg20t_port *priv) { struct uart_port *port =3D &priv->port; - struct circ_buf *xmit =3D &port->state->xmit; + unsigned char ch; int fifo_size; int tx_empty; =20 @@ -830,9 +830,9 @@ static unsigned int handle_tx(struct eg20t_port *priv) fifo_size--; } =20 - while (!uart_tx_stopped(port) && !uart_circ_empty(xmit) && fifo_size) { - iowrite8(xmit->buf[xmit->tail], priv->membase + PCH_UART_THR); - uart_xmit_advance(port, 1); + while (!uart_tx_stopped(port) && fifo_size && + uart_fifo_get(port, &ch)) { + iowrite8(ch, priv->membase + PCH_UART_THR); fifo_size--; tx_empty =3D 0; } @@ -850,14 +850,14 @@ static unsigned int handle_tx(struct eg20t_port *priv) static unsigned int dma_handle_tx(struct eg20t_port *priv) { struct uart_port *port =3D &priv->port; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; struct scatterlist *sg; int nent; int fifo_size; struct dma_async_tx_descriptor *desc; + unsigned int bytes, tail; int num; int i; - int bytes; int size; int rem; =20 @@ -886,7 +886,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *pr= iv) fifo_size--; } =20 - bytes =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + bytes =3D kfifo_out_linear(&tport->xmit_fifo, &tail, UART_XMIT_SIZE); if (!bytes) { dev_dbg(priv->port.dev, "%s 0 bytes return\n", __func__); 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) =20 for (i =3D 0; i < num; i++, sg++) { if (i =3D=3D (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); else - sg_set_page(sg, virt_to_page(xmit->buf), + sg_set_page(sg, virt_to_page(tport->xmit_buf), size, fifo_size * i); } =20 @@ -937,8 +937,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *pr= iv) priv->nent =3D nent; =20 for (i =3D 0; i < nent; i++, sg++) { - sg->offset =3D (xmit->tail & (UART_XMIT_SIZE - 1)) + - fifo_size * i; + sg->offset =3D tail + fifo_size * i; sg_dma_address(sg) =3D (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) + sg->offset; if (i =3D=3D (nent - 1)) diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uar= t.c index bbb46e6e98a2..f5af336a869b 100644 --- a/drivers/tty/serial/pic32_uart.c +++ b/drivers/tty/serial/pic32_uart.c @@ -342,7 +342,7 @@ static void pic32_uart_do_rx(struct uart_port *port) static void pic32_uart_do_tx(struct uart_port *port) { struct pic32_sport *sport =3D to_pic32_sport(port); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; unsigned int max_count =3D PIC32_UART_TX_FIFO_DEPTH; =20 if (port->x_char) { @@ -357,7 +357,7 @@ static void pic32_uart_do_tx(struct uart_port *port) return; } =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) goto txq_empty; =20 /* 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 & pic32_uart_readl(sport, PIC32_UART_STA))) { - unsigned int c =3D xmit->buf[xmit->tail]; + unsigned char c; =20 + if (!uart_fifo_get(port, &c)) + break; pic32_uart_writel(sport, PIC32_UART_TX, c); =20 - uart_xmit_advance(port, 1); - if (uart_circ_empty(xmit)) - break; if (--max_count =3D=3D 0) break; } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) goto txq_empty; =20 return; diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilo= g.c index 05d97e89511e..63bc726273fd 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -347,7 +347,8 @@ static void pmz_status_handle(struct uart_pmac_port *ua= p) =20 static void pmz_transmit_chars(struct uart_pmac_port *uap) { - struct circ_buf *xmit; + struct tty_port *tport; + unsigned char ch; =20 if (ZS_IS_CONS(uap)) { unsigned char status =3D read_zsreg(uap, R0); @@ -398,8 +399,8 @@ static void pmz_transmit_chars(struct uart_pmac_port *u= ap) =20 if (uap->port.state =3D=3D NULL) goto ack_tx_int; - xmit =3D &uap->port.state->xmit; - if (uart_circ_empty(xmit)) { + tport =3D &uap->port.state->port; + if (kfifo_is_empty(&tport->xmit_fifo)) { uart_write_wakeup(&uap->port); goto ack_tx_int; } @@ -407,12 +408,11 @@ static void pmz_transmit_chars(struct uart_pmac_port = *uap) goto ack_tx_int; =20 uap->flags |=3D 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); =20 - uart_xmit_advance(&uap->port, 1); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&uap->port); =20 return; @@ -620,15 +620,15 @@ static void pmz_start_tx(struct uart_port *port) port->icount.tx++; port->x_char =3D 0; } else { - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; + unsigned char ch; =20 - if (uart_circ_empty(xmit)) + if (!uart_fifo_get(&uap->port, &ch)) return; - write_zsdata(uap, xmit->buf[xmit->tail]); + write_zsdata(uap, ch); zssync(uap); - uart_xmit_advance(port, 1); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&uap->port); } } diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qco= m_geni_serial.c index f9f7ac1a10df..7814982f1921 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -505,7 +505,7 @@ static void qcom_geni_serial_console_write(struct conso= le *co, const char *s, */ qcom_geni_serial_poll_tx_done(uport); =20 - if (!uart_circ_empty(&uport->state->xmit)) { + if (!kfifo_is_empty(&uport->state->port.xmit_fifo)) { irq_en =3D readl(uport->membase + SE_GENI_M_IRQ_EN); writel(irq_en | M_TX_FIFO_WATERMARK_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) { struct qcom_geni_serial_port *port =3D to_dev_port(uport); - struct circ_buf *xmit =3D &uport->state->xmit; + struct tty_port *tport =3D &uport->state->port; unsigned int xmit_size; + u8 *tail; int ret; =20 if (port->tx_dma_addr) return; =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) return; =20 - xmit_size =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + xmit_size =3D kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, + UART_XMIT_SIZE); =20 qcom_geni_serial_setup_tx(uport, xmit_size); =20 - ret =3D geni_se_tx_dma_prep(&port->se, &xmit->buf[xmit->tail], - xmit_size, &port->tx_dma_addr); + ret =3D geni_se_tx_dma_prep(&port->se, tail, xmit_size, + &port->tx_dma_addr); if (ret) { dev_err(uport->dev, "unable to start TX SE DMA: %d\n", ret); qcom_geni_serial_stop_tx_dma(uport); @@ -853,18 +855,16 @@ static void qcom_geni_serial_send_chunk_fifo(struct u= art_port *uport, unsigned int chunk) { struct qcom_geni_serial_port *port =3D to_dev_port(uport); - struct circ_buf *xmit =3D &uport->state->xmit; - unsigned int tx_bytes, c, remaining =3D chunk; + struct tty_port *tport =3D &uport->state->port; + unsigned int tx_bytes, remaining =3D chunk; u8 buf[BYTES_PER_FIFO_WORD]; =20 while (remaining) { memset(buf, 0, sizeof(buf)); tx_bytes =3D min(remaining, BYTES_PER_FIFO_WORD); =20 - for (c =3D 0; c < tx_bytes ; c++) { - buf[c] =3D xmit->buf[xmit->tail]; - uart_xmit_advance(uport, 1); - } + tx_bytes =3D kfifo_out(&tport->xmit_fifo, buf, tx_bytes); + uart_xmit_advance(uport, tx_bytes); =20 iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1); =20 @@ -877,7 +877,7 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart= _port *uport, bool done, bool active) { struct qcom_geni_serial_port *port =3D to_dev_port(uport); - struct circ_buf *xmit =3D &uport->state->xmit; + struct tty_port *tport =3D &uport->state->port; size_t avail; size_t pending; u32 status; @@ -890,7 +890,7 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart= _port *uport, if (active) pending =3D port->tx_remaining; else - pending =3D uart_circ_chars_pending(xmit); + pending =3D kfifo_len(&tport->xmit_fifo); =20 /* All data has been transmitted and acknowledged as received */ if (!pending && !status && done) { @@ -933,24 +933,24 @@ static void qcom_geni_serial_handle_tx_fifo(struct ua= rt_port *uport, uport->membase + SE_GENI_M_IRQ_EN); } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(uport); } =20 static void qcom_geni_serial_handle_tx_dma(struct uart_port *uport) { struct qcom_geni_serial_port *port =3D to_dev_port(uport); - struct circ_buf *xmit =3D &uport->state->xmit; + struct tty_port *tport =3D &uport->state->port; =20 uart_xmit_advance(uport, port->tx_remaining); geni_se_tx_dma_unprep(&port->se, port->tx_dma_addr, port->tx_remaining); port->tx_dma_addr =3D 0; port->tx_remaining =3D 0; =20 - if (!uart_circ_empty(xmit)) + if (!kfifo_is_empty(&tport->xmit_fifo)) qcom_geni_serial_start_tx_dma(uport); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(uport); } =20 diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c index 82def9b8632a..663e35e424bd 100644 --- a/drivers/tty/serial/rda-uart.c +++ b/drivers/tty/serial/rda-uart.c @@ -330,8 +330,8 @@ static void rda_uart_set_termios(struct uart_port *port, =20 static void rda_uart_send_chars(struct uart_port *port) { - struct circ_buf *xmit =3D &port->state->xmit; - unsigned int ch; + struct tty_port *tport =3D &port->state->port; + unsigned char ch; u32 val; =20 if (uart_tx_stopped(port)) @@ -347,19 +347,14 @@ static void rda_uart_send_chars(struct uart_port *por= t) port->x_char =3D 0; } =20 - while (rda_uart_read(port, RDA_UART_STATUS) & RDA_UART_TX_FIFO_MASK) { - if (uart_circ_empty(xmit)) - break; - - ch =3D xmit->buf[xmit->tail]; + while ((rda_uart_read(port, RDA_UART_STATUS) & RDA_UART_TX_FIFO_MASK) && + uart_fifo_get(port, &ch)) rda_uart_write(port, ch, RDA_UART_RXTX_BUFFER); - uart_xmit_advance(port, 1); - } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 - if (!uart_circ_empty(xmit)) { + if (!kfifo_is_empty(&tport->xmit_fifo)) { /* Re-enable Tx FIFO interrupt */ val =3D rda_uart_read(port, RDA_UART_IRQ_MASK); val |=3D RDA_UART_TX_DATA_NEEDED; diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_= tty.c index a2d07e05c502..dc35eb77d2ef 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -329,7 +329,7 @@ static void s3c24xx_serial_tx_dma_complete(void *args) { struct s3c24xx_uart_port *ourport =3D args; struct uart_port *port =3D &ourport->port; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; struct s3c24xx_uart_dma *dma =3D ourport->dma; struct dma_tx_state state; unsigned long flags; @@ -348,7 +348,7 @@ static void s3c24xx_serial_tx_dma_complete(void *args) uart_xmit_advance(port, count); ourport->tx_in_progress =3D 0; =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 s3c24xx_serial_start_next_tx(ourport); @@ -431,17 +431,15 @@ static void s3c24xx_serial_start_tx_pio(struct s3c24x= x_uart_port *ourport) } =20 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 =3D &ourport->port; - struct circ_buf *xmit =3D &port->state->xmit; struct s3c24xx_uart_dma *dma =3D ourport->dma; =20 if (ourport->tx_mode !=3D S3C24XX_TX_DMA) enable_tx_dma(ourport); =20 dma->tx_size =3D count & ~(dma_get_cache_alignment() - 1); - dma->tx_transfer_addr =3D dma->tx_addr + xmit->tail; + dma->tx_transfer_addr =3D dma->tx_addr + tail; =20 dma_sync_single_for_device(dma->tx_chan->device->dev, 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) { struct uart_port *port =3D &ourport->port; - struct circ_buf *xmit =3D &port->state->xmit; - unsigned long count; + struct tty_port *tport =3D &port->state->port; + unsigned int count, tail; =20 /* Get data size up to the end of buffer */ - count =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + count =3D kfifo_out_linear(&tport->xmit_fifo, &tail, UART_XMIT_SIZE); =20 if (!count) { s3c24xx_serial_stop_tx(port); @@ -481,16 +479,16 @@ static void s3c24xx_serial_start_next_tx(struct s3c24= xx_uart_port *ourport) =20 if (!ourport->dma || !ourport->dma->tx_chan || count < ourport->min_dma_size || - xmit->tail & (dma_get_cache_alignment() - 1)) + tail & (dma_get_cache_alignment() - 1)) s3c24xx_serial_start_tx_pio(ourport); else - s3c24xx_serial_start_tx_dma(ourport, count); + s3c24xx_serial_start_tx_dma(ourport, count, tail); } =20 static void s3c24xx_serial_start_tx(struct uart_port *port) { struct s3c24xx_uart_port *ourport =3D to_ourport(port); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; =20 if (!ourport->tx_enabled) { if (port->flags & UPF_CONS_FLOW) @@ -502,7 +500,8 @@ static void s3c24xx_serial_start_tx(struct uart_port *p= ort) } =20 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); } } @@ -868,18 +867,19 @@ static irqreturn_t s3c24xx_serial_rx_irq(int irq, voi= d *dev_id) static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport) { struct uart_port *port =3D &ourport->port; - struct circ_buf *xmit =3D &port->state->xmit; - int count, dma_count =3D 0; + struct tty_port *tport =3D &port->state->port; + unsigned int count, dma_count =3D 0, tail; =20 - count =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + count =3D kfifo_out_linear(&tport->xmit_fifo, &tail, UART_XMIT_SIZE); =20 if (ourport->dma && ourport->dma->tx_chan && count >=3D ourport->min_dma_size) { int align =3D dma_get_cache_alignment() - - (xmit->tail & (dma_get_cache_alignment() - 1)); + (tail & (dma_get_cache_alignment() - 1)); if (count - align >=3D ourport->min_dma_size) { dma_count =3D count - align; count =3D align; + tail +=3D align; } } =20 @@ -894,7 +894,7 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_uart= _port *ourport) * stopped, disable the uart and exit */ =20 - 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); return; } @@ -906,24 +906,25 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_ua= rt_port *ourport) dma_count =3D 0; } =20 - while (!uart_circ_empty(xmit) && count > 0) { - if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull) + while (!(rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)) { + unsigned char ch; + + if (!uart_fifo_get(port, &ch)) break; =20 - wr_reg(port, S3C2410_UTXH, xmit->buf[xmit->tail]); - uart_xmit_advance(port, 1); + wr_reg(port, S3C2410_UTXH, ch); count--; } =20 if (!count && dma_count) { - s3c24xx_serial_start_tx_dma(ourport, dma_count); + s3c24xx_serial_start_tx_dma(ourport, dma_count, tail); return; } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) s3c24xx_serial_stop_tx(port); } =20 @@ -1118,7 +1119,8 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_= uart_port *p) =20 /* TX buffer */ dma->tx_addr =3D 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); if (dma_mapping_error(dma->tx_chan->device->dev, dma->tx_addr)) { reason =3D "DMA mapping error for TX buffer"; diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-= duart.c index dbec29d9a6c3..b4e1b90e5960 100644 --- a/drivers/tty/serial/sb1250-duart.c +++ b/drivers/tty/serial/sb1250-duart.c @@ -382,7 +382,8 @@ static void sbd_receive_chars(struct sbd_port *sport) static void sbd_transmit_chars(struct sbd_port *sport) { struct uart_port *uport =3D &sport->port; - struct circ_buf *xmit =3D &sport->port.state->xmit; + struct tty_port *tport =3D &sport->port.state->port; + unsigned char ch; unsigned int mask; int stop_tx; =20 @@ -395,19 +396,19 @@ static void sbd_transmit_chars(struct sbd_port *sport) } =20 /* If nothing to do or stopped or hardware stopped. */ - stop_tx =3D (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)); + stop_tx =3D uart_tx_stopped(&sport->port) || + !uart_fifo_get(&sport->port, &ch); =20 /* Send char. */ if (!stop_tx) { - write_sbdchn(sport, R_DUART_TX_HOLD, xmit->buf[xmit->tail]); - uart_xmit_advance(&sport->port, 1); + write_sbdchn(sport, R_DUART_TX_HOLD, ch); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&sport->port); } =20 /* Are we are done? */ - if (stop_tx || uart_circ_empty(xmit)) { + if (stop_tx || kfifo_is_empty(&tport->xmit_fifo)) { /* Disable tx interrupts. */ mask =3D read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2)); mask &=3D ~M_DUART_IMR_TX; diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 929206a9a6e1..c6983b7bd78c 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -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) { struct sc16is7xx_port *s =3D dev_get_drvdata(port->dev); - struct circ_buf *xmit =3D &port->state->xmit; - unsigned int txlen, to_send, i; + struct tty_port *tport =3D &port->state->port; unsigned long flags; + unsigned int txlen; =20 if (unlikely(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 *por= t) return; } =20 - 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); sc16is7xx_stop_tx(port); uart_port_unlock_irqrestore(port, flags); return; } =20 - /* Get length of data pending in circular buffer */ - to_send =3D uart_circ_chars_pending(xmit); - if (likely(to_send)) { - /* Limit to space available in TX FIFO */ - txlen =3D sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG); - if (txlen > SC16IS7XX_FIFO_SIZE) { - dev_err_ratelimited(port->dev, - "chip reports %d free bytes in TX fifo, but it only has %d", - txlen, SC16IS7XX_FIFO_SIZE); - txlen =3D 0; - } - to_send =3D (to_send > txlen) ? txlen : to_send; - - /* Convert to linear buffer */ - for (i =3D 0; i < to_send; ++i) { - s->buf[i] =3D xmit->buf[xmit->tail]; - uart_xmit_advance(port, 1); - } - - sc16is7xx_fifo_write(port, s->buf, to_send); + /* Limit to space available in TX FIFO */ + txlen =3D sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG); + if (txlen > SC16IS7XX_FIFO_SIZE) { + dev_err_ratelimited(port->dev, + "chip reports %d free bytes in TX fifo, but it only has %d", + txlen, SC16IS7XX_FIFO_SIZE); + txlen =3D 0; } =20 + txlen =3D uart_fifo_out(port, s->buf, txlen); + sc16is7xx_fifo_write(port, s->buf, txlen); + 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); =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) sc16is7xx_stop_tx(port); else sc16is7xx_ier_set(port, SC16IS7XX_IER_THRI_BIT); diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index f24217a560d7..6d1d142fd216 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -439,7 +439,7 @@ static void sccnxp_handle_rx(struct uart_port *port) static void sccnxp_handle_tx(struct uart_port *port) { u8 sr; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; struct sccnxp_port *s =3D dev_get_drvdata(port->dev); =20 if (unlikely(port->x_char)) { @@ -449,7 +449,7 @@ static void sccnxp_handle_tx(struct uart_port *port) return; } =20 - 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 */ if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXEMT) { sccnxp_disable_irq(port, IMR_TXRDY); @@ -461,16 +461,20 @@ static void sccnxp_handle_tx(struct uart_port *port) return; } =20 - while (!uart_circ_empty(xmit)) { + while (1) { + unsigned char ch; + sr =3D sccnxp_port_read(port, SCCNXP_SR_REG); if (!(sr & SR_TXRDY)) break; =20 - sccnxp_port_write(port, SCCNXP_THR_REG, xmit->buf[xmit->tail]); - uart_xmit_advance(port, 1); + if (!uart_fifo_get(port, &ch)) + break; + + sccnxp_port_write(port, SCCNXP_THR_REG, ch); } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); } =20 diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-= tegra.c index 525f3a2f7bd4..1183ca54ab92 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -484,18 +484,18 @@ static void tegra_uart_release_port(struct uart_port = *u) =20 static void tegra_uart_fill_tx_fifo(struct tegra_uart_port *tup, int max_b= ytes) { - struct circ_buf *xmit =3D &tup->uport.state->xmit; + unsigned char ch; int i; =20 for (i =3D 0; i < max_bytes; i++) { - BUG_ON(uart_circ_empty(xmit)); if (tup->cdata->tx_fifo_full_status) { unsigned long lsr =3D tegra_uart_read(tup, UART_LSR); if ((lsr & TEGRA_UART_LSR_TXFIFO_FULL)) break; } - tegra_uart_write(tup, xmit->buf[xmit->tail], UART_TX); - uart_xmit_advance(&tup->uport, 1); + if (WARN_ON_ONCE(!uart_fifo_get(&tup->uport, &ch))) + break; + tegra_uart_write(tup, ch, UART_TX); } } =20 @@ -514,7 +514,7 @@ static void tegra_uart_start_pio_tx(struct tegra_uart_p= ort *tup, static void tegra_uart_tx_dma_complete(void *args) { struct tegra_uart_port *tup =3D args; - struct circ_buf *xmit =3D &tup->uport.state->xmit; + struct tty_port *tport =3D &tup->uport.state->port; struct dma_tx_state state; unsigned long flags; unsigned int count; @@ -525,7 +525,7 @@ static void tegra_uart_tx_dma_complete(void *args) uart_port_lock_irqsave(&tup->uport, &flags); uart_xmit_advance(&tup->uport, count); tup->tx_in_progress =3D 0; - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&tup->uport); tegra_uart_start_next_tx(tup); 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, unsigned long count) { - struct circ_buf *xmit =3D &tup->uport.state->xmit; + struct tty_port *tport =3D &tup->uport.state->port; dma_addr_t tx_phys_addr; + unsigned int tail; =20 tup->tx_bytes =3D count & ~(0xF); - tx_phys_addr =3D tup->tx_dma_buf_phys + xmit->tail; + WARN_ON_ONCE(kfifo_out_linear(&tport->xmit_fifo, &tail, + UART_XMIT_SIZE) < count); + tx_phys_addr =3D tup->tx_dma_buf_phys + tail; =20 dma_sync_single_for_device(tup->uport.dev, tx_phys_addr, tup->tx_bytes, DMA_TO_DEVICE); @@ -562,18 +565,21 @@ static int tegra_uart_start_tx_dma(struct tegra_uart_= port *tup, =20 static void tegra_uart_start_next_tx(struct tegra_uart_port *tup) { + struct tty_port *tport =3D &tup->uport.state->port; + unsigned char *tail_ptr; unsigned long tail; - unsigned long count; - struct circ_buf *xmit =3D &tup->uport.state->xmit; + unsigned int count; =20 if (!tup->current_baud) return; =20 - tail =3D (unsigned long)&xmit->buf[xmit->tail]; - count =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + count =3D kfifo_out_linear_ptr(&tport->xmit_fifo, &tail_ptr, + UART_XMIT_SIZE); if (!count) return; =20 + tail =3D (unsigned long)tail_ptr; + if (tup->use_tx_pio || count < TEGRA_UART_MIN_DMA) tegra_uart_start_pio_tx(tup, count); 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) { struct tegra_uart_port *tup =3D to_tegra_uport(u); - struct circ_buf *xmit =3D &u->state->xmit; + struct tty_port *tport =3D &u->state->port; =20 - 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); } =20 @@ -628,11 +634,11 @@ static void tegra_uart_stop_tx(struct uart_port *u) =20 static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup) { - struct circ_buf *xmit =3D &tup->uport.state->xmit; + struct tty_port *tport =3D &tup->uport.state->port; =20 tegra_uart_fill_tx_fifo(tup, tup->tx_bytes); tup->tx_in_progress =3D 0; - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&tup->uport); tegra_uart_start_next_tx(tup); } @@ -1169,15 +1175,14 @@ static int tegra_uart_dma_channel_allocate(struct t= egra_uart_port *tup, tup->rx_dma_buf_virt =3D dma_buf; tup->rx_dma_buf_phys =3D dma_phys; } else { + dma_buf =3D tup->uport.state->port.xmit_buf; dma_phys =3D dma_map_single(tup->uport.dev, - tup->uport.state->xmit.buf, UART_XMIT_SIZE, - DMA_TO_DEVICE); + dma_buf, UART_XMIT_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(tup->uport.dev, dma_phys)) { dev_err(tup->uport.dev, "dma_map_single tx failed\n"); dma_release_channel(dma_chan); return -ENOMEM; } - dma_buf =3D tup->uport.state->xmit.buf; dma_sconfig.dst_addr =3D tup->uport.mapbase; dma_sconfig.dst_addr_width =3D DMA_SLAVE_BUSWIDTH_1_BYTE; dma_sconfig.dst_maxburst =3D 16; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_c= ore.c index ff85ebd3a007..3c0931fba1c6 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -272,9 +272,10 @@ static int uart_port_startup(struct tty_struct *tty, s= truct uart_state *state, return -ENOMEM; =20 uart_port_lock(state, flags); - if (!state->xmit.buf) { - state->xmit.buf =3D (unsigned char *) page; - uart_circ_clear(&state->xmit); + if (!state->port.xmit_buf) { + state->port.xmit_buf =3D (unsigned char *)page; + kfifo_init(&state->port.xmit_fifo, state->port.xmit_buf, + PAGE_SIZE); uart_port_unlock(uport, flags); } else { uart_port_unlock(uport, flags); @@ -387,8 +388,9 @@ static void uart_shutdown(struct tty_struct *tty, struc= t uart_state *state) * can endup in printk() recursion. */ uart_port_lock(state, flags); - xmit_buf =3D state->xmit.buf; - state->xmit.buf =3D NULL; + xmit_buf =3D port->xmit_buf; + port->xmit_buf =3D NULL; + INIT_KFIFO(port->xmit_fifo); uart_port_unlock(uport, flags); =20 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 =3D tty->driver_data; struct uart_port *port; - struct circ_buf *circ; unsigned long flags; int ret =3D 0; =20 - circ =3D &state->xmit; port =3D uart_port_lock(state, flags); - if (!circ->buf) { + if (WARN_ON_ONCE(!state->port.xmit_buf)) { uart_port_unlock(port, flags); return 0; } =20 - if (port && uart_circ_chars_free(circ) !=3D 0) { - circ->buf[circ->head] =3D c; - circ->head =3D (circ->head + 1) & (UART_XMIT_SIZE - 1); - ret =3D 1; - } + if (port) + ret =3D kfifo_put(&state->port.xmit_fifo, c); uart_port_unlock(port, flags); 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 =3D tty->driver_data; struct uart_port *port; - struct circ_buf *circ; unsigned long flags; - int c, ret =3D 0; + int ret =3D 0; =20 /* * This means you called this function _after_ the port was @@ -593,24 +589,13 @@ static ssize_t uart_write(struct tty_struct *tty, con= st u8 *buf, size_t count) return -EL3HLT; =20 port =3D uart_port_lock(state, flags); - circ =3D &state->xmit; - if (!circ->buf) { + if (WARN_ON_ONCE(!state->port.xmit_buf)) { uart_port_unlock(port, flags); return 0; } =20 - while (port) { - c =3D CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); - if (count < c) - c =3D count; - if (c <=3D 0) - break; - memcpy(circ->buf + circ->head, buf, c); - circ->head =3D (circ->head + c) & (UART_XMIT_SIZE - 1); - buf +=3D c; - count -=3D c; - ret +=3D c; - } + if (port) + ret =3D kfifo_in(&state->port.xmit_fifo, buf, count); =20 __uart_start(state); uart_port_unlock(port, flags); @@ -625,7 +610,7 @@ static unsigned int uart_write_room(struct tty_struct *= tty) unsigned int ret; =20 port =3D uart_port_lock(state, flags); - ret =3D uart_circ_chars_free(&state->xmit); + ret =3D kfifo_avail(&state->port.xmit_fifo); uart_port_unlock(port, flags); return ret; } @@ -638,7 +623,7 @@ static unsigned int uart_chars_in_buffer(struct tty_str= uct *tty) unsigned int ret; =20 port =3D uart_port_lock(state, flags); - ret =3D uart_circ_chars_pending(&state->xmit); + ret =3D kfifo_len(&state->port.xmit_fifo); uart_port_unlock(port, flags); return ret; } @@ -661,7 +646,7 @@ static void uart_flush_buffer(struct tty_struct *tty) port =3D uart_port_lock(state, flags); if (!port) return; - uart_circ_clear(&state->xmit); + kfifo_reset(&state->port.xmit_fifo); if (port->ops->flush_buffer) port->ops->flush_buffer(port); uart_port_unlock(port, flags); @@ -1064,7 +1049,7 @@ static int uart_get_lsr_info(struct tty_struct *tty, * interrupt happens). */ if (uport->x_char || - ((uart_circ_chars_pending(&state->xmit) > 0) && + (!kfifo_is_empty(&state->port.xmit_fifo) && !uart_tx_stopped(uport))) result &=3D ~TIOCSER_TEMT; =20 @@ -1788,8 +1773,9 @@ static void uart_tty_port_shutdown(struct tty_port *p= ort) * Free the transmit buffer. */ uart_port_lock_irq(uport); - buf =3D state->xmit.buf; - state->xmit.buf =3D NULL; + buf =3D port->xmit_buf; + port->xmit_buf =3D NULL; + INIT_KFIFO(port->xmit_fifo); uart_port_unlock_irq(uport); =20 free_page((unsigned long)buf); diff --git a/drivers/tty/serial/serial_port.c b/drivers/tty/serial/serial_p= ort.c index 22b9eeb23e68..3408c8827561 100644 --- a/drivers/tty/serial/serial_port.c +++ b/drivers/tty/serial/serial_port.c @@ -23,7 +23,7 @@ static int __serial_port_busy(struct uart_port *port) { return !uart_tx_stopped(port) && - uart_circ_chars_pending(&port->state->xmit); + !kfifo_is_empty(&port->state->port.xmit_fifo); } =20 static int serial_port_runtime_resume(struct device *dev) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index e512eaa57ed5..97031db26ae4 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -585,7 +585,7 @@ static void sci_start_tx(struct uart_port *port) sci_serial_out(port, SCSCR, new); } =20 - 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)) { if (s->cfg->regtype =3D=3D SCIx_RZ_SCIFA_REGTYPE) /* Switch irq from SCIF to DMA */ @@ -817,7 +817,7 @@ static int sci_rxfill(struct uart_port *port) =20 static void sci_transmit_chars(struct uart_port *port) { - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; unsigned int stopped =3D uart_tx_stopped(port); unsigned short status; unsigned short ctrl; @@ -826,7 +826,7 @@ static void sci_transmit_chars(struct uart_port *port) status =3D sci_serial_in(port, SCxSR); if (!(status & SCxSR_TDxE(port))) { ctrl =3D sci_serial_in(port, SCSCR); - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) ctrl &=3D ~SCSCR_TIE; else ctrl |=3D SCSCR_TIE; @@ -842,15 +842,14 @@ static void sci_transmit_chars(struct uart_port *port) if (port->x_char) { c =3D port->x_char; port->x_char =3D 0; - } else if (!uart_circ_empty(xmit) && !stopped) { - c =3D xmit->buf[xmit->tail]; - xmit->tail =3D (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - } else if (port->type =3D=3D PORT_SCI && uart_circ_empty(xmit)) { - ctrl =3D sci_serial_in(port, SCSCR); - ctrl &=3D ~SCSCR_TE; - sci_serial_out(port, SCSCR, ctrl); - return; - } else { + } else if (stopped || !kfifo_get(&tport->xmit_fifo, &c)) { + if (port->type =3D=3D PORT_SCI && + kfifo_is_empty(&tport->xmit_fifo)) { + ctrl =3D sci_serial_in(port, SCSCR); + ctrl &=3D ~SCSCR_TE; + sci_serial_out(port, SCSCR, ctrl); + return; + } break; } =20 @@ -861,9 +860,9 @@ static void sci_transmit_chars(struct uart_port *port) =20 sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port)); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); - if (uart_circ_empty(xmit)) { + if (kfifo_is_empty(&tport->xmit_fifo)) { if (port->type =3D=3D PORT_SCI) { ctrl =3D sci_serial_in(port, SCSCR); ctrl &=3D ~SCSCR_TIE; @@ -1199,7 +1198,7 @@ static void sci_dma_tx_complete(void *arg) { struct sci_port *s =3D arg; struct uart_port *port =3D &s->port; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; unsigned long flags; =20 dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); @@ -1208,10 +1207,10 @@ static void sci_dma_tx_complete(void *arg) =20 uart_xmit_advance(port, s->tx_dma_len); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 - if (!uart_circ_empty(xmit)) { + if (!kfifo_is_empty(&tport->xmit_fifo)) { s->cookie_tx =3D 0; schedule_work(&s->work_tx); } else { @@ -1424,10 +1423,10 @@ static void sci_dma_tx_work_fn(struct work_struct *= work) struct dma_async_tx_descriptor *desc; struct dma_chan *chan =3D s->chan_tx; struct uart_port *port =3D &s->port; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; unsigned long flags; + unsigned int tail; dma_addr_t buf; - int head, tail; =20 /* * DMA is idle now. @@ -1437,10 +1436,9 @@ static void sci_dma_tx_work_fn(struct work_struct *w= ork) * consistent xmit buffer state. */ uart_port_lock_irq(port); - head =3D xmit->head; - tail =3D xmit->tail; + s->tx_dma_len =3D kfifo_out_linear(&tport->xmit_fifo, &tail, + UART_XMIT_SIZE); buf =3D s->tx_dma_addr + tail; - s->tx_dma_len =3D CIRC_CNT_TO_END(head, tail, UART_XMIT_SIZE); if (!s->tx_dma_len) { /* Transmit buffer has been flushed */ uart_port_unlock_irq(port); @@ -1469,8 +1467,8 @@ static void sci_dma_tx_work_fn(struct work_struct *wo= rk) } =20 uart_port_unlock_irq(port); - dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n", - __func__, xmit->buf, tail, head, s->cookie_tx); + dev_dbg(port->dev, "%s: %p: %u, cookie %d\n", + __func__, tport->xmit_buf, tail, s->cookie_tx); =20 dma_async_issue_pending(chan); return; @@ -1585,6 +1583,7 @@ static struct dma_chan *sci_request_dma_chan(struct u= art_port *port, static void sci_request_dma(struct uart_port *port) { struct sci_port *s =3D to_sci_port(port); + struct tty_port *tport =3D &port->state->port; struct dma_chan *chan; =20 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) { /* UART circular tx buffer is an aligned page. */ s->tx_dma_addr =3D dma_map_single(chan->device->dev, - port->state->xmit.buf, + tport->xmit_buf, UART_XMIT_SIZE, DMA_TO_DEVICE); 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 { dev_dbg(port->dev, "%s: mapped %lu@%p to %pad\n", __func__, UART_XMIT_SIZE, - port->state->xmit.buf, &s->tx_dma_addr); + tport->xmit_buf, &s->tx_dma_addr); =20 INIT_WORK(&s->work_tx, sci_dma_tx_work_fn); s->chan_tx_saved =3D s->chan_tx =3D chan; diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_ser= ial.c index 15f14fa593da..3fc54cc02a1f 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -227,13 +227,13 @@ static int sprd_tx_buf_remap(struct uart_port *port) { struct sprd_uart_port *sp =3D container_of(port, struct sprd_uart_port, port); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; + unsigned char *tail; =20 - sp->tx_dma.trans_len =3D - CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + sp->tx_dma.trans_len =3D kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, + UART_XMIT_SIZE); =20 - sp->tx_dma.phys_addr =3D dma_map_single(port->dev, - (void *)&(xmit->buf[xmit->tail]), + sp->tx_dma.phys_addr =3D dma_map_single(port->dev, tail, sp->tx_dma.trans_len, DMA_TO_DEVICE); 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 =3D (struct uart_port *)data; struct sprd_uart_port *sp =3D container_of(port, struct sprd_uart_port, port); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; unsigned long flags; =20 uart_port_lock_irqsave(port, &flags); @@ -253,10 +253,10 @@ static void sprd_complete_tx_dma(void *data) =20 uart_xmit_advance(port, sp->tx_dma.trans_len); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 - 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)) sp->tx_dma.trans_len =3D 0; =20 @@ -319,7 +319,7 @@ static void sprd_start_tx_dma(struct uart_port *port) { struct sprd_uart_port *sp =3D container_of(port, struct sprd_uart_port, port); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; =20 if (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; } =20 - 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); return; } diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index a23e59551848..f91753a40a69 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -387,9 +387,9 @@ static unsigned int asc_get_mctrl(struct uart_port *por= t) /* There are probably characters waiting to be transmitted. */ static void asc_start_tx(struct uart_port *port) { - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; =20 - if (!uart_circ_empty(xmit)) + if (!kfifo_is_empty(&tport->xmit_fifo)) asc_enable_tx_interrupts(port); } =20 diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-us= art.c index 58d169e5c1db..8c66abcfe6ca 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -696,18 +696,23 @@ static void stm32_usart_transmit_chars_pio(struct uar= t_port *port) { struct stm32_port *stm32_port =3D to_stm32_port(port); const struct stm32_usart_offsets *ofs =3D &stm32_port->info->ofs; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; + + while (1) { + unsigned char ch; =20 - while (!uart_circ_empty(xmit)) { /* Check that TDR is empty before filling FIFO */ if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) 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); } =20 /* 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); else 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) { struct stm32_port *stm32port =3D to_stm32_port(port); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; struct dma_async_tx_descriptor *desc =3D NULL; unsigned int count; int ret; @@ -728,25 +733,8 @@ static void stm32_usart_transmit_chars_dma(struct uart= _port *port) return; } =20 - count =3D uart_circ_chars_pending(xmit); - - if (count > TX_BUF_L) - count =3D TX_BUF_L; - - if (xmit->tail < xmit->head) { - memcpy(&stm32port->tx_buf[0], &xmit->buf[xmit->tail], count); - } else { - size_t one =3D UART_XMIT_SIZE - xmit->tail; - size_t two; - - if (one > count) - one =3D count; - two =3D count - one; - - memcpy(&stm32port->tx_buf[0], &xmit->buf[xmit->tail], one); - if (two) - memcpy(&stm32port->tx_buf[one], &xmit->buf[0], two); - } + count =3D kfifo_out_peek(&tport->xmit_fifo, &stm32port->tx_buf[0], + TX_BUF_L); =20 desc =3D dmaengine_prep_slave_single(stm32port->tx_ch, stm32port->tx_dma_buf, @@ -792,14 +780,14 @@ static void stm32_usart_transmit_chars(struct uart_po= rt *port) { struct stm32_port *stm32_port =3D to_stm32_port(port); const struct stm32_usart_offsets *ofs =3D &stm32_port->info->ofs; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; u32 isr; int ret; =20 if (!stm32_port->hw_flow_control && port->rs485.flags & SER_RS485_ENABLED && (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_rs485_rts_enable(port); } @@ -826,7 +814,7 @@ static void stm32_usart_transmit_chars(struct uart_port= *port) return; } =20 - 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); return; } @@ -841,10 +829,10 @@ static void stm32_usart_transmit_chars(struct uart_po= rt *port) else stm32_usart_transmit_chars_pio(port); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 - if (uart_circ_empty(xmit)) { + if (kfifo_is_empty(&tport->xmit_fifo)) { stm32_usart_tx_interrupt_disable(port); if (!stm32_port->hw_flow_control && 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. */ static void stm32_usart_start_tx(struct uart_port *port) { - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; =20 - if (uart_circ_empty(xmit) && !port->x_char) { + if (kfifo_is_empty(&tport->xmit_fifo) && !port->x_char) { stm32_usart_rs485_rts_disable(port); return; } diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index 8d612ab80680..7f60679fdde1 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c @@ -39,10 +39,13 @@ static char *con_read_page; =20 static int hung_up =3D 0; =20 -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)) { - long status =3D sun4v_con_putchar(xmit->buf[xmit->tail]); + unsigned char ch; + + while (kfifo_peek(&tport->xmit_fifo, &ch)) { + long status =3D sun4v_con_putchar(ch); =20 if (status !=3D HV_EOK) break; @@ -51,14 +54,16 @@ static void transmit_chars_putchar(struct uart_port *po= rt, struct circ_buf *xmit } } =20 -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)) { - unsigned long ra =3D __pa(xmit->buf + xmit->tail); - unsigned long len, status, sent; + while (!kfifo_is_empty(&tport->xmit_fifo)) { + unsigned long len, ra, status, sent; + unsigned char *tail; + + len =3D kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, + UART_XMIT_SIZE); + ra =3D __pa(tail); =20 - len =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, - UART_XMIT_SIZE); status =3D sun4v_con_write(ra, len, &sent); if (status !=3D HV_EOK) break; @@ -165,7 +170,7 @@ static int receive_chars_read(struct uart_port *port) } =20 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); }; =20 @@ -196,18 +201,18 @@ static struct tty_port *receive_chars(struct uart_por= t *port) =20 static void transmit_chars(struct uart_port *port) { - struct circ_buf *xmit; + struct tty_port *tport; =20 if (!port->state) return; =20 - xmit =3D &port->state->xmit; - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + tport =3D &port->state->port; + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) return; =20 - sunhv_ops->transmit_chars(port, xmit); + sunhv_ops->transmit_chars(port, tport); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); } =20 diff --git a/drivers/tty/serial/sunplus-uart.c b/drivers/tty/serial/sunplus= -uart.c index f5e29eb4a4ce..abf7c449308d 100644 --- a/drivers/tty/serial/sunplus-uart.c +++ b/drivers/tty/serial/sunplus-uart.c @@ -200,7 +200,7 @@ static void sunplus_break_ctl(struct uart_port *port, i= nt ctl) =20 static void transmit_chars(struct uart_port *port) { - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; =20 if (port->x_char) { sp_uart_put_char(port, port->x_char); @@ -209,22 +209,24 @@ static void transmit_chars(struct uart_port *port) return; } =20 - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) { sunplus_stop_tx(port); return; } =20 do { - sp_uart_put_char(port, xmit->buf[xmit->tail]); - uart_xmit_advance(port, 1); - if (uart_circ_empty(xmit)) + unsigned char ch; + + if (!uart_fifo_get(port, &ch)) break; + + sp_uart_put_char(port, ch); } while (sunplus_tx_buf_not_full(port)); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) sunplus_stop_tx(port); } =20 diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index 1ea2f33a07a7..1acbe2fba746 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c @@ -232,7 +232,7 @@ static void sunsab_tx_idle(struct uart_sunsab_port *); static void transmit_chars(struct uart_sunsab_port *up, union sab82532_irq_status *stat) { - struct circ_buf *xmit =3D &up->port.state->xmit; + struct tty_port *tport =3D &up->port.state->port; int i; =20 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); sunsab_tx_idle(up); =20 - 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 |=3D SAB82532_IMR1_XPR; writeb(up->interrupt_mask1, &up->regs->w.imr1); return; @@ -265,21 +265,22 @@ static void transmit_chars(struct uart_sunsab_port *u= p, /* Stuff 32 bytes into Transmit FIFO. */ clear_bit(SAB82532_XPR, &up->irqflags); for (i =3D 0; i < up->port.fifosize; i++) { - writeb(xmit->buf[xmit->tail], - &up->regs->w.xfifo[i]); - uart_xmit_advance(&up->port, 1); - if (uart_circ_empty(xmit)) + unsigned char ch; + + if (!uart_fifo_get(&up->port, &ch)) break; + + writeb(ch, &up->regs->w.xfifo[i]); } =20 /* Issue a Transmit Frame command. */ sunsab_cec_wait(up); writeb(SAB82532_CMDR_XF, &up->regs->w.cmdr); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&up->port); =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) sunsab_stop_tx(&up->port); } =20 @@ -435,10 +436,10 @@ static void sunsab_start_tx(struct uart_port *port) { struct uart_sunsab_port *up =3D container_of(port, struct uart_sunsab_port, port); - struct circ_buf *xmit =3D &up->port.state->xmit; + struct tty_port *tport =3D &up->port.state->port; int i; =20 - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) return; =20 up->interrupt_mask1 &=3D ~(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); =20 for (i =3D 0; i < up->port.fifosize; i++) { - writeb(xmit->buf[xmit->tail], - &up->regs->w.xfifo[i]); - uart_xmit_advance(&up->port, 1); - if (uart_circ_empty(xmit)) + unsigned char ch; + + if (!uart_fifo_get(&up->port, &ch)) break; + + writeb(ch, &up->regs->w.xfifo[i]); } =20 /* Issue a Transmit Frame command. */ diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index c8b65f4b2710..67a5fc70bb4b 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -396,7 +396,8 @@ receive_chars(struct uart_sunsu_port *up, unsigned char= *status) =20 static void transmit_chars(struct uart_sunsu_port *up) { - struct circ_buf *xmit =3D &up->port.state->xmit; + struct tty_port *tport =3D &up->port.state->port; + unsigned char ch; int count; =20 if (up->port.x_char) { @@ -409,23 +410,23 @@ static void transmit_chars(struct uart_sunsu_port *up) sunsu_stop_tx(&up->port); return; } - if (uart_circ_empty(xmit)) { + if (kfifo_is_empty(&tport->xmit_fifo)) { __stop_tx(up); return; } =20 count =3D up->port.fifosize; do { - serial_out(up, UART_TX, xmit->buf[xmit->tail]); - uart_xmit_advance(&up->port, 1); - if (uart_circ_empty(xmit)) + if (!uart_fifo_get(&up->port, &ch)) break; + + serial_out(up, UART_TX, ch); } while (--count > 0); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&up->port); =20 - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) __stop_tx(up); } =20 diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index c99289c6c8f8..71758ad4241c 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -453,7 +453,8 @@ static void sunzilog_status_handle(struct uart_sunzilog= _port *up, static void sunzilog_transmit_chars(struct uart_sunzilog_port *up, struct zilog_channel __iomem *channel) { - struct circ_buf *xmit; + struct tty_port *tport; + unsigned char ch; =20 if (ZS_IS_CONS(up)) { unsigned char status =3D readb(&channel->control); @@ -496,21 +497,20 @@ static void sunzilog_transmit_chars(struct uart_sunzi= log_port *up, =20 if (up->port.state =3D=3D NULL) goto ack_tx_int; - xmit =3D &up->port.state->xmit; - if (uart_circ_empty(xmit)) - goto ack_tx_int; + tport =3D &up->port.state->port; =20 if (uart_tx_stopped(&up->port)) goto ack_tx_int; =20 + if (!uart_fifo_get(&up->port, &ch)) + goto ack_tx_int; + up->flags |=3D SUNZILOG_FLAG_TX_ACTIVE; - writeb(xmit->buf[xmit->tail], &channel->data); + writeb(ch, &channel->data); ZSDELAY(); ZS_WSYNC(channel); =20 - uart_xmit_advance(&up->port, 1); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&up->port); =20 return; @@ -700,17 +700,16 @@ static void sunzilog_start_tx(struct uart_port *port) port->icount.tx++; port->x_char =3D 0; } else { - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; + unsigned char ch; =20 - if (uart_circ_empty(xmit)) + if (!uart_fifo_get(&up->port, &ch)) return; - writeb(xmit->buf[xmit->tail], &channel->data); + writeb(ch, &channel->data); ZSDELAY(); ZS_WSYNC(channel); =20 - uart_xmit_advance(port, 1); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&up->port); } } diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c index d9c78320eb02..21ca5fcadf49 100644 --- a/drivers/tty/serial/tegra-tcu.c +++ b/drivers/tty/serial/tegra-tcu.c @@ -91,15 +91,17 @@ static void tegra_tcu_write(struct tegra_tcu *tcu, cons= t char *s, static void tegra_tcu_uart_start_tx(struct uart_port *port) { struct tegra_tcu *tcu =3D port->private_data; - struct circ_buf *xmit =3D &port->state->xmit; - unsigned long count; + struct tty_port *tport =3D &port->state->port; + unsigned char *tail; + unsigned int count; =20 for (;;) { - count =3D CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + count =3D kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, + UART_XMIT_SIZE); if (!count) break; =20 - tegra_tcu_write(tcu, &xmit->buf[xmit->tail], count); + tegra_tcu_write(tcu, tail, count); uart_xmit_advance(port, count); } =20 diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c index 4bc89a9b380a..43fa0938b5e3 100644 --- a/drivers/tty/serial/timbuart.c +++ b/drivers/tty/serial/timbuart.c @@ -95,14 +95,11 @@ static void timbuart_rx_chars(struct uart_port *port) =20 static void timbuart_tx_chars(struct uart_port *port) { - struct circ_buf *xmit =3D &port->state->xmit; + unsigned char ch; =20 while (!(ioread32(port->membase + TIMBUART_ISR) & TXBF) && - !uart_circ_empty(xmit)) { - iowrite8(xmit->buf[xmit->tail], - port->membase + TIMBUART_TXFIFO); - uart_xmit_advance(port, 1); - } + uart_fifo_get(port, &ch)) + iowrite8(ch, port->membase + TIMBUART_TXFIFO); =20 dev_dbg(port->dev, "%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 *p= ort, u32 isr, u32 *ier) { struct timbuart_port *uart =3D container_of(port, struct timbuart_port, port); - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; =20 - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) return; =20 if (port->x_char) @@ -130,7 +127,7 @@ static void timbuart_handle_tx_port(struct uart_port *p= ort, u32 isr, u32 *ier) /* clear all TX interrupts */ iowrite32(TXFLAGS, port->membase + TIMBUART_ISR); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); } else /* Re-enable any tx interrupt */ @@ -141,7 +138,7 @@ static void timbuart_handle_tx_port(struct uart_port *p= ort, u32 isr, u32 *ier) * we wake up the upper layer later when we got the interrupt * to give it some time to go out... */ - if (!uart_circ_empty(xmit)) + if (!kfifo_is_empty(&tport->xmit_fifo)) *ier |=3D TXBAE; =20 dev_dbg(port->dev, "%s - leaving\n", __func__); diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index 10ba41b7be99..68357ac8ffe3 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -189,7 +189,8 @@ static int ulite_receive(struct uart_port *port, int st= at) =20 static int ulite_transmit(struct uart_port *port, int stat) { - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; + unsigned char ch; =20 if (stat & ULITE_STATUS_TXFULL) return 0; @@ -201,14 +202,16 @@ static int ulite_transmit(struct uart_port *port, int= stat) return 1; } =20 - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + if (uart_tx_stopped(port)) + return 0; + + if (!uart_fifo_get(port, &ch)) return 0; =20 - uart_out32(xmit->buf[xmit->tail], ULITE_TX, port); - uart_xmit_advance(port, 1); + uart_out32(ch, ULITE_TX, port); =20 /* wake up */ - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 return 1; diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 397b95dff7ed..53bb8c5ef499 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c @@ -334,7 +334,7 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port) unsigned char *p; unsigned int count; struct uart_port *port =3D &qe_port->port; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; =20 /* Handle xon/xoff */ if (port->x_char) { @@ -358,7 +358,7 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port) return 1; } =20 - 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); return 0; } @@ -366,16 +366,10 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_po= rt) /* Pick next descriptor and fill from buffer */ bdp =3D qe_port->tx_cur; =20 - while (!(ioread16be(&bdp->status) & BD_SC_READY) && !uart_circ_empty(xmit= )) { - count =3D 0; + while (!(ioread16be(&bdp->status) & BD_SC_READY) && + !kfifo_is_empty(&tport->xmit_fifo)) { p =3D qe2cpu_addr(ioread32be(&bdp->buf), qe_port); - while (count < qe_port->tx_fifosize) { - *p++ =3D xmit->buf[xmit->tail]; - uart_xmit_advance(port, 1); - count++; - if (uart_circ_empty(xmit)) - break; - } + count =3D uart_fifo_out(port, p, qe_port->tx_fifosize); =20 iowrite16be(count, &bdp->length); qe_setbits_be16(&bdp->status, BD_SC_READY); @@ -388,10 +382,10 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_po= rt) } qe_port->tx_cur =3D bdp; =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 - if (uart_circ_empty(xmit)) { + if (kfifo_is_empty(&tport->xmit_fifo)) { /* The kernel buffer is empty, so turn off TX interrupts. We don't need to be told when the QE is finished transmitting the data. */ diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx= _uartps.c index 5f48ec37cb25..de3487206bcb 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -425,32 +425,32 @@ static void cdns_uart_handle_tx(void *dev_id) { struct uart_port *port =3D (struct uart_port *)dev_id; struct cdns_uart *cdns_uart =3D port->private_data; - struct circ_buf *xmit =3D &port->state->xmit; + struct tty_port *tport =3D &port->state->port; unsigned int numbytes; + unsigned char ch; =20 - 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 */ writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR); return; } =20 numbytes =3D port->fifosize; - while (numbytes && !uart_circ_empty(xmit) && - !(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)) { - - writel(xmit->buf[xmit->tail], port->membase + CDNS_UART_FIFO); - uart_xmit_advance(port, 1); + while (numbytes && + !(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL) && + uart_fifo_get(port, &ch)) { + writel(ch, port->membase + CDNS_UART_FIFO); numbytes--; } =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); =20 /* Enable the TX Empty interrupt */ writel(CDNS_UART_IXR_TXEMPTY, cdns_uart->port->membase + CDNS_UART_IER); =20 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 =3D &cdns_rs485_rx_callback; hrtimer_start(&cdns_uart->tx_timer, ns_to_ktime(cdns_calc_after_tx_delay(cdns_uart)), HRTIMER_MODE_RE= L); @@ -723,7 +723,7 @@ static void cdns_uart_start_tx(struct uart_port *port) status |=3D CDNS_UART_CR_TX_EN; writel(status, port->membase + CDNS_UART_CR); =20 - if (uart_circ_empty(&port->state->xmit)) + if (kfifo_is_empty(&port->state->port.xmit_fifo)) return; =20 /* Clear the TX Empty interrupt */ diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c index 65ca4da6e368..79ea7108a0f3 100644 --- a/drivers/tty/serial/zs.c +++ b/drivers/tty/serial/zs.c @@ -606,7 +606,8 @@ static void zs_receive_chars(struct zs_port *zport) =20 static void zs_raw_transmit_chars(struct zs_port *zport) { - struct circ_buf *xmit =3D &zport->port.state->xmit; + struct tty_port *tport =3D &zport->port.state->port; + unsigned char ch; =20 /* XON/XOFF chars. */ if (zport->port.x_char) { @@ -617,20 +618,20 @@ static void zs_raw_transmit_chars(struct zs_port *zpo= rt) } =20 /* 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); return; } =20 /* Send char. */ - write_zsdata(zport, xmit->buf[xmit->tail]); - uart_xmit_advance(&zport->port, 1); + write_zsdata(zport, ch); =20 - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&zport->port); =20 /* Are we are done? */ - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) zs_raw_stop_tx(zport); } =20 diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 0a0f6e21d40e..8cb65f50e830 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -699,7 +698,6 @@ struct uart_state { struct tty_port port; =20 enum uart_pm_state pm_state; - struct circ_buf xmit; =20 atomic_t refcount; 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 ch= ars) { - struct circ_buf *xmit =3D &up->state->xmit; + struct tty_port *tport =3D &up->state->port; =20 - xmit->tail =3D (xmit->tail + chars) & (UART_XMIT_SIZE - 1); + kfifo_skip_count(&tport->xmit_fifo, chars); up->icount.tx +=3D chars; } =20 +static inline unsigned int uart_fifo_out(struct uart_port *up, + unsigned char *buf, unsigned int chars) +{ + struct tty_port *tport =3D &up->state->port; + + chars =3D kfifo_out(&tport->xmit_fifo, buf, chars); + up->icount.tx +=3D chars; + + return chars; +} + +static inline unsigned int uart_fifo_get(struct uart_port *up, + unsigned char *ch) +{ + struct tty_port *tport =3D &up->state->port; + unsigned int chars; + + chars =3D kfifo_get(&tport->xmit_fifo, ch); + up->icount.tx +=3D chars; + + return chars; +} + struct module; struct tty_driver; =20 @@ -764,7 +785,7 @@ enum UART_TX_FLAGS { for_test, for_post) \ ({ \ struct uart_port *__port =3D (uport); \ - struct circ_buf *xmit =3D &__port->state->xmit; \ + struct tty_port *__tport =3D &__port->state->port; \ unsigned int pending; \ \ for (; (for_test) && (tx_ready); (for_post), __port->icount.tx++) { \ @@ -775,17 +796,18 @@ enum UART_TX_FLAGS { continue; \ } \ \ - if (uart_circ_empty(xmit) || uart_tx_stopped(__port)) \ + if (uart_tx_stopped(__port)) \ + break; \ + \ + if (!kfifo_get(&__tport->xmit_fifo, &(ch))) \ break; \ \ - (ch) =3D xmit->buf[xmit->tail]; \ (put_char); \ - xmit->tail =3D (xmit->tail + 1) % UART_XMIT_SIZE; \ } \ \ (tx_done); \ \ - pending =3D uart_circ_chars_pending(xmit); \ + pending =3D kfifo_len(&__tport->xmit_fifo); \ if (pending < WAKEUP_CHARS) { \ 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_resume_port(struct uart_driver *reg, struct uart_port *port); =20 -#define uart_circ_empty(circ) ((circ)->head =3D=3D (circ)->tail) -#define uart_circ_clear(circ) ((circ)->head =3D (circ)->tail =3D 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) { struct tty_struct *tty =3D port->state->port.tty; --=20 2.44.0