From: Jonas Gorski Date: Wed, 17 Jun 2015 09:55:13 +0000 (+0000) Subject: ar71xx: rb493g: fix gpio-mdio accesses under load X-Git-Tag: reboot~2757 X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=01796e87b169ef53d51f88a32d2550c1f914808a;p=openwrt%2Fstaging%2Fblogic.git ar71xx: rb493g: fix gpio-mdio accesses under load It seems that there are maximum timings for mdio accesses that can be hit when the system is under load and the thread is scheduled during a read or write access. Since there is no way of knowing if this happens as there is not even a parity bit, try to work around it by disabling interrupts during any gpio-mdio accesses. Performance impact seems to be neglectable, as mdio accesses are not that often. Hopefully fixes #19500. Signed-off-by: Jonas Gorski SVN-Revision: 46012 --- diff --git a/target/linux/ar71xx/patches-3.18/904-phy-mdio-bitbang-prevent-rescheduling-during-command.patch b/target/linux/ar71xx/patches-3.18/904-phy-mdio-bitbang-prevent-rescheduling-during-command.patch new file mode 100644 index 000000000000..68f86e0e09d2 --- /dev/null +++ b/target/linux/ar71xx/patches-3.18/904-phy-mdio-bitbang-prevent-rescheduling-during-command.patch @@ -0,0 +1,61 @@ +From 66e584435ac0de6e0abeb6d7166fe4fe25d6bb73 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Tue, 16 Jun 2015 13:15:08 +0200 +Subject: [PATCH] phy/mdio-bitbang: prevent rescheduling during command + +It seems some phys have some maximum timings for accessing the MDIO line, +resulting in bit errors under cpu stress. Prevent this from happening by +disabling interrupts when sending commands. + +Signed-off-by: Jonas Gorski +--- + drivers/net/phy/mdio-bitbang.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/net/phy/mdio-bitbang.c ++++ b/drivers/net/phy/mdio-bitbang.c +@@ -17,6 +17,7 @@ + * kind, whether express or implied. + */ + ++#include + #include + #include + #include +@@ -156,7 +157,9 @@ static int mdiobb_read(struct mii_bus *b + { + struct mdiobb_ctrl *ctrl = bus->priv; + int ret, i; ++ long flags; + ++ local_irq_save(flags); + if (reg & MII_ADDR_C45) { + reg = mdiobb_cmd_addr(ctrl, phy, reg); + mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); +@@ -169,13 +172,17 @@ static int mdiobb_read(struct mii_bus *b + + ret = mdiobb_get_num(ctrl, 16); + mdiobb_get_bit(ctrl); ++ local_irq_restore(flags); ++ + return ret; + } + + static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) + { + struct mdiobb_ctrl *ctrl = bus->priv; ++ long flags; + ++ local_irq_save(flags); + if (reg & MII_ADDR_C45) { + reg = mdiobb_cmd_addr(ctrl, phy, reg); + mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); +@@ -190,6 +197,8 @@ static int mdiobb_write(struct mii_bus * + + ctrl->ops->set_mdio_dir(ctrl, 0); + mdiobb_get_bit(ctrl); ++ local_irq_restore(flags); ++ + return 0; + } +