> -----Original Message-----
> From: Intel-wired-lan <[email protected]> On Behalf
> Of Chia-Lin Kao (AceLan) via Intel-wired-lan
> Sent: Thursday, June 18, 2026 9:33 AM
> To: Nguyen, Anthony L <[email protected]>; Kitszel,
> Przemyslaw <[email protected]>
> Cc: Andrew Lunn <[email protected]>; David S. Miller
> <[email protected]>; Eric Dumazet <[email protected]>; Jakub
> Kicinski <[email protected]>; Paolo Abeni <[email protected]>; intel-
> [email protected]; [email protected]; linux-
> [email protected]
> Subject: [Intel-wired-lan] [PATCH 1/2] igc: Wait for MAC passthrough
> after reset
> 
> Some systems support MAC passthrough for dock Ethernet controllers by
> having firmware rewrite the receive address registers after the
> controller reset completes.
> 
> igc resets the controller before reading RAL0/RAH0, so that reset can
> restore the controller native MAC address temporarily. If the driver
> reads the registers immediately, it can race the firmware rewrite and
> keep the native dock MAC instead of the host passthrough MAC.
> 
> For LMVP devices, poll RAL0/RAH0 after reset and before reading the
> MAC address. Stop once the address registers change to another valid
> Ethernet address, allowing firmware a bounded window to complete the
> passthrough update.
> 
Good day, Chia-Lin

It'd be great if you could share more details on how to reproduce the issue.

What exact hardware setup is affected (dock model, NIC, system)?
Which firmware/BIOS version?
How often does the race trigger?
Do you have a way to reliably reproduce it?

Also, what is the observed behavior vs. expected behavior? For example,
which MAC address is seen and which one should be used?


> Signed-off-by: Chia-Lin Kao (AceLan) <[email protected]>
> ---
>  drivers/net/ethernet/intel/igc/igc_main.c | 48
> +++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
> 
> diff --git a/drivers/net/ethernet/intel/igc/igc_main.c
> b/drivers/net/ethernet/intel/igc/igc_main.c
> index 2c9e2dfd8499..fa9752ed8bc5 100644
> --- a/drivers/net/ethernet/intel/igc/igc_main.c
> +++ b/drivers/net/ethernet/intel/igc/igc_main.c
> @@ -11,6 +11,7 @@
>  #include <net/pkt_sched.h>
>  #include <linux/bpf_trace.h>
>  #include <net/xdp_sock_drv.h>
> +#include <linux/etherdevice.h>
>  #include <linux/pci.h>
>  #include <linux/mdio.h>
> 
> @@ -69,6 +70,52 @@ static const struct pci_device_id igc_pci_tbl[] = {
> 
>  MODULE_DEVICE_TABLE(pci, igc_pci_tbl);
> 
> +static void igc_read_rar0(struct igc_hw *hw, u8 *addr, u32 *ral, u32
> +*rah) {
> +     *ral = rd32(IGC_RAL(0));
> +     *rah = rd32(IGC_RAH(0));
> +
> +     addr[0] = *ral & 0xff;
> +     addr[1] = (*ral >> 8) & 0xff;
> +     addr[2] = (*ral >> 16) & 0xff;
> +     addr[3] = (*ral >> 24) & 0xff;
> +     addr[4] = *rah & 0xff;
> +     addr[5] = (*rah >> 8) & 0xff;
> +}
> +
> +static bool igc_is_lmvp_device(struct pci_dev *pdev) {
> +     switch (pdev->device) {
> +     case IGC_DEV_ID_I225_LMVP:
> +     case IGC_DEV_ID_I226_LMVP:
> +             return true;
> +     default:
> +             return false;
> +     }
> +}
> +
> +static void igc_wait_for_lmvp_mac_passthrough(struct pci_dev *pdev,
> +                                           struct igc_hw *hw)
> +{
> +     u8 addr[ETH_ALEN] __aligned(2);
> +     u32 orig_ral, orig_rah;
> +     u32 ral, rah;
> +     int i;
> +
> +     if (!igc_is_lmvp_device(pdev))
> +             return;
> +
> +     igc_read_rar0(hw, addr, &orig_ral, &orig_rah);
> +
> +     for (i = 0; i < 100; i++) {
> +             msleep(100);
> +             igc_read_rar0(hw, addr, &ral, &rah);
> +             if ((ral != orig_ral || rah != orig_rah) &&
> +                 is_valid_ether_addr(addr))
> +                     return;
> +     }
> +}
> +
>  enum latency_range {
>       lowest_latency = 0,
>       low_latency = 1,
> @@ -7259,6 +7306,7 @@ static int igc_probe(struct pci_dev *pdev,
>        * known good starting state
>        */
>       hw->mac.ops.reset_hw(hw);
> +     igc_wait_for_lmvp_mac_passthrough(pdev, hw);
> 
>       if (igc_get_flash_presence_i225(hw)) {
>               if (hw->nvm.ops.validate(hw) < 0) {
> --
> 2.53.0

Reply via email to