From: "Taedcke, Christian" <christian.taedcke-oss@weidmueller.com>
To: "Théo Lebrun" <theo.lebrun@bootlin.com>,
"Kevin Hao" <haokexin@gmail.com>
Cc: christian.taedcke@weidmueller.com,
Conor Dooley <conor.dooley@microchip.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Clark Williams <clrkwllms@kernel.org>,
Steven Rostedt <rostedt@goodmis.org>,
Robert Hancock <robert.hancock@calian.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-rt-devel@lists.linux.dev, stable@vger.kernel.org
Subject: Re: [PATCH net 1/2] net: macb: reprogram TBQP after shuffling the TX ring on link-up
Date: Tue, 14 Jul 2026 17:35:50 +0200 [thread overview]
Message-ID: <52f6b231-7351-4dbf-92cf-459f1f19d150@weidmueller.com> (raw)
In-Reply-To: <DJUXYXEQMUJ4.31H82KQMG29UC@bootlin.com>
Hello Kevin & Théo,
i recorded some traces and include 2 of them here.
On 7/10/2026 3:56 PM, Théo Lebrun wrote:
> Hello Kevin & Christian,
>
> On Wed Jul 8, 2026 at 5:05 AM CEST, Kevin Hao wrote:
>>> I agree that the TRM says the transmit pointer is reset while TE is low. My
>>> question is whether this describes an internal pointer being reloaded from TBQP,
>>> or whether TBQP itself is restored to the original ring base.
>>
>> The Zynq UltraScale TRM [1] describes the receive-buffer queue pointer as follows:
>>
>> An internal counter represents the receive-buffer queue pointer and it is not
>> visible through the CPU interface.
>>
>> I could not find a similar description for the transmit-buffer queue pointer,
>> but I believe it behaves the same way. From a software perspective, it should
>> be safe to assume that the TBQP is reset to point to the start of the transmit
>> descriptor list upon reset. This assumption is supported by the description
>> of the transmit_q_ptr (GEM) Register [2]:
>>
>> Reading this register returns the location of the descriptor currently being accessed.
>> Since the DMA handles two frames at once, this may not necessarily be pointing to the
>> current frame being transmitted.
>>
>> [1] https://docs.amd.com/v/u/en-US/ug1085-zynq-ultrascale-trm
>> [2] https://docs.amd.com/r/en-US/ug1087-zynq-ultrascale-registers/transmit_q_ptr-GEM-Register
>
> For what it's worth, I agree with Kevin.
>
> It should be rather easy to detect if the patch is needed, with more
> logging. Dump TBQP before link-down & dump it at link-up. The code
> expects TBQP to reset to the ring start automatically whereas this
> commit message says the TBQP after link-up is some offset into the ring.
These traces were captured on a zynqmp device. The patches in this series were not applied.
The traces contain information from both tx queues (q0 and q1).
tbqp contains the value returned by queue_readl(queue, TBQP).
base is lower_32_bits(queue->tx_ring_dma).
tbqp_ctrl contains macb_tx_desc(queue, tbqp_idx)->ctrl.
tail_ctrl contains macb_tx_desc(queue, queue->tx_tail)->ctrl.
At the beginning the link is up and communication over ethernet is working.
The cpu is not at 100% load, everything worked fine.
Trace 1 (everythink works as expected, no high cpu load):
The ethernet link goes down.
Trace from macb_mac_link_down():
kworker/0:4-1679 [000] .N... 141.796925: macb_tx_hw_state: macb_tx_hw_state q0 linkdown_pre_te tbqp=67cd0030 base=67cd0000 ncr=0010001c tsr=00000021 imr=3fffffff head=2 tail=2 tbqp_idx=343 tbqp_ctrl=80000000(used=1) tail_ctrl=80000000(used=1)
kworker/0:4-1679 [000] ..... 141.796958: macb_tx_hw_state: macb_tx_hw_state q1 linkdown_pre_te tbqp=67cda598 base=67cd8000 ncr=0010001c tsr=00000021 imr=00000ce6 head=3985 tail=3985 tbqp_idx=59 tbqp_ctrl=80000036(used=1) tail_ctrl=80000000(used=1)
ctrl = macb_readl(bp, NCR) & ~(MACB_BIT(RE) | MACB_BIT(TE));
macb_writel(bp, NCR, ctrl);
kworker/0:4-1679 [000] ..... 141.796961: macb_tx_hw_state: macb_tx_hw_state q0 linkdown_post_te tbqp=67cd0030 base=67cd0000 ncr=00100010 tsr=00000021 imr=3fffffff head=2 tail=2 tbqp_idx=343 tbqp_ctrl=80000000(used=1) tail_ctrl=80000000(used=1)
kworker/0:4-1679 [000] ..... 141.796964: macb_tx_hw_state: macb_tx_hw_state q1 linkdown_post_te tbqp=67cd8000 base=67cd8000 ncr=00100010 tsr=00000021 imr=00000ce6 head=3985 tail=3985 tbqp_idx=170 tbqp_ctrl=0000800f(used=0) tail_ctrl=80000000(used=1)
Ethernet link goes up.
Trace from macb_mac_link_up():
kworker/0:3-190 [000] ..... 152.966203: macb_tx_hw_state: macb_tx_hw_state q0 linkup_post_shuffle tbqp=67cd0030 base=67cd0000 ncr=00100010 tsr=00000021 imr=3ffff305 head=0 tail=0 tbqp_idx=343 tbqp_ctrl=80000000(used=1) tail_ctrl=80018040(used=1)
kworker/0:3-190 [000] ..... 152.966206: macb_tx_hw_state: macb_tx_hw_state q1 linkup_post_shuffle tbqp=67cd8000 base=67cd8000 ncr=00100010 tsr=00000021 imr=00000004 head=0 tail=0 tbqp_idx=170 tbqp_ctrl=0000800f(used=0) tail_ctrl=0000800f(used=0)
macb_writel(bp, NCR, ctrl | MACB_BIT(RE) | MACB_BIT(TE));
kworker/0:3-190 [000] ..... 152.966209: macb_tx_hw_state: macb_tx_hw_state q0 linkup_post_te tbqp=67cd0030 base=67cd0000 ncr=0010001c tsr=00000021 imr=3ffff305 head=0 tail=0 tbqp_idx=343 tbqp_ctrl=80000000(used=1) tail_ctrl=80018040(used=1)
kworker/0:3-190 [000] ..... 152.966211: macb_tx_hw_state: macb_tx_hw_state q1 linkup_post_te tbqp=67cd8000 base=67cd8000 ncr=0010001c tsr=00000021 imr=00000004 head=0 tail=0 tbqp_idx=170 tbqp_ctrl=0000800f(used=0) tail_ctrl=0000800f(used=0)
CPU load is normal, no issue in this trace.
tbqp on q0 is not reset to base. But in this case it did not result in the interrupt storm.
Trace 2 (results in interrupt storm):
The ethernet link goes down.
Trace from macb_mac_link_down():
kworker/0:3-95 [000] .N... 459.682957: macb_tx_hw_state: macb_tx_hw_state q0 linkdown_pre_te tbqp=67cd2cb8 base=67cd0000 ncr=0010001c tsr=00000021 imr=3fffffff head=4061 tail=4061 tbqp_idx=306 tbqp_ctrl=0000800f(used=0) tail_ctrl=80000000(used=1)
kworker/0:3-95 [000] ..... 459.682991: macb_tx_hw_state: macb_tx_hw_state q1 linkdown_pre_te tbqp=67cd85a0 base=67cd8000 ncr=0010001c tsr=00000021 imr=00000ce6 head=60 tail=60 tbqp_idx=230 tbqp_ctrl=80000036(used=1) tail_ctrl=80000000(used=1)
ctrl = macb_readl(bp, NCR) & ~(MACB_BIT(RE) | MACB_BIT(TE));
macb_writel(bp, NCR, ctrl);
kworker/0:3-95 [000] ..... 459.682994: macb_tx_hw_state: macb_tx_hw_state q0 linkdown_post_te tbqp=67cd2cb8 base=67cd0000 ncr=00100010 tsr=00000021 imr=3fffffff head=4061 tail=4061 tbqp_idx=306 tbqp_ctrl=0000800f(used=0) tail_ctrl=80000000(used=1)
kworker/0:3-95 [000] ..... 459.682996: macb_tx_hw_state: macb_tx_hw_state q1 linkdown_post_te tbqp=67cd8000 base=67cd8000 ncr=00100010 tsr=00000021 imr=00000ce6 head=60 tail=60 tbqp_idx=170 tbqp_ctrl=80000036(used=1) tail_ctrl=80000000(used=1)
Ethernet link goes up.
Trace from macb_mac_link_up():
kworker/0:3-95 [000] ..... 470.292877: macb_tx_hw_state: macb_tx_hw_state q0 linkup_post_shuffle tbqp=67cd2cb8 base=67cd0000 ncr=00100010 tsr=00000021 imr=3ffff305 head=0 tail=0 tbqp_idx=306 tbqp_ctrl=0000800f(used=0) tail_ctrl=0000800f(used=0)
kworker/0:3-95 [000] ..... 470.292879: macb_tx_hw_state: macb_tx_hw_state q1 linkup_post_shuffle tbqp=67cd8000 base=67cd8000 ncr=00100010 tsr=00000021 imr=00000004 head=0 tail=0 tbqp_idx=170 tbqp_ctrl=80000036(used=1) tail_ctrl=80018040(used=1)
macb_writel(bp, NCR, ctrl | MACB_BIT(RE) | MACB_BIT(TE));
kworker/0:3-95 [000] ..... 470.292882: macb_tx_hw_state: macb_tx_hw_state q0 linkup_post_te tbqp=67cd2cb8 base=67cd0000 ncr=0010001c tsr=00000021 imr=3ffff305 head=0 tail=0 tbqp_idx=306 tbqp_ctrl=0000800f(used=0) tail_ctrl=0000800f(used=0)
kworker/0:3-95 [000] ..... 470.292884: macb_tx_hw_state: macb_tx_hw_state q1 linkup_post_te tbqp=67cd8000 base=67cd8000 ncr=0010001c tsr=00000021 imr=00000004 head=0 tail=0 tbqp_idx=170 tbqp_ctrl=80000036(used=1) tail_ctrl=80018040(used=1)
After that sequence one CPU core is at 100% load continously executing the macb irq handler.
The issue seems to be q0. tbqp of q1 is properly reset to its base address.
tbqp of q0 is not changed as expected in link down when tx is disabled.
Are there any other details i could put into the trace to determine the root cause?
I suspect that some packet is still in transmission/ being processed and this might be the
reason why tbqp of q0 is not being reset. But i do not see that in this trace.
>
> Lastly, the cover letter mentions that [PATCH 1/2] alone isn't enough.
> But it doesn't mention that [PATCH 2/2] alone doesn't solve the issue.
> This would be a useful test as well.
>
> On Tue Jul 7, 2026 at 3:36 PM CEST, Taedcke, Christian wrote:
>> Thank you for the quick review! This is my first Linux kernel
>> contribution, so I appreciate your feedback here.
>
> Welcome!
>
> Thanks,
>
> --
> Théo Lebrun, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com/
>
Regards,
Christian
next prev parent reply other threads:[~2026-07-14 15:35 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-06 14:02 [PATCH net 0/2] net: macb: fix TXUBR interrupt storm on link flapping Christian Taedcke via B4 Relay
2026-07-06 14:02 ` [PATCH net 1/2] net: macb: reprogram TBQP after shuffling the TX ring on link-up Christian Taedcke via B4 Relay
2026-07-06 15:04 ` Sebastian Andrzej Siewior
2026-07-07 13:36 ` Taedcke, Christian
2026-07-10 8:08 ` Sebastian Andrzej Siewior
2026-07-07 9:13 ` Kevin Hao
2026-07-07 14:29 ` Taedcke, Christian
2026-07-08 3:05 ` Kevin Hao
2026-07-10 13:56 ` Théo Lebrun
2026-07-14 15:35 ` Taedcke, Christian [this message]
2026-07-06 14:02 ` [PATCH net 2/2] net: macb: mask TXUBR during TX NAPI poll to prevent IRQ storms Christian Taedcke via B4 Relay
2026-07-06 15:05 ` Sebastian Andrzej Siewior
2026-07-07 13:41 ` Taedcke, Christian
2026-07-10 16:43 ` Théo Lebrun
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=52f6b231-7351-4dbf-92cf-459f1f19d150@weidmueller.com \
--to=christian.taedcke-oss@weidmueller.com \
--cc=andrew+netdev@lunn.ch \
--cc=bigeasy@linutronix.de \
--cc=christian.taedcke@weidmueller.com \
--cc=clrkwllms@kernel.org \
--cc=conor.dooley@microchip.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=haokexin@gmail.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-devel@lists.linux.dev \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=robert.hancock@calian.com \
--cc=rostedt@goodmis.org \
--cc=stable@vger.kernel.org \
--cc=theo.lebrun@bootlin.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox