summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-08-07 16:37:50 -0700
committerJakub Kicinski <kuba@kernel.org>2026-08-07 16:39:06 -0700
commit0200d48477602541419a26933c04ce0c331a482a (patch)
tree6f50f483bfaa820d6fe9d1ee5807dfdf04eb6404
parent0023e4c6171dc71ec6d0ee4cab45e67d5f5e2ea4 (diff)
parentdd52b3df25ed25a7a881d45d9fbfaa0ac7dec5d5 (diff)
downloadlinux-0200d48477602541419a26933c04ce0c331a482a.tar.gz
linux-0200d48477602541419a26933c04ce0c331a482a.zip
Merge branch 'net-dsa-mt7530-fix-remaining-swallowed-mdio-access-errors'
Daniel Golle says: ==================== net: dsa: mt7530: fix remaining swallowed MDIO access errors The original series, "net: dsa: mt7530: fix swallowed MDIO read errors", landed on net as its v1 [1] just before its v2 [2] was sent. This series started from the fixes in that original v2 which its v1 had not already carried: the two standalone patches that original v2 grew from the Sashiko AI review of its v1 (the mtk-lynxi read check and the regmap IRQ serialization), plus, split into patches of their own, the companion fixes original v2 had folded into the already-applied patches -- the unchecked bus->read() in core_rmw() and the unchecked PHY_IAC command writes in the MT7531 indirect PHY access functions. The Sashiko AI review of this series' own v1 [3] then flagged two more swallowed MDIO errors of the same kind, added here as patches of their own: the unchecked CORE_PLL_GROUP4 read-modify-write in mt7531_setup(), and the unchecked ATC/VTCR command-register writes in mt7530_fdb_cmd() and mt7530_vlan_cmd(). The remaining non-fix changes from the original v2, dropping a redundant read-back and improving the poll failure messages, will follow via net-next. [1] https://lore.kernel.org/netdev/cover.1785213071.git.daniel@makrotopia.org/ [2] https://lore.kernel.org/netdev/cover.1785368701.git.daniel@makrotopia.org/ [3] https://lore.kernel.org/netdev/cover.1785427248.git.daniel@makrotopia.org/ ==================== Link: https://patch.msgid.link/cover.1785811140.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/dsa/mt7530.c86
-rw-r--r--drivers/net/pcs/pcs-mtk-lynxi.c7
2 files changed, 75 insertions, 18 deletions
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 55131bfd11f6..2b7be091c056 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -124,8 +124,12 @@ core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set)
goto err;
/* Read the content of the MMD's selected register */
- val = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
+ ret = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MII_MMD_DATA);
+ if (ret < 0)
+ goto err;
+ val = ret;
+
val &= ~mask;
val |= set;
/* Write the data into MMD's selected register */
@@ -181,14 +185,18 @@ mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
return val;
}
-static void
+static int
mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)
{
+ int ret;
+
mt7530_mutex_lock(priv);
- mt7530_mii_write(priv, reg, val);
+ ret = mt7530_mii_write(priv, reg, val);
mt7530_mutex_unlock(priv);
+
+ return ret;
}
static u32
@@ -245,7 +253,9 @@ mt7530_fdb_cmd(struct mt7530_priv *priv, enum mt7530_fdb_cmd cmd, u32 *rsp)
/* Set the command operating upon the MAC address entries */
val = ATC_BUSY | ATC_MAT(0) | cmd;
- mt7530_write(priv, MT7530_ATC, val);
+ ret = mt7530_write(priv, MT7530_ATC, val);
+ if (ret)
+ return ret;
mt7530_mutex_lock(priv);
@@ -561,7 +571,9 @@ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
reg = MT7531_MDIO_CL45_ADDR | MT7531_MDIO_PHY_ADDR(port) |
MT7531_MDIO_DEV_ADDR(devad) | regnum;
- mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
+ ret = mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
+ if (ret < 0)
+ goto out;
ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
!(val & MT7531_PHY_ACS_ST), 20, 100000);
@@ -572,7 +584,9 @@ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
reg = MT7531_MDIO_CL45_READ | MT7531_MDIO_PHY_ADDR(port) |
MT7531_MDIO_DEV_ADDR(devad);
- mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
+ ret = mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
+ if (ret < 0)
+ goto out;
ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
!(val & MT7531_PHY_ACS_ST), 20, 100000);
@@ -606,7 +620,9 @@ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
reg = MT7531_MDIO_CL45_ADDR | MT7531_MDIO_PHY_ADDR(port) |
MT7531_MDIO_DEV_ADDR(devad) | regnum;
- mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
+ ret = mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
+ if (ret < 0)
+ goto out;
ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
!(val & MT7531_PHY_ACS_ST), 20, 100000);
@@ -617,7 +633,9 @@ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
reg = MT7531_MDIO_CL45_WRITE | MT7531_MDIO_PHY_ADDR(port) |
MT7531_MDIO_DEV_ADDR(devad) | data;
- mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
+ ret = mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
+ if (ret < 0)
+ goto out;
ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
!(val & MT7531_PHY_ACS_ST), 20, 100000);
@@ -650,7 +668,9 @@ mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
val = MT7531_MDIO_CL22_READ | MT7531_MDIO_PHY_ADDR(port) |
MT7531_MDIO_REG_ADDR(regnum);
- mt7530_mii_write(priv, MT7531_PHY_IAC, val | MT7531_PHY_ACS_ST);
+ ret = mt7530_mii_write(priv, MT7531_PHY_IAC, val | MT7531_PHY_ACS_ST);
+ if (ret < 0)
+ goto out;
ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
!(val & MT7531_PHY_ACS_ST), 20, 100000);
@@ -685,7 +705,9 @@ mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
reg = MT7531_MDIO_CL22_WRITE | MT7531_MDIO_PHY_ADDR(port) |
MT7531_MDIO_REG_ADDR(regnum) | data;
- mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
+ ret = mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
+ if (ret < 0)
+ goto out;
ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, reg,
!(reg & MT7531_PHY_ACS_ST), 20, 100000);
@@ -1616,7 +1638,9 @@ mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid)
int ret;
val = VTCR_BUSY | VTCR_FUNC(cmd) | vid;
- mt7530_write(priv, MT7530_VTCR, val);
+ ret = mt7530_write(priv, MT7530_VTCR, val);
+ if (ret)
+ return ret;
mt7530_mutex_lock(priv);
@@ -2295,6 +2319,21 @@ static const struct regmap_irq mt7530_irqs[] = {
REGMAP_IRQ_REG_LINE(31, 32), /* ACL */
};
+/* Serialize regmap-irq's mask sync like every other regmap user */
+static int mt7530_irq_mask_sync(int index, unsigned int mask_buf_def,
+ unsigned int mask_buf, void *irq_drv_data)
+{
+ struct mt7530_priv *priv = irq_drv_data;
+ int ret;
+
+ mt7530_mutex_lock(priv);
+ ret = regmap_update_bits(priv->regmap, MT7530_SYS_INT_EN,
+ mask_buf_def, ~mask_buf);
+ mt7530_mutex_unlock(priv);
+
+ return ret;
+}
+
static const struct regmap_irq_chip mt7530_regmap_irq_chip = {
.name = KBUILD_MODNAME,
.status_base = MT7530_SYS_INT_STS,
@@ -2304,12 +2343,14 @@ static const struct regmap_irq_chip mt7530_regmap_irq_chip = {
.irqs = mt7530_irqs,
.num_irqs = ARRAY_SIZE(mt7530_irqs),
.num_regs = 1,
+ .handle_mask_sync = mt7530_irq_mask_sync,
};
static int
mt7530_setup_irq(struct mt7530_priv *priv)
{
struct regmap_irq_chip_data *irq_data;
+ struct regmap_irq_chip *chip;
struct device *dev = priv->dev;
struct device_node *np = dev->of_node;
int irq, ret;
@@ -2329,10 +2370,17 @@ mt7530_setup_irq(struct mt7530_priv *priv)
if (priv->id == ID_MT7530 || priv->id == ID_MT7621)
mt7530_set(priv, MT7530_TOP_SIG_CTRL, TOP_SIG_CTRL_NORMAL);
+ chip = devm_kmemdup(dev, &mt7530_regmap_irq_chip, sizeof(*chip),
+ GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->irq_drv_data = priv;
+
ret = devm_regmap_add_irq_chip_fwnode(dev, dev_fwnode(dev),
priv->regmap, irq,
IRQF_ONESHOT,
- 0, &mt7530_regmap_irq_chip,
+ 0, chip,
&irq_data);
if (ret)
return ret;
@@ -2765,14 +2813,20 @@ mt7531_setup(struct dsa_switch *ds)
* phy_[read,write]_mmd_indirect is called, we provide our own
* mt7531_ind_mmd_phy_[read,write] to complete this function.
*/
- val = mt7531_ind_c45_phy_read(priv,
+ ret = mt7531_ind_c45_phy_read(priv,
MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MDIO_MMD_VEND2, CORE_PLL_GROUP4);
+ if (ret < 0)
+ return ret;
+
+ val = ret;
val |= MT7531_RG_SYSPLL_DMY2 | MT7531_PHY_PLL_BYPASS_MODE;
val &= ~MT7531_PHY_PLL_OFF;
- mt7531_ind_c45_phy_write(priv,
- MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
- MDIO_MMD_VEND2, CORE_PLL_GROUP4, val);
+ ret = mt7531_ind_c45_phy_write(priv,
+ MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
+ MDIO_MMD_VEND2, CORE_PLL_GROUP4, val);
+ if (ret < 0)
+ return ret;
/* Disable EEE advertisement on the switch PHYs. */
for (i = MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr);
diff --git a/drivers/net/pcs/pcs-mtk-lynxi.c b/drivers/net/pcs/pcs-mtk-lynxi.c
index a753bd88cbc2..7290fc3e5d18 100644
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
@@ -113,8 +113,11 @@ static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs,
unsigned int bm, adv;
/* Read the BMSR and LPA */
- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm);
- regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv);
+ if (regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm) ||
+ regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv)) {
+ state->link = false;
+ return;
+ }
phylink_mii_c22_pcs_decode_state(state, neg_mode,
FIELD_GET(SGMII_BMSR, bm),