From: "Måns Rullgård" <mans@mansr.com>
To: Jiri Slaby <jirislaby@kernel.org>
Cc: gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org,
linux-serial@vger.kernel.org, linux-omap@vger.kernel.org,
stable@vger.kernel.org
Subject: Re: [PATCH v2 1/2] tty: serial: 8250_omap: fix tx with dma
Date: Wed, 07 May 2025 08:49:50 +0100 [thread overview]
Message-ID: <yw1xwmaslv1d.fsf@mansr.com> (raw)
In-Reply-To: <d51b4422-0c46-4b03-840b-302603b3136f@kernel.org> (Jiri Slaby's message of "Wed, 7 May 2025 08:05:35 +0200")
Jiri Slaby <jirislaby@kernel.org> writes:
> On 06. 05. 25, 17:07, Mans Rullgard wrote:
>> Commit 1788cf6a91d9 ("tty: serial: switch from circ_buf to kfifo")
>> introduced an error in the TX DMA handling for 8250_omap.
>> When the OMAP_DMA_TX_KICK flag is set, one byte is pulled from the
>> kfifo and emitted directly in order to start the DMA. This is done
>> without updating DMA tx_size which leads to uart_xmit_advance() called
>> in the DMA complete callback advancing the kfifo by one too much.
>> In practice, transmitting N bytes has been seen to result in the last
>> N-1 bytes being sent repeatedly.
>> This change fixes the problem by moving all of the dma setup after
>> the OMAP_DMA_TX_KICK handling and using kfifo_len() instead of the
>> dma size for the 4-byte cutoff check. This slightly changes the
>> behaviour at buffer wraparound, but it still transmits the correct
>> bytes somehow. At the point kfifo_dma_out_prepare_mapped is called,
>> at least one byte is guaranteed to be in the fifo, so checking the
>> return value is not necessary.
>> Fixes: 1788cf6a91d9 ("tty: serial: switch from circ_buf to kfifo")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Mans Rullgard <mans@mansr.com>
>> ---
>> v2: split patch in two
>> ---
>> drivers/tty/serial/8250/8250_omap.c | 24 +++++++++---------------
>> 1 file changed, 9 insertions(+), 15 deletions(-)
>> diff --git a/drivers/tty/serial/8250/8250_omap.c
>> b/drivers/tty/serial/8250/8250_omap.c
>> index f1aee915bc02..180466e09605 100644
>> --- a/drivers/tty/serial/8250/8250_omap.c
>> +++ b/drivers/tty/serial/8250/8250_omap.c
>> @@ -1173,16 +1173,6 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
>> return 0;
>> }
>> - sg_init_table(&sg, 1);
>> - ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1,
>> - UART_XMIT_SIZE, dma->tx_addr);
>> - if (ret != 1) {
>> - serial8250_clear_THRI(p);
>> - return 0;
>> - }
>> -
>> - dma->tx_size = sg_dma_len(&sg);
>> -
>> if (priv->habit & OMAP_DMA_TX_KICK) {
>> unsigned char c;
>> u8 tx_lvl;
> ...
>> @@ -1216,11 +1206,12 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
>> goto err;
>> }
>> skip_byte = c;
>> - /* now we need to recompute due to kfifo_get */
>> - kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1,
>> - UART_XMIT_SIZE, dma->tx_addr);
>> }
>> + sg_init_table(&sg, 1);
>> + kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1,
>> + UART_XMIT_SIZE, dma->tx_addr);
>
> This can fail (note the first call to this was checked). The latter
> (deliberately) not.
No, it can't. The fifo has already been checked to contain something
right at the top of the function. There is no other failure mode for
kfifo_dma_out_prepare_mapped.
>> +
>> desc = dmaengine_prep_slave_sg(dma->txchan, &sg, 1, DMA_MEM_TO_DEV,
>> DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
>> if (!desc) {
> ...
>> @@ -1248,8 +1240,10 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
>> err:
>> dma->tx_err = 1;
>> out_skip:
>> - if (skip_byte >= 0)
>> + if (skip_byte >= 0) {
>> serial_out(p, UART_TX, skip_byte);
>> + p->port.icount.tx++;
>
> This is still unrelated.
No, it's not. Your broken code called uart_xmit_advance with the full
amount due to the incorrect tx_size value. This compensates for that.
You made this mess. Now fix it. I don't care how. It's wasted enough
of my time already.
--
Måns Rullgård
next prev parent reply other threads:[~2025-05-07 7:49 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-06 15:07 [PATCH v2 1/2] tty: serial: 8250_omap: fix tx with dma Mans Rullgard
2025-05-06 15:07 ` [PATCH 2/2] tty: serial: 8250_omap: use two-entry sg list for tx dma Mans Rullgard
2025-05-07 6:05 ` [PATCH v2 1/2] tty: serial: 8250_omap: fix tx with dma Jiri Slaby
2025-05-07 7:49 ` Måns Rullgård [this message]
2025-05-07 8:09 ` Jiri Slaby
2025-05-07 10:56 ` Måns Rullgård
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=yw1xwmaslv1d.fsf@mansr.com \
--to=mans@mansr.com \
--cc=gregkh@linuxfoundation.org \
--cc=jirislaby@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.