Skip to content

EEE support for rp1 mac#7251

Open
nbuchwitz wants to merge 8 commits intoraspberrypi:rpi-6.12.yfrom
nbuchwitz:devel/gmac-eee
Open

EEE support for rp1 mac#7251
nbuchwitz wants to merge 8 commits intoraspberrypi:rpi-6.12.yfrom
nbuchwitz:devel/gmac-eee

Conversation

@nbuchwitz
Copy link
Contributor

This adds EEE support to the macb driver for the Pi 5 / CM5. Right now EEE is broken on the Pi because the PHY advertises EEE but the MAC has no LPI support, so it was marked as broken in #6900. This series fixes that by implementing proper software-managed TX LPI in the driver and reverting the DT workaround.

See #6855

This should go through mainline as the EEE registers are the same across all Cadence GEM variants (SAMA5D2, SAME70, PIC32CZ, RP1, ...) and the code is generic, just gated on a capability flag. I'm looking for early feedback from Pi users before sending it upstream though. If you've got a Pi 5 or CM5, give it a spin and let me know how it goes — link stability, ethtool --show-eee, ethtool -S | grep lpi, that kind of thing.

@nbuchwitz
Copy link
Contributor Author

f0d41dc is not directly EEE related, but I noticed it was missing while debugging

@pelwell
Copy link
Contributor

pelwell commented Feb 18, 2026

Thanks, Nicolai - this looks great.

For anyone wishing to try the new EEE capability, you can install a trial build using sudo rpi-update pulls/7251, after reading the caveats.

@pelwell
Copy link
Contributor

pelwell commented Feb 18, 2026

For comparison, these are the values I get after being up for a few minutes:

pi@philpi5:~$ ethtool --show-eee eth0
EEE settings for eth0:
        EEE status: enabled - active
        Tx LPI: 0 (us)
        Supported EEE link modes:  100baseT/Full
                                   1000baseT/Full
        Advertised EEE link modes:  100baseT/Full
                                    1000baseT/Full
        Link partner advertised EEE link modes:  100baseT/Full
                                                 1000baseT/Full
pi@philpi5:~$ ethtool -S eth0 | grep lpi
     rx_lpi_transitions: 0
     rx_lpi_time: 0
     tx_lpi_transitions: 88
     tx_lpi_time: 85760892

@nbuchwitz
Copy link
Contributor Author

For better comparison: is the ethernet link actively used or not? If yes, how do the tx lpi rate change when the ethernet is mostly idle (eg wifi used)?

@nbuchwitz
Copy link
Contributor Author

nbuchwitz commented Feb 19, 2026

After some more testing, I've improved the patch set further and fixed a bug.

Changes since v1:

  • Use mod_delayed_work() instead of schedule_delayed_work() for LPI idle timer re-entry. schedule_delayed_work() is a no-op when work is already pending, so the timer was never reset by TX completions - causing LPI to be asserted periodically even under full load.
  • Set MACB_TX_LPI_TIMER_DEFAULT_MS to 500ms (was 250ms). Chosen as a good compromise between energy savings and throughput stability - lower values cause more frequent LPI wake transitions with associated retransmission overhead on bursty workloads.
  • Remove unused RX LPI status bit change interrupt definitions (RXLPISBC). The interrupt is not wired up in this series and can be added later if needed for diagnostics.
  • Include fix for a probable upstream bug in phy_ethtool_set_eee() where EEE advertised modes were not correctly restored after an off/on toggle, because eee_cfg.eee_enabled was updated after genphy_c45_ethtool_set_eee() instead of before. -> already fixed in a615309 (not part of rpi-6.12.y yet)

@nbuchwitz nbuchwitz force-pushed the devel/gmac-eee branch 2 times, most recently from a615309 to 2702d7d Compare February 19, 2026 12:03
@nbuchwitz
Copy link
Contributor Author

