public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: Heiner Kallweit <hkallweit1@gmail.com>
To: Huan Zhao <ms.huan.zhao@gmail.com>
Cc: netdev@vger.kernel.org
Subject: Re: r8169: RTL8125B restores default LEDSEL values on Link Up, preventing persistent LED configuration
Date: Sun, 15 Mar 2026 19:06:58 +0100	[thread overview]
Message-ID: <67e97f82-1539-4334-8c95-df6b2f01e769@gmail.com> (raw)
In-Reply-To: <abbs0Zp-HeOaC_69@ser8.localdomain>

On 15.03.2026 18:41, Huan Zhao wrote:
> You are correct. I apologize for the incorrect analysis in my previous
> email. Further testing has clarified the actual behavior.
> 
> Summary of findings after additional testing:
> 
> 1. The LEDSEL registers do NOT reset on Link Up.
> 
>    After writing 0x0000 to all LEDSEL registers via BAR0 MMIO and
>    triggering multiple Link Up/Down cycles, the registers retained
>    their zero values throughout. The hardware does not restore any
>    defaults on link state changes.
> 
> 2. The real problem is CONFIG_LEDS_TRIGGER_NETDEV=m on Arch Linux.
> 
>    As you clarified, the LED classdev registers successfully without
>    ledtrig_netdev present — just without a trigger assigned. However,
>    the link_* sysfs files (link_100, link_2500, etc.) do not appear
>    until the netdev trigger is explicitly assigned. Without these
>    files, there is no way to configure the LED modes through the
>    standard interface.
> 
>    The workaround is to ensure ledtrig_netdev loads before r8169
>    via /etc/modules-load.d/.

The netdev trigger module can be loaded also after r8169, and then
be assigned as trigger.

> 
> 3. Persistent LED disable works correctly via the standard interface.
> 
>    With ledtrig_netdev loaded before r8169, the following sequence
>    successfully and persistently disables all LEDs:
> 
>      echo netdev > /sys/class/leds/enp2s0-N::lan/trigger

How is it if you add a small delay here? I'd have check whether
assigning a trigger is fully synchronous.

>      echo 0 > /sys/class/leds/enp2s0-N::lan/link_10
>      echo 0 > /sys/class/leds/enp2s0-N::lan/link_100
>      echo 0 > /sys/class/leds/enp2s0-N::lan/link_1000
>      echo 0 > /sys/class/leds/enp2s0-N::lan/link_2500
>      echo 0 > /sys/class/leds/enp2s0-N::lan/tx
>      echo 0 > /sys/class/leds/enp2s0-N::lan/rx
> 
>    This survives Link Up/Down cycles and network cable
>    insertion/removal without any further intervention.
> 
>    This is implemented as a systemd oneshot service running after
>    network.target, at which point all link_* files are immediately
>    writable with no waiting required.
> 
> 4. Remaining question: udev timing issue.
> 
>    When the same script runs from a udev RUN rule (triggered on
>    ACTION=="move" for the network interface rename), the link_*
>    files are not yet writable at that point, even after
>    trigger=netdev is set. The files only become writable after
>    a delay of up to several seconds. Is there a reliable udev
>    event or sysfs condition that indicates hw_control is fully
>    ready for writing?
> 
> Thanks,
> Huan Zhao
> 
> On Sun, Mar 15, 2026 at 02:55:17PM +0100, Heiner Kallweit wrote:
>> On 15.03.2026 02:46, Huan Zhao wrote:
>>> Hardware: Beelink SER8 mini PC
>>> NIC: Realtek RTL8125B (XID 0x641, RTL_GIGA_MAC_VER_63, rev 05)
>>> Kernel: 6.19.6-arch1-1
>>> Driver: r8169 (in-tree)
>>> CONFIG_R8169_LEDS=y
>>> CONFIG_LEDS_TRIGGER_NETDEV=m
>>>
>>> Problem:
>>> The RTL8125B chip restores its LEDSEL registers to hardware default values
>>> on every Link Up event. The r8169 driver does not reapply the LED
>>> configuration after Link Up, making it impossible to persistently configure
>>> LEDs (e.g. disable them) through the standard kernel LED subsystem.
>>>
>>> Details:
>>>
>>> The Link Up path in the driver is:
>>>
>>>   r8169_phylink_handler()       [r8169_main.c:4757]
>>>     -> rtl_link_chg_patch()     [r8169_main.c:1597]
>>>     -> rtl_enable_tx_lpi()
>>>     -> pm_request_resume()
>>>
>>> rtl_link_chg_patch() has no handling for RTL_GIGA_MAC_VER_63 and does not
>>> touch the LEDSEL registers. Similarly, rtl_hw_start_8125b() and
>>> rtl_hw_start_8125_common(), which are called on hardware initialization,
>>> do not write to any LEDSEL register (LEDSEL0=0x18, LEDSEL1=0x86,
>>> LEDSEL2=0x84, LEDSEL3=0x96).
>>>
>>> The only driver code that writes LEDSEL registers is rtl8125_set_led_mode()
>>> in r8169_leds.c, called exclusively from the LED classdev hw_control
>>> callbacks. Therefore, any LED configuration applied via sysfs is silently
>>> overwritten by the hardware chip's own firmware on every Link Up event,
>>> before the driver has a chance to reapply it.
>>>
>>> This was verified by observing that:
>>> 1. Writing 0x0000 to all LEDSEL registers (via BAR0 MMIO) before Link Up
>>>    successfully turns off all LEDs.
>>> 2. After Link Up completes, the LEDSEL registers revert to their hardware
>>>    defaults, turning the LEDs back on.
>>> 3. Writing 0x0000 to LEDSEL registers immediately after Link Up (via
>>>    NetworkManager dispatcher triggered on dhcp4-change) successfully keeps
>>>    the LEDs off persistently.
>>>
>>> Original LEDSEL register values (hardware defaults) on this machine:
>>>   LEDSEL0 (0x18) = 0x0002  (LINK_100)
>>>   LEDSEL1 (0x86) = 0x0028  (LINK_2500 + LINK_1000)
>>>   LEDSEL2 (0x84) = 0x022b  (ACT + LINK_2500 + LINK_1000 + LINK_100 + LINK_10)
>>>   LEDSEL3 (0x96) = 0x0020  (LINK_2500)
>>>
>>> Secondary issue: CONFIG_LEDS_TRIGGER_NETDEV=m causes silent failure
>>>
>>> On Arch Linux, CONFIG_LEDS_TRIGGER_NETDEV=m (module, not built-in).
>>> The r8169 driver uses /* ignore errors */ when calling
>>> led_classdev_register() in rtl8125_setup_led_ldev(). If ledtrig_netdev
>>> is not loaded when r8169 initializes, the registration fails silently.
>>
>> No, it doesn't fail. Just that no trigger is assigned by default.
>> Once you load ledtrig-netdev module and assign netdev trigger to
>> the LED, you can control LED hw modes.
>>
>>
>>> The result is that /sys/class/leds/enp2s0-* entries appear to exist but
>>> are dummy stubs with no hardware control capability. Writing to their
>>> trigger or brightness attributes has no effect on the physical LEDs.
>>>
>> Setting brightness manually isn't supported by HW.
>>
>>> This was verified by manually loading ledtrig_netdev before r8169, which
>>> resulted in functional LED classdev entries. The fix was to add
>>> ledtrig_netdev to /etc/modules-load.d/ to ensure it loads before r8169.
>>>
>>> However, even with ledtrig_netdev loaded correctly and offloaded=1
>>> confirmed, the LED configuration is still lost on every Link Up due to
>>> the hardware reset described above.
>>>
>>> Suggested fix:
>>>
>>> In r8169_phylink_handler(), after Link Up is confirmed, reapply the
>>> current LED configuration by notifying the LED classdevs. For example:
>>>
>>>   if (netif_carrier_ok(ndev)) {
>>>       rtl_link_chg_patch(tp);
>>>       rtl_enable_tx_lpi(tp, tp->phydev->enable_tx_lpi);
>>>       /* Reapply LED configuration after hardware resets LEDSEL on Link Up */
>>>       if (tp->leds)
>>>           led_classdev_notify_clients(tp->leds);  /* or equivalent */
>>>       pm_request_resume(d);
>>>   }
>>>
>>> The exact mechanism for reapplying the LED configuration (whether through
>>> the LED classdev framework or by directly re-calling rtl8125_set_led_mode()
>>> with saved values) is left to your discretion.
>>>
>>> Thanks,
>>> Huan Zhao
>>


  reply	other threads:[~2026-03-15 18:07 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-15  1:46 r8169: RTL8125B restores default LEDSEL values on Link Up, preventing persistent LED configuration Huan Zhao
2026-03-15  9:32 ` Heiner Kallweit
2026-03-19  2:35   ` Javen
2026-03-19  6:49     ` Heiner Kallweit
2026-03-15 13:55 ` Heiner Kallweit
2026-03-15 17:41   ` Huan Zhao
2026-03-15 18:06     ` Heiner Kallweit [this message]
2026-03-15 23:02       ` Huan Zhao

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=67e97f82-1539-4334-8c95-df6b2f01e769@gmail.com \
    --to=hkallweit1@gmail.com \
    --cc=ms.huan.zhao@gmail.com \
    --cc=netdev@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox