ar71xx: rb493g: fix gpio-mdio accesses under load
authorJonas Gorski <jogo@openwrt.org>
Wed, 17 Jun 2015 09:55:13 +0000 (09:55 +0000)
committerJonas Gorski <jogo@openwrt.org>
Wed, 17 Jun 2015 09:55:13 +0000 (09:55 +0000)
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 <jogo@openwrt.org>
SVN-Revision: 46012

target/linux/ar71xx/patches-3.18/904-phy-mdio-bitbang-prevent-rescheduling-during-command.patch [new file with mode: 0644]

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 (file)
index 0000000..68f86e0
--- /dev/null
@@ -0,0 +1,61 @@
+From 66e584435ac0de6e0abeb6d7166fe4fe25d6bb73 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+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 <jogo@openwrt.org>
+---
+ 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 <linux/irqflags.h>
+ #include <linux/module.h>
+ #include <linux/mdio-bitbang.h>
+ #include <linux/types.h>
+@@ -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;
+ }