Changes since v2:

  • Fix a bug in macb_tx_lpi_work_fn() where LPI was entered without checking whether all TX queues are actually idle. The delayed work was scheduled when one queue drained, but other queues could still have active transmissions. Now verify tx_head == tx_tail on all queues before asserting TXLPIEN, and reschedule the timer if any queue is still busy. With this fix, iperf3 measured throughput with EEE enabled is now identical to without EEE - earlier versions showed an initial bandwidth drop caused by premature LPI entry.
  • Set MACB_TX_LPI_TIMER_DEFAULT_MS back to 250ms (the v1 default). The multi-queue idle check makes this safe - LPI is no longer entered prematurely under load, so a shorter idle timeout improves energy savings without risking throughput.
Metric                                 EEE off          EEE on
------------------------------ --------------- ---------------
TCP TX throughput                     937.0 Mb/s        937.3 Mb/s
  TX first 5s avg                     939.5 Mb/s        939.8 Mb/s
  TX remaining avg                    936.5 Mb/s        936.8 Mb/s
TCP RX throughput                     936.5 Mb/s        936.5 Mb/s
Ping 1s avg RTT                        0.188 ms         0.272 ms
Ping 10ms avg RTT                      0.172 ms         0.205 ms
Flood ping loss                 0% packet loss  0% packet loss
Flood ping avg RTT                     0.155 ms         0.199 ms
Ping under load avg RTT                1.915 ms         1.904 ms

LPI counters during 1s-interval ping (EEE on):
  rx_lpi_transitions: 0
  rx_lpi_time: 0
  tx_lpi_transitions: 101
  tx_lpi_time: 16234605

Note on RX LPI

RX LPI monitoring is not implemented in this series. The BCM54213PE PHY on the Raspberry Pi 5 operates in "native EEE" mode - it handles received LPI internally without forwarding it to the MAC over the RGMII interface. The PHY's vendor-specific LPI_FEATURE_EN bit (register 0x803d) is required for EEE negotiation to work at all, and with it enabled the PHY absorbs incoming LPI transparently. As a result, the GEM MAC's RX LPI hardware counters (RXLPI/RXLPITIME at 0x270/0x274) and the RXLPISBC status change interrupt (ISR bit 27) will never trigger, regardless of driver configuration. The PHY itself does detect and count received LPI (confirmed via PCS status register and the vendor-specific LPI counter at 0x803f), but this information is not exposed on the RGMII interface. This appears to be a PHY hardware limitation, not a driver issue - though this conclusion is based on register-level experimentation without access to Broadcom documentation.

@pelwell, could you check with your Broadcom contacts whether the BCM54213PE supports exposing RX LPI on the RGMII interface?

nbuchwitz and others added 8 commits February 19, 2026 13:07
Wire phy_ethtool_nway_reset() as the .nway_reset ethtool operation,
allowing userspace to restart PHY autonegotiation via 'ethtool -r'.

Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
Add register and bitfield definitions for the Cadence GEM MAC's
IEEE 802.3az Energy Efficient Ethernet (EEE) support:

- LPI statistics counter registers (GEM_RXLPI, GEM_RXLPITIME,
  GEM_TXLPI, GEM_TXLPITIME) at offsets 0x270-0x27c
- TX LPI enable bitfield (GEM_TXLPIEN) in the NCR register (bit 19),
  which directly asserts/deasserts LPI on the transmit path
- MACB_CAPS_EEE capability flag to gate EEE support per platform

These registers are present in all Cadence GEM revisions that support
EEE (verified on SAMA5D2, SAME70, PIC32CZ, and RP1 variants).

No functional change.

Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
Expose the GEM MAC's EEE Low Power Idle hardware counters through
ethtool -S:

- rx_lpi_transitions: number of RX LPI entry events
- rx_lpi_time: cumulative time spent in RX LPI
- tx_lpi_transitions: number of TX LPI entry events (TXLPIEN 0->1)
- tx_lpi_time: cumulative time in TX LPI

