generic: 6.1: backport qca8k fixes for big endian and MDIO
[openwrt/staging/blocktrron.git] / target / linux / generic / backport-6.1 / 781-v6.6-02-net-dsa-qca8k-fix-potential-MDIO-bus-conflict-when-a.patch
diff --git a/target/linux/generic/backport-6.1/781-v6.6-02-net-dsa-qca8k-fix-potential-MDIO-bus-conflict-when-a.patch b/target/linux/generic/backport-6.1/781-v6.6-02-net-dsa-qca8k-fix-potential-MDIO-bus-conflict-when-a.patch
new file mode 100644 (file)
index 0000000..fc573cc
--- /dev/null
@@ -0,0 +1,106 @@
+From 526c8ee04bdbd4d8d19a583b1f3b06700229a815 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+Date: Wed, 4 Oct 2023 11:19:04 +0200
+Subject: [PATCH 2/2] net: dsa: qca8k: fix potential MDIO bus conflict when
+ accessing internal PHYs via management frames
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Besides the QCA8337 switch the Turris 1.x device has on it's MDIO bus
+also Micron ethernet PHY (dedicated to the WAN port).
+
+We've been experiencing a strange behavior of the WAN ethernet
+interface, wherein the WAN PHY started timing out the MDIO accesses, for
+example when the interface was brought down and then back up.
+
+Bisecting led to commit 2cd548566384 ("net: dsa: qca8k: add support for
+phy read/write with mgmt Ethernet"), which added support to access the
+QCA8337 switch's internal PHYs via management ethernet frames.
+
+Connecting the MDIO bus pins onto an oscilloscope, I was able to see
+that the MDIO bus was active whenever a request to read/write an
+internal PHY register was done via an management ethernet frame.
+
+My theory is that when the switch core always communicates with the
+internal PHYs via the MDIO bus, even when externally we request the
+access via ethernet. This MDIO bus is the same one via which the switch
+and internal PHYs are accessible to the board, and the board may have
+other devices connected on this bus. An ASCII illustration may give more
+insight:
+
+           +---------+
+      +----|         |
+      |    | WAN PHY |
+      | +--|         |
+      | |  +---------+
+      | |
+      | |  +----------------------------------+
+      | |  | QCA8337                          |
+MDC   | |  |                        +-------+ |
+------o-+--|--------o------------o--|       | |
+MDIO    |  |        |            |  | PHY 1 |-|--to RJ45
+--------o--|---o----+---------o--+--|       | |
+           |   |    |         |  |  +-------+ |
+          | +-------------+  |  o--|       | |
+          | | MDIO MDC    |  |  |  | PHY 2 |-|--to RJ45
+eth1      | |             |  o--+--|       | |
+-----------|-|port0        |  |  |  +-------+ |
+           | |             |  |  o--|       | |
+          | | switch core |  |  |  | PHY 3 |-|--to RJ45
+           | +-------------+  o--+--|       | |
+          |                  |  |  +-------+ |
+          |                  |  o--|  ...  | |
+          +----------------------------------+
+
+When we send a request to read an internal PHY register via an ethernet
+management frame via eth1, the switch core receives the ethernet frame
+on port 0 and then communicates with the internal PHY via MDIO. At this
+time, other potential devices, such as the WAN PHY on Turris 1.x, cannot
+use the MDIO bus, since it may cause a bus conflict.
+
+Fix this issue by locking the MDIO bus even when we are accessing the
+PHY registers via ethernet management frames.
+
+Fixes: 2cd548566384 ("net: dsa: qca8k: add support for phy read/write with mgmt Ethernet")
+Signed-off-by: Marek BehĂșn <kabel@kernel.org>
+Reviewed-by: Christian Marangi <ansuelsmth@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/dsa/qca/qca8k-8xxx.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/net/dsa/qca/qca8k-8xxx.c
++++ b/drivers/net/dsa/qca/qca8k-8xxx.c
+@@ -665,6 +665,15 @@ qca8k_phy_eth_command(struct qca8k_priv
+               goto err_read_skb;
+       }
++      /* It seems that accessing the switch's internal PHYs via management
++       * packets still uses the MDIO bus within the switch internally, and
++       * these accesses can conflict with external MDIO accesses to other
++       * devices on the MDIO bus.
++       * We therefore need to lock the MDIO bus onto which the switch is
++       * connected.
++       */
++      mutex_lock(&priv->bus->mdio_lock);
++
+       /* Actually start the request:
+        * 1. Send mdio master packet
+        * 2. Busy Wait for mdio master command
+@@ -677,6 +686,7 @@ qca8k_phy_eth_command(struct qca8k_priv
+       mgmt_master = priv->mgmt_master;
+       if (!mgmt_master) {
+               mutex_unlock(&mgmt_eth_data->mutex);
++              mutex_unlock(&priv->bus->mdio_lock);
+               ret = -EINVAL;
+               goto err_mgmt_master;
+       }
+@@ -764,6 +774,7 @@ exit:
+                                   QCA8K_ETHERNET_TIMEOUT);
+       mutex_unlock(&mgmt_eth_data->mutex);
++      mutex_unlock(&priv->bus->mdio_lock);
+       return ret;