aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2011-05-08 16:32:53 +0000
committerGabor Juhos <juhosg@openwrt.org>2011-05-08 16:32:53 +0000
commit5d77f370d695c9a70f25ffb8367db64efadaaedd (patch)
tree447565cb138433c4789c5f2010512d9a0db57361
parent37116582811963a277f3219059371998645e0b13 (diff)
downloadupstream-5d77f370d695c9a70f25ffb8367db64efadaaedd.tar.gz
upstream-5d77f370d695c9a70f25ffb8367db64efadaaedd.tar.bz2
upstream-5d77f370d695c9a70f25ffb8367db64efadaaedd.zip
ar71xx: ag71xx: make switch register access atomic
Reading of the PHY registers occasionally returns with bogus values under heavy load. This misleads the PHY driver and thus causes false link/speed change notifications which leads to performance loss. This is easily noticable during an iperf session: ... [ 3] 52.0-53.0 sec 11.3 MBytes 94.4 Mbits/sec [ 3] 53.0-54.0 sec 11.4 MBytes 95.4 Mbits/sec eth1: link down br-lan: port 2(eth1) entering forwarding state eth1: link up (100Mbps/Full duplex) br-lan: port 2(eth1) entering forwarding state br-lan: port 2(eth1) entering forwarding state [ 3] 54.0-55.0 sec 6.75 MBytes 56.6 Mbits/sec [ 3] 55.0-56.0 sec 0.00 Bytes 0.00 bits/sec [ 3] 56.0-57.0 sec 10.5 MBytes 88.1 Mbits/sec ... [ 3] 169.0-170.0 sec 11.4 MBytes 95.4 Mbits/sec [ 3] 170.0-171.0 sec 11.4 MBytes 95.4 Mbits/sec eth1: link up (10Mbps/Half duplex) [ 3] 171.0-172.0 sec 7.63 MBytes 64.0 Mbits/sec [ 3] 172.0-173.0 sec 9.38 MBytes 78.6 Mbits/sec eth1: link up (100Mbps/Full duplex) [ 3] 173.0-174.0 sec 11.3 MBytes 94.4 Mbits/sec [ 3] 174.0-175.0 sec 11.4 MBytes 95.4 Mbits/sec SVN-Revision: 26856
-rw-r--r--target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c
index 0270e60511..1bc7f58c17 100644
--- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c
+++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c
@@ -233,37 +233,39 @@ static inline u16 mk_high_addr(u32 reg)
static u32 __ar7240sw_reg_read(struct mii_bus *mii, u32 reg)
{
+ unsigned long flags;
u16 phy_addr;
u16 phy_reg;
u32 hi, lo;
reg = (reg & 0xfffffffc) >> 2;
-
- ag71xx_mdio_mii_write(mii->priv, 0x1f, 0x10, mk_high_addr(reg));
-
phy_addr = mk_phy_addr(reg);
phy_reg = mk_phy_reg(reg);
+ local_irq_save(flags);
+ ag71xx_mdio_mii_write(mii->priv, 0x1f, 0x10, mk_high_addr(reg));
lo = (u32) ag71xx_mdio_mii_read(mii->priv, phy_addr, phy_reg);
hi = (u32) ag71xx_mdio_mii_read(mii->priv, phy_addr, phy_reg + 1);
+ local_irq_restore(flags);
return (hi << 16) | lo;
}
static void __ar7240sw_reg_write(struct mii_bus *mii, u32 reg, u32 val)
{
+ unsigned long flags;
u16 phy_addr;
u16 phy_reg;
reg = (reg & 0xfffffffc) >> 2;
-
- ag71xx_mdio_mii_write(mii->priv, 0x1f, 0x10, mk_high_addr(reg));
-
phy_addr = mk_phy_addr(reg);
phy_reg = mk_phy_reg(reg);
+ local_irq_save(flags);
+ ag71xx_mdio_mii_write(mii->priv, 0x1f, 0x10, mk_high_addr(reg));
ag71xx_mdio_mii_write(mii->priv, phy_addr, phy_reg + 1, (val >> 16));
ag71xx_mdio_mii_write(mii->priv, phy_addr, phy_reg, (val & 0xffff));
+ local_irq_restore(flags);
}
static u32 ar7240sw_reg_read(struct mii_bus *mii, u32 reg_addr)