From: Dima Ruinskiy Some systems implement a system MAC address object in the ACPI table, using either \\_SB.AMAC or \\MACA object names. This system MAC address, when enabled, is intended to override the permanent MAC address of the network controller. Implement lookup of the relevant ACPI object names and use them to initialize the MAC address. On systems where the feature is disabled or unsupported, the ACPI objects do not exist or do not contain a valid Ethernet MAC, causing a fallback to the existing MAC address initialization path. Assisted-by: GitHub-Copilot:claude-opus-4.7 Signed-off-by: Dima Ruinskiy Tested-by: Chia-Lin Kao (AceLan) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/igc/igc_main.c | 64 ++++++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 21d2fe38a41a..424c12c0394a 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include @@ -7105,6 +7107,57 @@ static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer) return HRTIMER_NORESTART; } +static bool igc_get_acpi_mac_passthru(u8 *mac) +{ + static const struct { + const char *name; + acpi_object_type type; + u32 length; + } sources[] = { + { "\\_SB.AMAC", ACPI_TYPE_BUFFER, 23 }, + { "\\MACA", ACPI_TYPE_STRING, 22 }, + }; + struct acpi_buffer buffer; + union acpi_object *obj; + bool mac_found = false; + acpi_status status; + u8 buf[ETH_ALEN]; + int i; + + if (!IS_ENABLED(CONFIG_ACPI)) + return false; + + for (i = 0; i < ARRAY_SIZE(sources) && !mac_found; i++) { + buffer.length = ACPI_ALLOCATE_BUFFER; + buffer.pointer = NULL; + + status = acpi_evaluate_object(NULL, (char *)sources[i].name, + NULL, &buffer); + if (ACPI_FAILURE(status)) + continue; + + obj = buffer.pointer; + if (!obj || obj->type != sources[i].type || + obj->string.length != sources[i].length) + goto free_obj; + + if (strncmp(obj->string.pointer, "_AUXMAC_#", 9) || + obj->string.pointer[21] != '#') + goto free_obj; + + if (hex2bin(buf, obj->string.pointer + 9, ETH_ALEN) || + !is_valid_ether_addr(buf)) + goto free_obj; + + ether_addr_copy(mac, buf); + mac_found = true; +free_obj: + kfree(obj); + } + + return mac_found; +} + /** * igc_probe - Device Initialization Routine * @pdev: PCI device information struct @@ -7268,9 +7321,16 @@ static int igc_probe(struct pci_dev *pdev, } if (eth_platform_get_mac_address(&pdev->dev, hw->mac.addr)) { - /* copy the MAC address out of the NVM */ - if (hw->mac.ops.read_mac_addr(hw)) + /* Look for a system-provided MAC in the ACPI table before + * falling back to reading the address from the NVM. + */ + if (igc_get_acpi_mac_passthru(hw->mac.addr)) { + netdev->addr_assign_type = NET_ADDR_STOLEN; + dev_info(&pdev->dev, "Using ACPI pass-through MAC addr %pM\n", + hw->mac.addr); + } else if (hw->mac.ops.read_mac_addr(hw)) { dev_err(&pdev->dev, "NVM Read Error\n"); + } } eth_hw_addr_set(netdev, hw->mac.addr); -- 2.47.1