[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <64feeb9e-0e28-0441-4d42-20e3f5ec7a7a@microchip.com>
Date: Fri, 25 Mar 2022 08:57:12 +0000
From: <Claudiu.Beznea@...rochip.com>
To: <tomas.melin@...sala.com>, <netdev@...r.kernel.org>
CC: <Nicolas.Ferre@...rochip.com>, <davem@...emloft.net>,
<kuba@...nel.org>, <pabeni@...hat.com>
Subject: Re: [PATCH] net: macb: Restart tx only if queue pointer is lagging
On 25.03.2022 08:50, Tomas Melin wrote:
> [Some people who received this message don't often get email from tomas.melin@...sala.com. Learn why this is important at http://aka.ms/LearnAboutSenderIdentification.]
>
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
> commit 5ea9c08a8692 ("net: macb: restart tx after tx used bit read")
> added support for restarting transmission. Restarting tx does not work
> in case controller asserts TXUBR interrupt and TQBP is already at the end
> of the tx queue. In that situation, restarting tx will immediately cause
> assertion of another TXUBR interrupt. The driver will end up in an infinite
> interrupt loop which it cannot break out of.
>
> For cases where TQBP is at the end of the tx queue, instead
> only clear TXUBR interrupt. As more data gets pushed to the queue,
> transmission will resume.
>
> This issue was observed on a Xilinx Zynq based board. During stress test of
> the network interface, driver would get stuck on interrupt loop
> within seconds or minutes causing CPU to stall.
>
> Signed-off-by: Tomas Melin <tomas.melin@...sala.com>
> ---
> drivers/net/ethernet/cadence/macb_main.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
> index 800d5ced5800..e475be29845c 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -1658,6 +1658,7 @@ static void macb_tx_restart(struct macb_queue *queue)
> unsigned int head = queue->tx_head;
> unsigned int tail = queue->tx_tail;
> struct macb *bp = queue->bp;
> + unsigned int head_idx, tbqp;
>
> if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
> queue_writel(queue, ISR, MACB_BIT(TXUBR));
> @@ -1665,6 +1666,13 @@ static void macb_tx_restart(struct macb_queue *queue)
> if (head == tail)
> return;
>
> + tbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(bp);
> + tbqp = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, tbqp));
> + head_idx = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, head));
> +
> + if (tbqp == head_idx)
> + return;
> +
This looks like TBQP is not advancing though there are packets in the
software queues (head != tail). Packets are added in the software queues on
TX path and removed when TX was done for them.
Maybe TX_WRAP is missing on one TX descriptor? Few months ago while
investigating some other issues on this I found that this might be missed
on one descriptor [1] but haven't managed to make it break at that point
anyhow.
Could you check on your side if this is solving your issue?
/* Set 'TX_USED' bit in buffer descriptor at tx_head position
* to set the end of TX queue
*/
i = tx_head;
entry = macb_tx_ring_wrap(bp, i);
ctrl = MACB_BIT(TX_USED);
+ if (entry == bp->tx_ring_size - 1)
+ ctrl |= MACB_BIT(TX_WRAP);
desc = macb_tx_desc(queue, entry);
desc->ctrl = ctrl;
[1]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/cadence/macb_main.c#n1958
> macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
> }
>
> --
> 2.35.1
>
Powered by blists - more mailing lists