From: Simon Horman <horms@kernel.org>
To: jedrzej.jagielski@intel.com
Cc: Simon Horman <horms@kernel.org>,
intel-wired-lan@lists.osuosl.org, anthony.l.nguyen@intel.com,
netdev@vger.kernel.org
Subject: Re: [Intel-wired-lan] [PATCH iwl-next v1 5/6] ixgbe: E610: add MAC address runtime refresh
Date: Wed, 8 Jul 2026 18:02:15 +0100 [thread overview]
Message-ID: <20260708170223.1514429-1-horms@kernel.org> (raw)
In-Reply-To: <20260702091553.57112-6-jedrzej.jagielski@intel.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
ixgbe: E610: add MAC address runtime refresh
This change polls RAR0 each service-task cycle on E610 and updates
netdev->dev_addr, hw->mac.addr and mac_table[0].addr when firmware has
altered the MAC. A refresh is also invoked from ixgbe_reset() so the
address survives RAR0 clearing during init_hw().
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> index df698ddd08be..eb05c2f982e8 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> @@ -6464,6 +6464,36 @@ void ixgbe_disable_tx(struct ixgbe_adapter *adapter)
> }
> }
>
> +static void ixgbe_mac_addr_refresh(struct ixgbe_adapter *adapter)
> +{
> + struct net_device *netdev = adapter->netdev;
> + struct ixgbe_hw *hw = &adapter->hw;
> + int err;
> +
> + if (hw->mac.type != ixgbe_mac_e610)
> + return;
> +
> + /* fetch address stored currently in RAR0 in case the addr has been
> + * altered by FW; if so, use it as the default one
> + */
> + err = hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
> + if (err) {
> + e_dev_warn("Cannot get MAC address\n");
> + return;
> + }
[High]
Can this overwrite hw->mac.addr with transient/garbage RAR0 contents
before validation? ixgbe_get_mac_addr_generic() unconditionally copies
the raw IXGBE_RAH(0)/IXGBE_RAL(0) values into the buffer passed by the
caller and always returns 0. Here the caller passes hw->mac.addr
itself as the destination:
err = hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
so any transient RAR0 value (all zeros while firmware is rewriting the
register, garbage during the PCI slot-reset/resume window, a
multicast/zero pattern in flight) silently clobbers hw->mac.addr.
The is_valid_ether_addr() check below prevents publishing to netdev,
but it does not restore the previous hw->mac.addr.
Consider reading into a local u8 buf[ETH_ALEN], validating that, and
only then copying into hw->mac.addr.
Compounding that, ixgbe_get_mac_addr_generic()'s own comment states "A
reset of the adapter must be performed prior to calling this function
in order for the MAC address to have been loaded from the EEPROM into
RAR0", but in ixgbe_reset() the refresh runs before init_hw(). Can
this ordering yield a stale/invalid RAR0 read on the reset path?
The corruption is then observable: after the refresh returns,
ixgbe_reset() proceeds through init_hw() and ixgbe_mac_set_default_filter()
memcpy()s hw->mac.addr into mac_table[0].addr and programs it via
set_rar() — a corrupted hw->mac.addr can therefore end up written to
hardware.
> +
> + if (ether_addr_equal(netdev->dev_addr, hw->mac.addr) ||
> + !is_valid_ether_addr(hw->mac.addr))
> + return;
> +
> + ASSERT_RTNL();
> +
> + eth_hw_addr_set(netdev, hw->mac.addr);
> + ether_addr_copy(adapter->mac_table[0].addr, hw->mac.addr);
> +
> + call_netdevice_notifiers(NETDEV_CHANGEADDR, netdev);
> +}
[Medium]
Does this leave hw->mac.perm_addr, netdev->perm_addr and
netdev->addr_assign_type inconsistent with the newly published
address? Every other MAC-handling site in ixgbe (probe,
ixgbe_reset_hw_e610, and the equivalent flows on 82598/82599/X540/X550)
writes RAR0 into hw->mac.perm_addr. After firmware alters the MAC at
runtime, perm_addr will keep reporting the pre-change value, so
consumers such as ethtool -P, bonding and netlink perm-address
attributes will report the stale address while NET_ADDR_PERM is still
advertised for what is now effectively a runtime-assigned MAC.
[Medium]
This unconditionally treats RAR0 (owned by firmware/MGMT) as
authoritative and, on the next service-task tick, silently overwrites
any MAC previously configured via "ip link set dev X address ...":
eth_hw_addr_set(netdev, hw->mac.addr);
ether_addr_copy(adapter->mac_table[0].addr, hw->mac.addr);
call_netdevice_notifiers(NETDEV_CHANGEADDR, netdev);
No log line, no arbitration with an admin-set address, no opt-out.
NETDEV_CHANGEADDR is also emitted from a polling context, which means
userspace (udev, NetworkManager, bridging, bonding) can receive
spontaneous address-change events on E610 with no correlating
administrative action. Should the commit message describe this uAPI
behavior change ("ip link" no longer produces a persistent MAC on
E610), and should there be some form of arbitration or logging when
firmware overrides an admin-configured address?
> +
> void ixgbe_reset(struct ixgbe_adapter *adapter)
> {
> struct ixgbe_hw *hw = &adapter->hw;
> @@ -6481,6 +6511,8 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
> IXGBE_FLAG2_SFP_NEEDS_RESET);
> adapter->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;
>
> + ixgbe_mac_addr_refresh(adapter);
> +
[High]
Is ixgbe_reset() always called with RTNL held? ixgbe_mac_addr_refresh()
uses ASSERT_RTNL() and then dispatches eth_hw_addr_set() and
call_netdevice_notifiers(NETDEV_CHANGEADDR, netdev), both of which
require RTNL.
The follow-up commit "ixgbe: take rtnl lock before ixgbe_reset() is
called" only converts the ixgbe_resume() path. The PCI error-recovery
callback ixgbe_io_slot_reset() still calls ixgbe_reset() without
acquiring rtnl_lock(), and .slot_reset callbacks are not guaranteed to
run under RTNL.
On that path, if RAR0 differs from netdev->dev_addr on an E610,
ASSERT_RTNL() will WARN and the subsequent netdev address publication
and notifier-chain traversal race with concurrent RTNL-protected
users (SIOCSIFHWADDR, notifier chain (un)registration, etc). Should
ixgbe_io_slot_reset() also take rtnl_lock() around ixgbe_reset(), or
should the refresh be moved to a caller-side location that guarantees
RTNL?
> err = hw->mac.ops.init_hw(hw);
> switch (err) {
> case 0:
> @@ -8651,6 +8683,11 @@ static void ixgbe_service_task(struct work_struct *work)
> ixgbe_handle_fw_event(adapter);
> ixgbe_check_media_subtask(adapter);
> }
> +
> + rtnl_lock();
> + ixgbe_mac_addr_refresh(adapter);
> + rtnl_unlock();
> +
[Medium]
Would it make sense to hoist the E610 gating out of
ixgbe_mac_addr_refresh() and skip the rtnl_lock()/rtnl_unlock()
entirely for non-E610 devices?
The type check lives inside the helper:
static void ixgbe_mac_addr_refresh(struct ixgbe_adapter *adapter)
{
...
if (hw->mac.type != ixgbe_mac_e610)
return;
...
}
so 82598, 82599, X540 and X550 adapters (which comprise most of the
ixgbe device family) acquire the global rtnl_mutex every service-task
cycle only to return immediately. Something like:
if (adapter->hw.mac.type == ixgbe_mac_e610) {
rtnl_lock();
ixgbe_mac_addr_refresh(adapter);
rtnl_unlock();
}
would avoid the rtnl_mutex contention on non-E610 hardware.
> ixgbe_reset_subtask(adapter);
> ixgbe_phy_interrupt_subtask(adapter);
> ixgbe_sfp_detection_subtask(adapter);
next prev parent reply other threads:[~2026-07-08 17:02 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-02 9:15 [PATCH iwl-next v1 0/6] ixgbe: improve FW/SW data synchronization Jedrzej Jagielski
2026-07-02 9:15 ` [PATCH iwl-next v1 1/6] ixgbe: E610: init Link Status Events mask just once Jedrzej Jagielski
2026-07-02 9:15 ` [PATCH iwl-next v1 2/6] ixgbe: E610: prevent from disabling LSE Jedrzej Jagielski
2026-07-02 9:15 ` [PATCH iwl-next v1 3/6] ixgbe: E610: do not disable LSE on driver down/remove Jedrzej Jagielski
2026-07-08 17:01 ` Simon Horman
2026-07-09 9:36 ` Jagielski, Jedrzej
2026-07-02 9:15 ` [PATCH iwl-next v1 4/6] ixgbe: E610: re-enable LSE unconditionally Jedrzej Jagielski
2026-07-02 9:15 ` [PATCH iwl-next v1 5/6] ixgbe: E610: add MAC address runtime refresh Jedrzej Jagielski
2026-07-07 13:34 ` [Intel-wired-lan] " Loktionov, Aleksandr
2026-07-08 17:02 ` Simon Horman [this message]
2026-07-09 9:37 ` Jagielski, Jedrzej
2026-07-10 9:57 ` Maciej Fijalkowski
2026-07-02 9:15 ` [PATCH iwl-next v1 6/6] ixgbe: take rtnl lock before ixgbe_reset() is called Jedrzej Jagielski
2026-07-07 13:35 ` [Intel-wired-lan] " Loktionov, Aleksandr
2026-07-08 17:02 ` Simon Horman
2026-07-09 9:38 ` Jagielski, Jedrzej
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=20260708170223.1514429-1-horms@kernel.org \
--to=horms@kernel.org \
--cc=anthony.l.nguyen@intel.com \
--cc=intel-wired-lan@lists.osuosl.org \
--cc=jedrzej.jagielski@intel.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