aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-5.10/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/backport-5.10/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch')
-rw-r--r--target/linux/generic/backport-5.10/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch50
1 files changed, 50 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.10/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch b/target/linux/generic/backport-5.10/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch
new file mode 100644
index 0000000000..4593da032b
--- /dev/null
+++ b/target/linux/generic/backport-5.10/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch
@@ -0,0 +1,50 @@
+From 63c33bbfeb6842a956a0eb12901e28eb335bdb18 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth@gmail.com>
+Date: Fri, 14 May 2021 23:00:07 +0200
+Subject: [PATCH] net: dsa: qca8k: clear MASTER_EN after phy read/write
+
+Clear MDIO_MASTER_EN bit from MDIO_MASTER_CTRL after read/write
+operation. The MDIO_MASTER_EN bit is not reset after read/write
+operation and the next operation can be wrongly interpreted by the
+switch as a mdio operation. This cause a production of wrong/garbage
+data from the switch and underfined bheavior. (random port drop,
+unplugged port flagged with link up, wrong port speed)
+Also on driver remove the MASTER_CTRL can be left set and cause the
+malfunction of any next driver using the mdio device.
+
+Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -649,8 +649,14 @@ qca8k_mdio_write(struct qca8k_priv *priv
+ if (ret)
+ return ret;
+
+- return qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
+- QCA8K_MDIO_MASTER_BUSY);
++ ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
++ QCA8K_MDIO_MASTER_BUSY);
++
++ /* even if the busy_wait timeouts try to clear the MASTER_EN */
++ qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
++ QCA8K_MDIO_MASTER_EN);
++
++ return ret;
+ }
+
+ static int
+@@ -685,6 +691,10 @@ qca8k_mdio_read(struct qca8k_priv *priv,
+
+ val &= QCA8K_MDIO_MASTER_DATA_MASK;
+
++ /* even if the busy_wait timeouts try to clear the MASTER_EN */
++ qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
++ QCA8K_MDIO_MASTER_EN);
++
+ return val;
+ }
+