From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Wei Fang <wei.fang@nxp.com>
Cc: Clark Wang <xiaoning.wang@nxp.com>,
Oleksij Rempel <o.rempel@pengutronix.de>,
Emanuele Ghidoli <ghidoliemanuele@gmail.com>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
"imx@lists.linux.dev" <imx@lists.linux.dev>,
"linux-arm-kernel@lists.infradead.org"
<linux-arm-kernel@lists.infradead.org>,
Daniel Scally <dan.scally@ideasonboard.com>,
Kieran Bingham <kieran.bingham@ideasonboard.com>,
Stefan Klug <stefan.klug@ideasonboard.com>,
Conor Dooley <conor+dt@kernel.org>,
Fabio Estevam <festevam@gmail.com>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Pengutronix Kernel Team <kernel@pengutronix.de>,
Rob Herring <robh@kernel.org>,
Sascha Hauer <s.hauer@pengutronix.de>,
Shawn Guo <shawnguo@kernel.org>,
"Russell King (Oracle)" <linux@armlinux.org.uk>
Subject: Re: [PATCH] arm64: dts: imx8mp-debix-model-a: Disable EEE for 1000T
Date: Sat, 22 Nov 2025 16:22:46 +0900 [thread overview]
Message-ID: <20251122072246.GA16239@pendragon.ideasonboard.com> (raw)
In-Reply-To: <PAXPR04MB8510E17B2B8C612DD02175CE88D6A@PAXPR04MB8510.eurprd04.prod.outlook.com>
Hello Wei,
On Tue, Nov 18, 2025 at 01:50:55AM +0000, Wei Fang wrote:
> Sorry, I only have a little experience with DWMac, add Clark to help look
> at this issue.
Thank you.
I think we're getting close to having a good understanding of the
problem. I've debugged it as far as I could based on the information
available publicly. Let's try to get to the bottom of this issue, it
impacts quite a lot of people and it would be very nice to fix it
properly in mainline.
The short summary is that I'm experiencing an interrupt storm on IRQ 135
when EEE is enabled with the EQOS interface.
My current theory is that
- The lpi_intr_o signal of the EQOS is OR'ed into IRQ 135.
- The issue is triggerted by the PHY exiting LPI mode
- When it exits LPI mode, the PHY restarts generating the RX clock
(clk_rx_i).
- The MAC detects exit from LPI, and asserts lpi_intr_o.
- Before the CPU has time to process the interrupt, the PHY enters LPI
mode again, and stops generating the RX clock.
- The CPU processes the interrupt and reads the GMAC4_LPI_CTRL_STATUS
registers. This does not clear lpi_intr_o as there's no clk_rx_i.
Would someone at NXP with access to internal documentation and/or the
RTL be able to confirm that lpi_intr_o is indeed OR'ed into IRQ 135 ?
> > Dropping Catalin Popescu from CC as his e-mail address bounces, and adding
> > Fugang Duan, Joakim Zhang, Wei Fang and Yannick Vignong from NXP who have
> > worked on upstream i.MX8MP support in the driver.
> >
> > Fugang, Joakim, Wei and Yannick, there's a question for you below.
> >
> > On Thu, Nov 13, 2025 at 10:59:23AM +0000, Russell King (Oracle) wrote:
> > > On Thu, Nov 13, 2025 at 03:06:27AM +0200, Laurent Pinchart wrote:
> > > > On Thu, Nov 13, 2025 at 12:25:52AM +0200, Laurent Pinchart wrote:
> > > > > On Wed, Nov 12, 2025 at 12:03:13PM +0000, Russell King (Oracle) wrote:
> > > > > > On Wed, Nov 12, 2025 at 01:54:34AM +0200, Laurent Pinchart wrote:
> > > > > > > On Tue, Oct 28, 2025 at 09:18:17AM +0200, Laurent Pinchart wrote:
> > > > > > > > I didn't notice it at the time because my board was
> > > > > > > > connected to a switch that didn't support EEE.
> > > > > > >
> > > > > > > I can confirm that reverting that commit makes the issue
> > > > > > > disappear. So we're dealing with an interrupt storm that
> > > > > > > occurs when all three of the following conditions are true:
> > > > > > >
> > > > > > > - cpu-pd-wait is enabled
> > > > > > > - EEE is enabled
> > > > > > > - the peer also supports EEE
> > > > > >
> > > > > > Thanks - overall, please take the statistics and interrupt
> > > > > > status bits with a pinch of salt - I suspect there are cases
> > > > > > where the interrupt is not actually enabled, and the code
> > > > > > doesn't take action to clear down a set status bit, but _does_
> > > > > > count it - so every interrupt that happens increments the counter.
> > > > >
> > > > > True. To (partly) avoid that, I've dropped the line that discards
> > > > > disabled bits in dwmac4_irq_status():
> > > > >
> > > > > /* Discard disabled bits */
> > > > > - intr_status &= intr_enable;
> > > > >
> > > > > to ensure that all bits are processed and cleared. I then didn't
> > > > > see any high count of any of the GMAC_INT_STATUS interrupts. For
> > > > > MTL_INTERRUPT_STATUS it's a bit different, as by default only one
> > > > > queue is processed.
> > > > >
> > > > > > > Furthermore, I tried counting bits from all the interrupt
> > > > > > > status registers I could find. The count of
> > > > > > > MTL_INTERRUPT_STATUS Q0IS to Q4IS bits is very high, and so are the
> > DMA_CH0_STATUS TBU and ETI bits.
> > > > > >
> > > > > > TBU means that the transmitter found that the next buffer was
> > > > > > owned by the "application" rather than the hardware, which would
> > > > > > be normal after getting to the end of the queued packets.
> > > > > >
> > > > > > ETI means that a packet has been transferred into MTL memory,
> > > > > > and thus would occur for every transmitted packet.
> > > > > >
> > > > > > Having dug into the imx8m documentation and the driver this
> > > > > > morning, I don't think TBU and ETI are the source of the
> > > > > > interrupt storm. Their corresponding interrupt enable bits are
> > > > > > DMA_CHAN_INTR_ENA_TBUE and DMA_CHAN_INTR_ENA_ETE (driver
> > names).
> > > > > > Both of these only appear in a header file - the code never
> > > > > > enables these interrupts. So, TBU and ETI should not be causing an
> > interrupt storm.
> > > > > >
> > > > > > As for QxIS, stmmac_common_interrupt() will iterate over the
> > > > > > queues in use, calling stmmac_host_mtl_irq_status() aka
> > > > > > dwmac4_irq_mtl_status() for each. Only if this happens will
> > > > > > MTL_CHAN_INT_CTRL() be read which clears the status bit. In
> > > > > > other words, if e.g. Q1IS is set, but only one queue is being
> > > > > > used. dwmac4_irq_mtl_status() won't be called for queue 1, and thus
> > MTL_CHAN_INT_CTRL() won't be read to clear Q1IS.
> > > > >
> > > > > That's why I tried to enable all 5 queues in DT, but alas, it
> > > > > didn't help. I'll try again and count all possible interrupts.
> > > >
> > > > Here's my debug patch (not very pretty, sorry about that):
> > >
> > > That's fine. Thanks for providing this and the raw data.
> > >
> > > > Here are the corresponding stats captured right after booting to
> > > > userspace, with the 0 counts stripped off to keep the output readable:
> > > >
> > > > irq_gmac_0_n: 1
> > >
> > > RSGMIIS, disabled, cleared by read of MAC_PHYIF_CONTROL_STATUS.
> > >
> > > > irq_gmac_5_n: 4047
> > >
> > > LPIIS, enabled, cleared by read of LPI_CONTROL_STATUS which is done.
> > >
> > > > irq_gmac_18_n: 46
> > >
> > > MDIOIS, disabled, clear on read of _this_ status register
> > >
> > > > irq_mtl0_n: 2244307
> > >
> > > This will increment each time dwmac4_irq_mtl_status() is called for
> > > channel 0, which will be called each time stmmac_common_interrupt() is
> > > called. Thus, this indicates the total number of times the stmmac
> > > interrupt handler has been called.
> >
> > Yes, my goal with the irq_mtlX_n counters was to check for which
> > channels/queues the dwmac4_irq_mtl_status() was called.
> >
> > > > irq_mtl_0_n: 2244307
> > > > irq_mtl_1_n: 2244307
> > > > irq_mtl_2_n: 2244307
> > > > irq_mtl_3_n: 2244307
> > > > irq_mtl_4_n: 2244307
> > >
> > > These should be cleared by reading the corresponding queue interrupt
> > > control/status register, iow MTL_CHAN_INT_CTRL(). However, we do not
> > > write to MTL_CHAN_INT_CTRL() to enable any of the interrupts there, so
> > > this looks weird to me, so it would be an idea to look at what value
> > > this MTL_CHAN_INT_CTRL() register contains, it may provide something
> > > useful, but I actually suspect it's another red herring.
> >
> > All the MTL_CHAN_INT_CTRL() registers read as 0x00000002, so the interrupts
> > are not enabled.
> >
> > > > irq_chan0_n: 2244307
> > >
> > > Similarly to irq_mtl0_n, this will increment each time
> > > dwmac4_dma_interrupt() is called for channel 0, which will be via
> > > stmmac_napi_check(), stmmac_dma_interrupt() and
> > > stmmac_common_interrupt(). Therefore, it is expected to have the same
> > > value as irq_mtl0_n.
> > >
> > > > irq_chan0_0_n: 333
> > > > irq_chan0_2_n: 2244307
> > > > irq_chan0_6_n: 2769
> > > > irq_chan0_10_n: 2244307
> > > > irq_chan0_11_n: 2799
> > > > irq_chan0_15_n: 2701
> > >
> > > Only interrupts 0, 6, 12, 14 and 15 are enabled. Status bits in this
> > > register require '1' to be written to clear them. As the value written
> > > back is the status that was read masked by the interrupt enable, if
> > > bits 2 or 10 are set, they will never be cleared, so will increment
> > > each and every time stmmac_common_interrupt() is called. Therefore,
> > > these values are not significant.
> >
> > I've commented out the masking in dwmac4_dma_interrupt(), and the counters
> > show that bits 2 and 10 were indeed not significant:
> >
> > irq_gmac_0_n: 1
> > irq_gmac_5_n: 3846
> > irq_gmac_18_n: 59
> > irq_mtl0_n: 2189598
> > irq_mtl_0_n: 2189598
> > irq_mtl_1_n: 2189598
> > irq_mtl_2_n: 2189598
> > irq_mtl_3_n: 2189598
> > irq_mtl_4_n: 2189598
> > irq_chan0_n: 2189598
> > irq_chan0_0_n: 258
> > irq_chan0_2_n: 2680
> > irq_chan0_6_n: 2660
> > irq_chan0_10_n: 2682
> > irq_chan0_11_n: 1659
> > irq_chan0_15_n: 2598
> > irq_tx_path_in_lpi_mode_n: 6
> > irq_tx_path_exit_lpi_mode_n: 6
> > irq_rx_path_in_lpi_mode_n: 2012
> > irq_rx_path_exit_lpi_mode_n: 2009
> > irq_rgmii_n: 1
> > rx_normal_irq_n: 2660
> > tx_normal_irq_n: 258
> > normal_irq_n: 4577
> > q0_tx_irq_n: 258
> > q0_rx_irq_n: 2660
> >
> > There is still an interrupt storm, as shown by bits Q0IS to Q4IS in
> > MTL_INTERRUPT_STATUS. Those bits are documented in the i.MX8MP RM as
> >
> > Queue 0 Interrupt status
> >
> > This bit indicates that there is an interrupt from Queue 0. To reset
> > this bit, the application must read Queue 0 Interrupt Control and
> > Status register to get the exact cause of the interrupt and clear its
> > source.
> >
> > I've added counters for the MTL_CHAN_INT_CTRL() registers bits in
> > dwmac4_irq_mtl_status():
> >
> > irq_gmac_0_n: 1
> > irq_gmac_5_n: 4088
> > irq_gmac_18_n: 70
> > irq_mtl0_n: 2279161
> > irq_mtl_0_n: 2279161
> > irq_mtl_1_n: 2279161
> > irq_mtl_2_n: 2279161
> > irq_mtl_3_n: 2279161
> > irq_mtl_4_n: 2279161
> > irq_mtl_chan0_1_n: 2279161
> > irq_chan0_n: 2279161
> > irq_chan0_0_n: 269
> > irq_chan0_2_n: 2874
> > irq_chan0_6_n: 2754
> > irq_chan0_10_n: 2871
> > irq_chan0_11_n: 1793
> > irq_chan0_15_n: 2749
> > irq_tx_path_in_lpi_mode_n: 13
> > irq_tx_path_exit_lpi_mode_n: 13
> > irq_rx_path_in_lpi_mode_n: 2112
> > irq_rx_path_exit_lpi_mode_n: 2111
> > irq_rgmii_n: 1
> > rx_normal_irq_n: 2754
> > tx_normal_irq_n: 269
> > normal_irq_n: 4816
> > q0_tx_irq_n: 269
> > q0_rx_irq_n: 2754
> >
> > I've then modified dwmac4_irq_mtl_status() to write back the status value to
> > MTL_CHAN_INT_CTRL() unconditionally:
> >
> > irq_gmac_0_n: 1
> > irq_gmac_5_n: 4429
> > irq_gmac_18_n: 96
> > irq_mtl0_n: 5165861
> > irq_mtl_0_n: 5212
> > irq_mtl_1_n: 5165861
> > irq_mtl_2_n: 5165861
> > irq_mtl_3_n: 5165861
> > irq_mtl_4_n: 5165861
> > irq_mtl_chan0_1_n: 5212
> > irq_chan0_n: 5165861
> > irq_chan0_0_n: 274
> > irq_chan0_2_n: 2965
> > irq_chan0_6_n: 2858
> > irq_chan0_10_n: 2965
> > irq_chan0_11_n: 1899
> > irq_chan0_15_n: 2838
> > irq_tx_path_in_lpi_mode_n: 6
> > irq_tx_path_exit_lpi_mode_n: 6
> > irq_rx_path_in_lpi_mode_n: 2364
> > irq_rx_path_exit_lpi_mode_n: 2363
> > irq_rgmii_n: 1
> > rx_normal_irq_n: 2858
> > tx_normal_irq_n: 274
> > normal_irq_n: 5031
> > q0_tx_irq_n: 274
> > q0_rx_irq_n: 2858
> >
> > As expected, that clears the interrupt source for Q01S, so irq_mtl_chan0_1_n
> > and irq_mtl_0_n are now under control.Enabling support for 5 channels in DT:
> >
> > irq_gmac_0_n: 1
> > irq_gmac_5_n: 4993
> > irq_gmac_18_n: 74
> > irq_mtl0_n: 3084994
> > irq_mtl1_n: 3084994
> > irq_mtl2_n: 3084994
> > irq_mtl3_n: 3084994
> > irq_mtl4_n: 3084994
> > irq_mtl_0_n: 5433
> > irq_mtl_1_n: 9272
> > irq_mtl_2_n: 13218
> > irq_mtl_3_n: 17084
> > irq_mtl_4_n: 21010
> > irq_mtl_chan0_0_n: 1
> > irq_mtl_chan0_1_n: 4401
> > irq_mtl_chan0_16_n: 1
> > irq_mtl_chan1_1_n: 4401
> > irq_mtl_chan2_1_n: 4401
> > irq_mtl_chan3_1_n: 4401
> > irq_mtl_chan4_1_n: 4401
> > irq_chan0_n: 3084994
> > irq_chan1_n: 3084994
> > irq_chan2_n: 3084994
> > irq_chan3_n: 3084994
> > irq_chan4_n: 3084994
> > irq_chan0_0_n: 266
> > irq_chan0_2_n: 2923
> > irq_chan0_6_n: 2809
> > irq_chan0_10_n: 2925
> > irq_chan0_11_n: 2203
> > irq_chan0_15_n: 2738
> > irq_chan1_2_n: 3
> > irq_chan1_10_n: 3
> > irq_chan2_2_n: 1
> > irq_chan2_10_n: 1
> > irq_chan3_2_n: 8
> > irq_chan3_10_n: 8
> > irq_chan4_2_n: 2
> > irq_chan4_10_n: 2
> > irq_tx_path_in_lpi_mode_n: 6
> > irq_tx_path_exit_lpi_mode_n: 6
> > irq_rx_path_in_lpi_mode_n: 2633
> > irq_rx_path_exit_lpi_mode_n: 2632
> > irq_rgmii_n: 1
> > rx_normal_irq_n: 2809
> > tx_normal_irq_n: 266
> > normal_irq_n: 5278
> > q0_tx_irq_n: 266
> > q0_rx_irq_n: 2809
> >
> > There are no more storms in interrupt bit counters. The only counters that are
> > out of control are irq_mtlX_n and irq_chanX_n, as expected, as they simply
> > count the number of times the IRQ handling functions are called.
> >
> > Unless we're missing some interrupt sources in other registers, I think this
> > indicates that the storm is not caused by the sbd_intr_o or
> > sbd_perch_[rt]x_intr_o signals. lpi_intr_o seems the most likely culprit at this
> > point (more on that below).
> >
> > > > Here are the stats after enabling five queues in DT, also captured
> > > > right after booting to userspace:
> > > >
> > > > irq_gmac_0_n: 1
> > > > irq_gmac_5_n: 4020
> > > > irq_gmac_18_n: 41
> > > > irq_mtl0_n: 1286469
> > > > irq_mtl1_n: 1286469
> > > > irq_mtl2_n: 1286469
> > > > irq_mtl3_n: 1286469
> > > > irq_mtl4_n: 1286469
> > > > irq_mtl_0_n: 6432345
> > > > irq_mtl_1_n: 6432345
> > > > irq_mtl_2_n: 6432345
> > > > irq_mtl_3_n: 6432345
> > > > irq_mtl_4_n: 6432345
> > >
> > > These values are the sum of irq_mtl[0-4]_n, so would be expected given
> > > the other numbers.
> > >
> > > > irq_chan0_n: 1286469
> > > > irq_chan1_n: 1286469
> > > > irq_chan2_n: 1286469
> > > > irq_chan3_n: 1286469
> > > > irq_chan4_n: 1286469
> > > > irq_chan0_0_n: 416
> > > > irq_chan0_2_n: 1286466
> > > > irq_chan0_6_n: 3470
> > > > irq_chan0_10_n: 1286466
> > > > irq_chan0_11_n: 2740
> > > > irq_chan0_15_n: 2686
> > > > irq_chan1_2_n: 1286469
> > > > irq_chan1_10_n: 1286469
> > > > irq_chan2_2_n: 1286467
> > > > irq_chan2_10_n: 1286467
> > > > irq_chan4_2_n: 1286469
> > > > irq_chan4_10_n: 1286469
> > >
> > > It's slightly interesting that irq_chanX_2_n and irq_chanX_10_n don't
> > > match their corresponding irq_chanX_n values, which implies that they
> > > have been clear. It's likely given that we're talking about 0, 2 or 3
> > > times that's due to the first few packets and these bits hadn't been
> > > set. So again, I don't think TBU and ETI are significant.
> > >
> > > > Setting eee-broken-1000t, with a single queue:
> > > >
> > > > irq_gmac_0_n: 1
> > > > irq_gmac_18_n: 6
> > > > irq_mtl0_n: 2548
> > > > irq_mtl_0_n: 2548
> > > > irq_mtl_1_n: 2548
> > > > irq_mtl_2_n: 2548
> > > > irq_mtl_3_n: 2548
> > > > irq_mtl_4_n: 2548
> > > > irq_chan0_n: 2548
> > > > irq_chan0_0_n: 282
> > > > irq_chan0_2_n: 2548
> > > > irq_chan0_6_n: 2324
> > > > irq_chan0_10_n: 2548
> > > > irq_chan0_11_n: 29
> > > > irq_chan0_15_n: 2548
> > >
> > > These counts suggest that the interrupt handler was entered 2548 times
> > > at the point they were captured, which corresponds to "normal"
> > > interrupts for channel 0.
> > >
> > > >
> > > > And eee-broken-1000t with 5 queues:
> > > >
> > > > irq_gmac_0_n: 1
> > > > irq_gmac_18_n: 8
> > > > irq_mtl0_n: 2672
> > > > irq_mtl1_n: 2672
> > > > irq_mtl2_n: 2672
> > > > irq_mtl3_n: 2672
> > > > irq_mtl4_n: 2672
> > > > irq_mtl_0_n: 13360
> > > > irq_mtl_1_n: 13360
> > > > irq_mtl_2_n: 13360
> > > > irq_mtl_3_n: 13360
> > > > irq_mtl_4_n: 13360
> > > > irq_chan0_n: 2672
> > > > irq_chan1_n: 2672
> > > > irq_chan2_n: 2672
> > > > irq_chan3_n: 2672
> > > > irq_chan4_n: 2672
> > > > irq_chan0_0_n: 283
> > > > irq_chan0_2_n: 2672
> > > > irq_chan0_6_n: 2439
> > > > irq_chan0_10_n: 2672
> > > > irq_chan0_11_n: 46
> > > > irq_chan0_15_n: 2672
> > > > irq_chan2_2_n: 2670
> > > > irq_chan2_10_n: 2670
> > > > irq_chan3_2_n: 2672
> > > > irq_chan3_10_n: 2672
> > >
> > > So channel 0 responsible for 2672 normal interrupts. Again, this
> > > reinforces that the other values with 2672 are likely not significant.
> > >
> > > > Given the enabled interrupts, I agree that the counters are
> > > > misleading, as none of the interrupt bits with high counts are
> > > > enabled. I'm however not entirely sure about the MTL interrupt
> > > > status register, it's not clear to me if it is wired to the EQOS IRQ
> > > > line as I don't see a corresponding interrupt enable register.
> > > >
> > > > If we rule out the main EQOS IRQ line and the per-channel RX and TX
> > > > IRQ lines as the source of the interrupt storm, the last possible
> > > > culprit according to section 7.1.2 (A53 Interrupts) of the i.MX8MP
> > > > reference manual would be the "ENET QOS TSN LPI RX exit Interrupt"
> > > > that is OR'ed into IRQ 135. As that's related to EEE, it's a
> > > > probable culprit, but I don't know how what controls that IRQ line.
> > >
> > > As you have several interrupt signals which presumably show up in
> > > /proc/interrupts, do the values in your IRQ counters correspond with
> > > those interrupt sources? Are any of these interrupts shared with
> > > anything else?
> >
> > # cat /proc/interrupts
> > CPU0 CPU1 CPU2 CPU3
> > 9: 0 0 0 0 GICv3 25
> > Level vgic
> > 11: 4587 5251 5038 5230 GICv3 30
> > Level arch_timer
> > 12: 0 0 0 0 GICv3 27
> > Level kvm guest vtimer
> > 14: 3953 7210 6374 5861 GICv3 79
> > Level timer@306a0000
> > 15: 0 0 0 0 GICv3 60
> > Level 30880000.serial
> > 16: 173 0 0 0 GICv3 59
> > Level 30890000.serial
> > 17: 0 0 0 0 GICv3 61
> > Level 30a60000.serial
> > 18: 0 0 0 0 GICv3 36
> > Level 30370000.snvs:snvs-powerkey
> > 19: 0 0 0 0 GICv3 51
> > Level rtc alarm
> > 20: 0 0 0 0 GICv3 110
> > Level 30280000.watchdog
> > 21: 52 0 0 0 GICv3 56
> > Level mmc2
> > 23: 0 0 0 0 GICv3 23
> > Level arm-pmu
> > 24: 0 0 0 0 GICv3 130
> > Level imx8_ddr_perf_pmu
> > 30: 0 0 0 0 gpio-mxc 3 Edge
> > pca9450-irq
> > 72: 0 0 0 0 gpio-mxc 11 Edge
> > hym8563
> > 73: 0 0 0 0 gpio-mxc 12 Edge
> > 30b50000.mmc cd
> > 195: 810 0 0 0 GICv3 67
> > Level 30a20000.i2c
> > 196: 140 0 0 0 GICv3 68
> > Level 30a30000.i2c
> > 197: 0 0 0 0 GICv3 69
> > Level 30a40000.i2c
> > 198: 35 0 0 0 GICv3 70
> > Level 30a50000.i2c
> > 199: 0 0 0 0 GICv3 109
> > Level 30ae0000.i2c
> > 200: 5930706 0 0 0 GICv3 167
> > Level eth0
> > 201: 0 0 0 0 GICv3 166
> > Level eth0
> > 202: 370 0 0 0 GICv3 55
> > Level mmc1
> > 203: 0 0 0 0 GICv3 181
> > Level 32f10108.usb
> > 205: 81 0 0 0 GICv3 73
> > Level xhci-hcd:usb1
> > 206: 0 0 0 0 GICv3 34
> > Level 30bd0000.dma-controller
> > 207: 0 0 0 0 GICv3 49
> > Level 32e40000.csi
> > 208: 0 0 0 0 GICv3 35
> > Level 38000000.gpu
> > 209: 0 0 0 0 GICv3 66
> > Level 30e00000.dma-controller
> > 210: 0 0 0 0 GICv3 57
> > Level 38008000.gpu
> > 211: 0 0 0 0 GICv3 45
> > Level 38500000.npu
> > 212: 0 0 0 0 GICv3 132
> > Level 32e30000.dwe
> > 213: 0 0 0 0 irqsteer 0 Level
> > 32fd8000.hdmi
> > 214: 0 0 0 0 GICv3 135
> > Level 30e10000.dma-controller
> > 215: 0 0 0 0 GICv3 106
> > Level rkisp1
> > 216: 0 0 0 0 irqsteer 8 Level
> > imx-lcdif
> > 217: 0 0 0 0 GICv3 39
> > Level 38300000.video-codec
> > 218: 0 0 0 0 GICv3 40
> > Level 38310000.video-codec
> > IPI0: 587 430 859 896 Rescheduling
> > interrupts
> > IPI1: 5548 7530 6814 7366 Function call
> > interrupts
> > IPI2: 0 0 0 0 CPU stop
> > interrupts
> > IPI3: 0 0 0 0 CPU stop
> > NMIs
> > IPI4: 2410 3635 3487 3707 Timer
> > broadcast interrupts
> > IPI5: 3554 4650 3986 3762 IRQ work
> > interrupts
> > IPI6: 0 0 0 0 CPU
> > backtrace interrupts
> > IPI7: 0 0 0 0 KGDB
> > roundup interrupts
> > Err: 0
> >
> > GICv3 167 is interrupt 135 from section 7.1.2.
> >
> > > Hmm, looking at 7.1.2, and the mention of "ENET QOS TSN LPI RX exit
> > > Interrupt" I'm wondering whether Freescale have wired the lpi_intr_o
> > > signal of the GMAC to their OR4 gate. This is the LPI RX exit
> > > interrupt output, and it is cleared when reading the LPI control/
> > > status register. However, its deassertion is synchronous to the RX
> > > clock domain, so it will take time to clear.
> >
> > I think we're getting somewhere... All the data above confirm this hypothesis in
> > my opinion (or at least they rule out all the other hypotheses I had).
> >
> > Fugang, Joakim, Wei, Yannick, would you be able to check is the lpi_intr_o signal
> > is indeed OR'ed into interrupt 137 ? Are you aware of the issue investigated in
> > this mail thread ?
> >
> > > The purpose of this signal is to trigger to external hardware (to the
> > > GMAC) to restore the application clock to the MAC. I'm not sure that
> > > this was meant to be wired to an actual CPU interrupt. The only clue
> > > is the name which suggests it is, but there's nothing that states
> > > there's a way to disable it being asserted which makes me more
> > > suspicious that it's not meant to be a CPU interrupt.
> >
> > I've modified dwmac4_irq_status() to read GMAC4_LPI_CTRL_STATUS
> > unconditionally, and the problem persists. This could be explained by the fact
> > that lpi_intr_o takes time to clear as you mentioned.
> >
> > Now I'm exploring unknown territory, this may be a stupid hypothesis, but what
> > if:
> >
> > - The PHY exits LPI mode, and restarts generating the RX clock (clk_rx_i).
> > - The MAC detects exit from LPI, and asserts lpi_intr_o.
> > - Before the CPU has time to process the interrupt, the PHY enters LPI
> > mode again, and stops generating the RX clock.
> > - The CPU processes the interrupt and reads the GMAC4_LPI_CTRL_STATUS
> > registers. This does not clear lpi_intr_o as there's no clk_rx_i.
> >
> > > So, maybe this is the cause of the interrupt storm. Maybe Kieran isn't
> > > seeing the storm because his receive path is not entering LPI.
> >
> > Kieran told me he will perform more tests, but ran out of time this week.
> >
> > > I think a useful check for this would be if you could either disable
> > > LPI entry at the link partner, or hook it up to another system which
> > > can have tx_lpi disabled, and see how the iMX8 system behaves.
> >
> > I tried that with my RTL8153 USB-ethernet adapter, but I don't think I can really
> > trust the result. The device doesn't respond to `ethtool --set-eee` in an expected
> > way, it got stuck with LPI completely disabled and I had to disconnect and
> > reconnect it to recover from that.
> >
> > I have another USB-ethernet adapter doesn't support EEE, and no second
> > i.MX8MP system I could use for testing right now. I'll see if I can find suitable
> > hardware, but it may take a while (I'm about to go on a trip abroad).
> >
> > > If preventing the iMX8 receive path entering LPI fixes the problem,
> > > then I think this is likely the culpret.
> > >
> > > However, I'd be worred about this - if we "disable LPI" by way of the
> > > advertisement at the local end, there is the possibility that a remote
> > > system could override the negotiation and force its transmit link into
> > > LPI mode, which would cause the iMX8MP receive side to see LPI entry
> > > and exit, triggering this interrupt. If this is correct, that gives an
> > > attacker a way to manipulate the iMX8MP system, potentially causing
> > > all sorts of problems.
> > >
> > > Hmm. Not sure I like this look of that.
> >
> > I'm sure I don't like it :-/
> >
> > > If this hypothesis is correct, then yes, disabling EEE is the only way
> > > forward for this, but I would suggest going further - ensuring that
> > > SmartEEE is enabled on the PHY but with the advertisement cleared (so
> > > EEE negotiation indicates not supported) to block the receive side LPI
> > > getting to the EQOS.
> >
> > I'm not sure how that should be implemented, I'd appreciate guidance. In
> > particular, the RTL8211E appears to support SmartEEE (based on the
> > information provided in this mail thread), but the registers to control it are not
> > documented. Maybe we can just rely on the fact it will be enabled as a reset
> > default at boot time.
> >
> > > This also means that 100M EEE would also be affected, so just
> > > disabling 1G EEE in DT is insufficient.
> >
> > Agreed. I've just tested forcing 100BaseT with EEE enabled, and the issue
> > persists.
> >
> > > Andrew - if we need to go down this path, I think we need a flag in
> > > the PHY flags to indicate that we want SmartEEE enabled.
--
Regards,
Laurent Pinchart
next prev parent reply other threads:[~2025-11-22 7:23 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-26 12:29 [PATCH] arm64: dts: imx8mp-debix-model-a: Disable EEE for 1000T Laurent Pinchart
2025-10-27 1:31 ` Fabio Estevam
2025-10-27 3:08 ` Andrew Lunn
2025-10-27 7:27 ` Laurent Pinchart
2025-10-27 8:47 ` Emanuele Ghidoli
2025-10-27 9:00 ` Russell King (Oracle)
2025-10-27 9:18 ` Emanuele Ghidoli
2025-10-27 9:32 ` Russell King (Oracle)
2025-10-27 23:08 ` Laurent Pinchart
2025-10-27 11:22 ` Russell King (Oracle)
2025-10-27 23:15 ` Laurent Pinchart
2025-10-27 9:12 ` Oleksij Rempel
2025-10-27 10:02 ` Laurent Pinchart
2025-10-27 10:23 ` Oleksij Rempel
2025-10-27 10:31 ` Laurent Pinchart
2025-10-27 10:34 ` Russell King (Oracle)
2025-10-27 10:44 ` Oleksij Rempel
2025-10-27 10:48 ` Russell King (Oracle)
2025-10-27 12:50 ` Andrew Lunn
2025-10-27 14:50 ` Oleksij Rempel
2025-11-12 12:34 ` Russell King (Oracle)
2025-11-12 12:41 ` Kieran Bingham
2025-11-12 12:56 ` Russell King (Oracle)
2025-11-13 1:17 ` Laurent Pinchart
2025-11-12 21:32 ` Laurent Pinchart
2025-10-27 9:07 ` Russell King (Oracle)
2025-10-27 9:33 ` Laurent Pinchart
2025-10-27 9:45 ` Russell King (Oracle)
2025-10-27 9:55 ` Laurent Pinchart
2025-10-27 13:33 ` Russell King (Oracle)
2025-10-27 15:13 ` Russell King (Oracle)
2025-10-27 19:52 ` Andrew Lunn
2025-10-27 23:46 ` Laurent Pinchart
2025-10-28 0:57 ` Russell King (Oracle)
2025-10-28 7:18 ` Laurent Pinchart
2025-11-11 23:54 ` Laurent Pinchart
2025-11-12 12:03 ` Russell King (Oracle)
2025-11-12 22:25 ` Laurent Pinchart
2025-11-13 1:06 ` Laurent Pinchart
2025-11-13 10:59 ` Russell King (Oracle)
2025-11-14 22:26 ` Laurent Pinchart
2025-11-18 1:50 ` Wei Fang
2025-11-22 7:22 ` Laurent Pinchart [this message]
2025-11-22 9:57 ` Russell King (Oracle)
2025-11-23 5:38 ` Laurent Pinchart
2025-11-23 8:52 ` Russell King (Oracle)
2025-11-23 15:23 ` Laurent Pinchart
2025-11-23 17:11 ` Russell King (Oracle)
2025-11-24 0:12 ` Laurent Pinchart
2025-11-24 5:44 ` Oleksij Rempel
2025-11-24 8:43 ` Russell King (Oracle)
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=20251122072246.GA16239@pendragon.ideasonboard.com \
--to=laurent.pinchart@ideasonboard.com \
--cc=conor+dt@kernel.org \
--cc=dan.scally@ideasonboard.com \
--cc=devicetree@vger.kernel.org \
--cc=festevam@gmail.com \
--cc=ghidoliemanuele@gmail.com \
--cc=imx@lists.linux.dev \
--cc=kernel@pengutronix.de \
--cc=kieran.bingham@ideasonboard.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux@armlinux.org.uk \
--cc=o.rempel@pengutronix.de \
--cc=robh@kernel.org \
--cc=s.hauer@pengutronix.de \
--cc=shawnguo@kernel.org \
--cc=stefan.klug@ideasonboard.com \
--cc=wei.fang@nxp.com \
--cc=xiaoning.wang@nxp.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;
as well as URLs for NNTP newsgroup(s).