From: DENG Qingfang Date: Sat, 3 Apr 2021 14:59:15 +0000 (+0800) Subject: ramips: mt7530 swconfig: fix race condition in register access X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=f99c9cd9c4d4c49a676d678327546fd41690fe2a;p=openwrt%2Fstaging%2Fblocktrron.git ramips: mt7530 swconfig: fix race condition in register access The mt7530_{r,w}32 operation over MDIO uses 3 mdiobus operations and does not hold a lock, which causes a race condition when multiple threads try to access a register, they may get unexpected results. To avoid this, handle the MDIO lock manually, and use the unlocked __mdiobus_{read,write} in the critical section. This fixes the "Ghost VLAN" artifact[1] in MT7530/7621 when the VLAN operation and the swconfig LED link status poll race between each other. [1] https://forum.openwrt.org/t/mysterious-vlan-ids-on-mt7621-device/64495 Signed-off-by: DENG Qingfang --- diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c index be1b8a6d8e..b4632d3990 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c @@ -290,9 +290,11 @@ mt7530_r32(struct mt7530_priv *priv, u32 reg) if (priv->bus) { u16 high, low; - mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); - low = mdiobus_read(priv->bus, 0x1f, (reg >> 2) & 0xf); - high = mdiobus_read(priv->bus, 0x1f, 0x10); + mutex_lock(&priv->bus->mdio_lock); + __mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); + low = __mdiobus_read(priv->bus, 0x1f, (reg >> 2) & 0xf); + high = __mdiobus_read(priv->bus, 0x1f, 0x10); + mutex_unlock(&priv->bus->mdio_lock); return (high << 16) | (low & 0xffff); } @@ -307,9 +309,11 @@ static void mt7530_w32(struct mt7530_priv *priv, u32 reg, u32 val) { if (priv->bus) { - mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); - mdiobus_write(priv->bus, 0x1f, (reg >> 2) & 0xf, val & 0xffff); - mdiobus_write(priv->bus, 0x1f, 0x10, val >> 16); + mutex_lock(&priv->bus->mdio_lock); + __mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); + __mdiobus_write(priv->bus, 0x1f, (reg >> 2) & 0xf, val & 0xffff); + __mdiobus_write(priv->bus, 0x1f, 0x10, val >> 16); + mutex_unlock(&priv->bus->mdio_lock); return; }