mirror of
https://github.com/openwrt/openwrt.git
synced 2025-03-11 06:54:21 +00:00
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@gmail.com> (cherry picked from commit f99c9cd9c4d4c49a676d678327546fd41690fe2a)
This commit is contained in:
parent
8788e86245
commit
718e97c5c8
@ -310,9 +310,11 @@ mt7530_r32(struct mt7530_priv *priv, u32 reg)
|
|||||||
if (priv->bus) {
|
if (priv->bus) {
|
||||||
u16 high, low;
|
u16 high, low;
|
||||||
|
|
||||||
mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
|
mutex_lock(&priv->bus->mdio_lock);
|
||||||
low = mdiobus_read(priv->bus, 0x1f, (reg >> 2) & 0xf);
|
__mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
|
||||||
high = mdiobus_read(priv->bus, 0x1f, 0x10);
|
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);
|
return (high << 16) | (low & 0xffff);
|
||||||
}
|
}
|
||||||
@ -327,9 +329,11 @@ static void
|
|||||||
mt7530_w32(struct mt7530_priv *priv, u32 reg, u32 val)
|
mt7530_w32(struct mt7530_priv *priv, u32 reg, u32 val)
|
||||||
{
|
{
|
||||||
if (priv->bus) {
|
if (priv->bus) {
|
||||||
mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
|
mutex_lock(&priv->bus->mdio_lock);
|
||||||
mdiobus_write(priv->bus, 0x1f, (reg >> 2) & 0xf, val & 0xffff);
|
__mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
|
||||||
mdiobus_write(priv->bus, 0x1f, 0x10, val >> 16);
|
__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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user