These are clear-on-read hardware registers at offsets 0x270-0x27c,
automatically collected by the existing gem_statistics read loop.

Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
Implement software-managed TX Low Power Idle (LPI) for the Cadence GEM
MAC as part of IEEE 802.3az Energy Efficient Ethernet support.

The GEM MAC has no built-in idle timer - the TXLPIEN bit (NCR bit 19)
immediately asserts LPI and blocks all TX while set. The MAC does not
auto-wake for transmit. Per Microchip GMAC documentation (section
40.6.19): "It is best to use firmware to control LPI."

This patch implements a software idle timer using delayed_work:
- On TX completion with an empty ring, schedule LPI entry after a
  configurable idle timeout (default 250ms). The work function
  verifies all TX queues are truly idle before entering LPI to
  prevent entering LPI while traffic is still active.
- On TX start, wake from LPI by clearing TXLPIEN, cancelling any
  pending re-entry, and waiting 50us for the PHY to exit LPI
  (conservative vs IEEE 802.3az Tw_sys of ~17us/~30us)
- On link up, check EEE negotiation via phy_init_eee() and defer
  first LPI entry by 1 second per IEEE 802.3az requirements
- On link down, immediately cancel pending work and clear TXLPIEN

The timer value is configurable at runtime via ethtool --set-eee
tx-timer.

The implementation is gated on MACB_CAPS_EEE so platforms must
explicitly opt in via their macb_config.

Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
Implement ethtool get_eee and set_eee operations for the Cadence GEM
MAC, delegating to phylink for PHY-level EEE negotiation state.

The MAC-level LPI control (TXLPIEN) is not manipulated directly in the
ethtool ops. Instead, phylink_ethtool_set_eee() updates the PHY's EEE
advertisement, which triggers link renegotiation. The mac_link_up
callback then checks the negotiated EEE state and enables LPI
accordingly.

Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
Enable IEEE 802.3az Energy Efficient Ethernet on the Raspberry Pi 5's
RP1 southbridge by adding MACB_CAPS_EEE to its platform config.

The RP1 contains a Cadence GEM_GXL MAC (revision 0x00070109) paired
with a Broadcom BCM54213PE PHY, both of which support EEE at
1000BASE-T and 100BASE-TX.

Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
…of phydev->eee_cfg.eee_enabled

This is a follow-up to 41ffcd9 ("net: phy: fix phylib's dual
eee_enabled") and resolves an issue with genphy_c45_an_config_eee_aneg()
(called from genphy_c45_ethtool_set_eee) not seeing the new value of
phydev->eee_cfg.eee_enabled.

Fixes: 49168d1 ("net: phy: Add phy_support_eee() indicating MAC support EEE")
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reported-by: Choong Yong Liang <yong.liang.choong@linux.intel.com>
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit f26a29a)
@pelwell
Copy link
Contributor

pelwell commented Feb 19, 2026

could you check with your Broadcom contacts whether the BCM54213PE supports exposing RX LPI on the RGMII interface?

Warning: I'm at the limits of my EEE knowledge here, so this might be painful.

The BCM54213PE PHY on the Raspberry Pi 5 operates in "native EEE" mode - it handles received LPI internally without forwarding it to the MAC over the RGMII interface.

The PHY datasheet says that Native EEE is for MACs that support LPI signalling over RGMII, while AutogrEEEn mode is for MACs that don't support LPI signalling over RGMII. This seems to contradict your statement.

@nbuchwitz
Copy link
Contributor Author

The BCM54213PE PHY on the Raspberry Pi 5 operates in "native EEE" mode - it handles received LPI internally without forwarding it to the MAC over the RGMII interface.

The PHY datasheet says that Native EEE is for MACs that support LPI signalling over RGMII, while AutogrEEEn mode is for MACs that don't support LPI signalling over RGMII. This seems to contradict your statement.

I probably messed up some of the Broadcom terminology here -- never understood why they need their own marketing names for what is just 802.3az. Will keep poking at the PHY registers and might find something useful eventually.

@nbuchwitz nbuchwitz mentioned this pull request Feb 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments