Re: [Intel-wired-lan] [PATCH 1/2] igc: Wait for MAC passthrough after reset
From: Ruinskiy, Dima
Date: Mon Jun 29 2026 - 12:43:27 EST
Hi AceLan,
Some more comments below.
On 22/06/2026 4:57, Chia-Lin Kao (AceLan) wrote:
5 seconds also sounds excessive, assuming the majority of the systems do not support / enable MAC passthrough via the FW feature (and I have a hunch it is the case). 2 seconds... maybe, but then you say that in some rare cases it exceeds 2 seconds as well. What if in some even rare cases it exceeds 5/10 seconds? Perhaps because of some glitch it will not come up at all on this cycle. Should the driver always wait?Yes, just in case it takes longer.
Because 100 iterations of 100msec each - this translates to up-to 10
seconds, no?
I think 5 seconds should be enough if you feel this is feasible.
I wish we can detect if the MAC passthrough is enabled, so that weUnfortunately, like you I am not aware of any way for the driver to know whether MAC passthrough via FW is enabled. Because of this we have been exploring a simpler way to support this feature via ACPI objects (which are set by the BIOS when MAC passthrough is enabled and are easy for the driver to query). I know some vendors have already implemented it, and I am currently drafting a patch to send.
know if we need to poll for the MAC address.
For the FW interrupt mechanism also needs BIOS support, and we don'tThe mechanism I have in mind does not require BIOS support - the I225/I226 FW already supports the required interrupt, AFAIK - it merely needs to be enabled in the igc driver. With that said, there still remains the question of how to notify the network stack above us that the MAC address has changed post-probe - and whether it is even supported.
have the power to push this.
--Dima
Thanks,
Dima.
Signed-off-by: Chia-Lin Kao (AceLan) <acelan.kao@xxxxxxxxxxxxx>
---
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