summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/serial-tegra.c
diff options
context:
space:
mode:
authorJiri Slaby (SUSE) <jirislaby@kernel.org>2024-04-05 08:08:23 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-04-09 15:28:03 +0200
commit1788cf6a91d9fa9aa61fc2917afe192c23d67f6a (patch)
tree38f5efd7c979768ead681553a234a9205e9acbed /drivers/tty/serial/serial-tegra.c
parentf8fef2fa419febbfed2d04f0518111565df2673d (diff)
tty: serial: switch from circ_buf to kfifo
Switch from struct circ_buf to proper kfifo. kfifo provides much better API, esp. when wrap-around of the buffer needs to be taken into account. Look at pl011_dma_tx_refill() or cpm_uart_tx_pump() changes for example. Kfifo API can also fill in scatter-gather DMA structures, so it easier for that use case too. Look at lpuart_dma_tx() for example. Note that not all drivers can be converted to that (like atmel_serial), they handle DMA specially. Note that usb-serial uses kfifo for TX for ages. omap needed a bit more care as it needs to put a char into FIFO to start the DMA transfer when OMAP_DMA_TX_KICK is set. In that case, we have to do kfifo_dma_out_prepare twice: once to find out the tx_size (to find out if it is worths to do DMA at all -- size >= 4), the second time for the actual transfer. All traces of circ_buf are removed from serial_core.h (and its struct uart_state). Signed-off-by: Jiri Slaby (SUSE) <jirislaby@kernel.org> Cc: Al Cooper <alcooperx@gmail.com> Cc: Matthias Brugger <matthias.bgg@gmail.com> Cc: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Cc: Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com> Cc: Tharun Kumar P <tharunkumar.pasumarthi@microchip.com> Cc: Russell King <linux@armlinux.org.uk> Cc: Vineet Gupta <vgupta@kernel.org> Cc: Richard Genoud <richard.genoud@gmail.com> Cc: Nicolas Ferre <nicolas.ferre@microchip.com> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com> Cc: Claudiu Beznea <claudiu.beznea@tuxon.dev> Cc: Alexander Shiyan <shc_work@mail.ru> Cc: Baruch Siach <baruch@tkos.co.il> Cc: Maciej W. Rozycki <macro@orcam.me.uk> Cc: Shawn Guo <shawnguo@kernel.org> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Neil Armstrong <neil.armstrong@linaro.org> Cc: Kevin Hilman <khilman@baylibre.com> Cc: Jerome Brunet <jbrunet@baylibre.com> Cc: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Cc: Taichi Sugaya <sugaya.taichi@socionext.com> Cc: Takao Orito <orito.takao@socionext.com> Cc: Bjorn Andersson <andersson@kernel.org> Cc: Konrad Dybcio <konrad.dybcio@linaro.org> Cc: Pali Rohár <pali@kernel.org> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Nicholas Piggin <npiggin@gmail.com> Cc: Christophe Leroy <christophe.leroy@csgroup.eu> Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org> Cc: Naveen N. Rao <naveen.n.rao@linux.ibm.com> Cc: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Cc: Alim Akhtar <alim.akhtar@samsung.com> Cc: Laxman Dewangan <ldewangan@nvidia.com> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Jonathan Hunter <jonathanh@nvidia.com> Cc: Orson Zhai <orsonzhai@gmail.com> Cc: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: Chunyan Zhang <zhang.lyra@gmail.com> Cc: Patrice Chotard <patrice.chotard@foss.st.com> Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com> Cc: Alexandre Torgue <alexandre.torgue@foss.st.com> Cc: David S. Miller <davem@davemloft.net> Cc: Hammer Hsieh <hammerh0314@gmail.com> Cc: Peter Korsgaard <jacmet@sunsite.dk> Cc: Timur Tabi <timur@kernel.org> Cc: Michal Simek <michal.simek@amd.com> Cc: Sumit Semwal <sumit.semwal@linaro.org> Cc: Christian König <christian.koenig@amd.com> Link: https://lore.kernel.org/r/20240405060826.2521-13-jirislaby@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/serial-tegra.c')
-rw-r--r--drivers/tty/serial/serial-tegra.c43
1 files changed, 24 insertions, 19 deletions
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)
static void tegra_uart_fill_tx_fifo(struct tegra_uart_port *tup, int max_bytes)
{
- struct circ_buf *xmit = &tup->uport.state->xmit;
+ unsigned char ch;
int i;
for (i = 0; i < max_bytes; i++) {
- BUG_ON(uart_circ_empty(xmit));
if (tup->cdata->tx_fifo_full_status) {
unsigned long lsr = 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);
}
}
@@ -514,7 +514,7 @@ static void tegra_uart_start_pio_tx(struct tegra_uart_port *tup,
static void tegra_uart_tx_dma_complete(void *args)
{
struct tegra_uart_port *tup = args;
- struct circ_buf *xmit = &tup->uport.state->xmit;
+ struct tty_port *tport = &tup->uport.state->port;
struct dma_tx_state state;
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 = 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 = &tup->uport.state->xmit;
+ struct tty_port *tport = &tup->uport.state->port;
dma_addr_t tx_phys_addr;
+ unsigned int tail;
tup->tx_bytes = count & ~(0xF);
- tx_phys_addr = tup->tx_dma_buf_phys + xmit->tail;
+ WARN_ON_ONCE(kfifo_out_linear(&tport->xmit_fifo, &tail,
+ UART_XMIT_SIZE) < count);
+ tx_phys_addr = tup->tx_dma_buf_phys + tail;
dma_sync_single_for_device(tup->uport.dev, tx_phys_addr,
tup->tx_bytes, DMA_TO_DEVICE);
@@ -562,18 +565,21 @@ static int tegra_uart_start_tx_dma(struct tegra_uart_port *tup,
static void tegra_uart_start_next_tx(struct tegra_uart_port *tup)
{
+ struct tty_port *tport = &tup->uport.state->port;
+ unsigned char *tail_ptr;
unsigned long tail;
- unsigned long count;
- struct circ_buf *xmit = &tup->uport.state->xmit;
+ unsigned int count;
if (!tup->current_baud)
return;
- tail = (unsigned long)&xmit->buf[xmit->tail];
- count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+ count = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail_ptr,
+ UART_XMIT_SIZE);
if (!count)
return;
+ tail = (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 = to_tegra_uport(u);
- struct circ_buf *xmit = &u->state->xmit;
+ struct tty_port *tport = &u->state->port;
- if (!uart_circ_empty(xmit) && !tup->tx_in_progress)
+ if (!kfifo_is_empty(&tport->xmit_fifo) && !tup->tx_in_progress)
tegra_uart_start_next_tx(tup);
}
@@ -628,11 +634,11 @@ static void tegra_uart_stop_tx(struct uart_port *u)
static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup)
{
- struct circ_buf *xmit = &tup->uport.state->xmit;
+ struct tty_port *tport = &tup->uport.state->port;
tegra_uart_fill_tx_fifo(tup, tup->tx_bytes);
tup->tx_in_progress = 0;
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&tup->uport);
tegra_uart_start_next_tx(tup);
}
@@ -1169,15 +1175,14 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup,
tup->rx_dma_buf_virt = dma_buf;
tup->rx_dma_buf_phys = dma_phys;
} else {
+ dma_buf = tup->uport.state->port.xmit_buf;
dma_phys = 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 = tup->uport.state->xmit.buf;
dma_sconfig.dst_addr = tup->uport.mapbase;
dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_sconfig.dst_maxburst = 16;