Netdev List
 help / color / mirror / Atom feed
* [PATCH 1/2] igc: Wait for MAC passthrough after reset
@ 2026-06-18  7:33 Chia-Lin Kao (AceLan)
  2026-06-18  7:33 ` [PATCH 2/2] igc: Cache MAC passthrough address Chia-Lin Kao (AceLan)
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Chia-Lin Kao (AceLan) @ 2026-06-18  7:33 UTC (permalink / raw)
  To: Tony Nguyen, Przemek Kitszel
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, intel-wired-lan, netdev, linux-kernel

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.

Signed-off-by: Chia-Lin Kao (AceLan) <acelan.kao@canonical.com>
---
 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


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-06-18 10:12 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-18  7:33 [PATCH 1/2] igc: Wait for MAC passthrough after reset Chia-Lin Kao (AceLan)
2026-06-18  7:33 ` [PATCH 2/2] igc: Cache MAC passthrough address Chia-Lin Kao (AceLan)
2026-06-18  7:55 ` [Intel-wired-lan] [PATCH 1/2] igc: Wait for MAC passthrough after reset Loktionov, Aleksandr
2026-06-18  8:51   ` Ruinskiy, Dima
2026-06-18  8:08 ` Andrew Lunn
2026-06-18  8:49 ` [Intel-wired-lan] " Kwapulinski, Piotr
2026-06-18 10:11 ` Paul Menzel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox