[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20251025160905.3857885-103-sashal@kernel.org>
Date: Sat, 25 Oct 2025 11:55:34 -0400
From: Sasha Levin <sashal@...nel.org>
To: patches@...ts.linux.dev,
stable@...r.kernel.org
Cc: Colin Foster <colin.foster@...advantage.com>,
Jakub Kicinski <kuba@...nel.org>,
Sasha Levin <sashal@...nel.org>,
steve.glendinning@...well.net,
netdev@...r.kernel.org
Subject: [PATCH AUTOSEL 6.17-6.1] smsc911x: add second read of EEPROM mac when possible corruption seen
From: Colin Foster <colin.foster@...advantage.com>
[ Upstream commit 69777753a8919b0b8313c856e707e1d1fe5ced85 ]
When the EEPROM MAC is read by way of ADDRH, it can return all 0s the
first time. Subsequent reads succeed.
This is fully reproduceable on the Phytec PCM049 SOM.
Re-read the ADDRH when this behaviour is observed, in an attempt to
correctly apply the EEPROM MAC address.
Signed-off-by: Colin Foster <colin.foster@...advantage.com>
Link: https://patch.msgid.link/20250903132610.966787-1-colin.foster@in-advantage.com
Signed-off-by: Jakub Kicinski <kuba@...nel.org>
Signed-off-by: Sasha Levin <sashal@...nel.org>
---
LLM Generated explanations, may be completely bogus:
YES
- What changed
- In `drivers/net/ethernet/smsc/smsc911x.c:2162`,
`smsc911x_read_mac_address()` now re-reads the MAC high register
(`ADDRH`) once if the first read returns 0, then uses the second
value: `drivers/net/ethernet/smsc/smsc911x.c:2168`,
`drivers/net/ethernet/smsc/smsc911x.c:2174-2177`.
- The function still reads `ADDRL` once and programs `dev->dev_addr`
via `eth_hw_addr_set()`:
`drivers/net/ethernet/smsc/smsc911x.c:2169`,
`drivers/net/ethernet/smsc/smsc911x.c:2179-2185`.
- A trace message is added for visibility when the re-read path is
taken: `drivers/net/ethernet/smsc/smsc911x.c:2175`.
- Why it matters (user-visible bug)
- The commit fixes a real-world, reproducible issue where reading the
EEPROM-backed MAC via `ADDRH` can spuriously return all zeros on the
first attempt (commit message), leading to an incorrect MAC or
fallback to a random MAC during probe.
- This behavior is seen on the Phytec PCM049 SoM; without the fix,
users may get an invalid or non-persistent MAC at boot.
- Scope and containment
- Change is confined to a single driver and a single function
(`smsc911x_read_mac_address()`), only affecting initialization-time
MAC retrieval.
- Callers invoke this function under `mac_lock` (e.g., pre-reset save
path `drivers/net/ethernet/smsc/smsc911x.c:2308-2311`, and post-
registration selection path
`drivers/net/ethernet/smsc/smsc911x.c:2533-2547`), matching the
expectation of `smsc911x_mac_read()` that the lock is held
(`drivers/net/ethernet/smsc/smsc911x.c:492-520`).
- Safety and regression risk
- The re-read only occurs when `ADDRH` initially returns 0. If a
device legitimately has a MAC with 0 in the upper two bytes (ending
in “:00:00”), the second read is harmless and preserves the same
value.
- No timing changes beyond one extra register read in a rare path; no
sleeps are introduced; locking discipline remains unchanged.
- `smsc911x_mac_read()` returns `0xFFFFFFFF` on busy/error (not 0), so
the new check won’t mask those failures; the new logic specifically
addresses the “all zeros on first `ADDRH` read” quirk.
- No API, UAPI, or architectural changes; only driver-internal logic.
Minimal chance of regression.
- Impacted flows
- Early pre-reset MAC preservation when `SMSC911X_SAVE_MAC_ADDRESS` is
set: `drivers/net/ethernet/smsc/smsc911x.c:2308-2311`.
- Normal probe-time MAC selection when none is preconfigured:
`drivers/net/ethernet/smsc/smsc911x.c:2533-2559`, where
`smsc_get_mac(dev)` invokes the updated function
`drivers/net/ethernet/smsc/smsc911x.h:404`.
- Stable backport criteria
- Fixes an initialization-time correctness bug affecting real
hardware.
- Small, targeted change with trivial logic and very low risk.
- No new features or architectural shifts; contained to one driver
file.
- Improves reliability in a way users will notice (correct MAC vs.
random/invalid).
Given the user-visible bug, minimal risk, and tight scope, this is a
good candidate for stable backport.
drivers/net/ethernet/smsc/smsc911x.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 6ca290f7c0dfb..3ebd0664c697f 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -2162,10 +2162,20 @@ static const struct net_device_ops smsc911x_netdev_ops = {
static void smsc911x_read_mac_address(struct net_device *dev)
{
struct smsc911x_data *pdata = netdev_priv(dev);
- u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH);
- u32 mac_low32 = smsc911x_mac_read(pdata, ADDRL);
+ u32 mac_high16, mac_low32;
u8 addr[ETH_ALEN];
+ mac_high16 = smsc911x_mac_read(pdata, ADDRH);
+ mac_low32 = smsc911x_mac_read(pdata, ADDRL);
+
+ /* The first mac_read in some setups can incorrectly read 0. Re-read it
+ * to get the full MAC if this is observed.
+ */
+ if (mac_high16 == 0) {
+ SMSC_TRACE(pdata, probe, "Re-read MAC ADDRH\n");
+ mac_high16 = smsc911x_mac_read(pdata, ADDRH);
+ }
+
addr[0] = (u8)(mac_low32);
addr[1] = (u8)(mac_low32 >> 8);
addr[2] = (u8)(mac_low32 >> 16);
--
2.51.0
Powered by blists - more mailing lists