[openwrt/openwrt] ramips: mt7530 swconfig: fix race condition in register access

LEDE Commits lede-commits at lists.infradead.org
Sun May 2 13:47:51 BST 2021


hauke pushed a commit to openwrt/openwrt.git, branch openwrt-19.07:
https://git.openwrt.org/718e97c5c84325ef6ab3de5e08e841e150233f52

commit 718e97c5c84325ef6ab3de5e08e841e150233f52
Author: DENG Qingfang <dqfext at gmail.com>
AuthorDate: Mon Apr 26 12:20:24 2021 +0800

    ramips: mt7530 swconfig: fix race condition in register access
    
    [ Upstream commit f99c9cd9c4d4c49a676d678327546fd41690fe2a ]
    
    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 <dqfext at gmail.com>
    (cherry picked from commit f99c9cd9c4d4c49a676d678327546fd41690fe2a)
---
 .../files-4.14/drivers/net/ethernet/mediatek/mt7530.c    | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mt7530.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mt7530.c
index 5216cb5c66..7fb76fca81 100644
--- a/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mt7530.c
+++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mt7530.c
@@ -310,9 +310,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);
 	}
@@ -327,9 +329,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;
 	}
 



More information about the lede-commits mailing list