]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blobdiff - queue-6.1/net-dsa-introduce-preferred_default_local_cpu_port-and-use-on-mt7530.patch
6.1-stable patches
[thirdparty/kernel/stable-queue.git] / queue-6.1 / net-dsa-introduce-preferred_default_local_cpu_port-and-use-on-mt7530.patch
diff --git a/queue-6.1/net-dsa-introduce-preferred_default_local_cpu_port-and-use-on-mt7530.patch b/queue-6.1/net-dsa-introduce-preferred_default_local_cpu_port-and-use-on-mt7530.patch
new file mode 100644 (file)
index 0000000..aac2eca
--- /dev/null
@@ -0,0 +1,171 @@
+From b79d7c14f48083abb3fb061370c0c64a569edf4c Mon Sep 17 00:00:00 2001
+From: Vladimir Oltean <olteanv@gmail.com>
+Date: Sat, 17 Jun 2023 09:26:48 +0300
+Subject: net: dsa: introduce preferred_default_local_cpu_port and use on MT7530
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Vladimir Oltean <olteanv@gmail.com>
+
+commit b79d7c14f48083abb3fb061370c0c64a569edf4c upstream.
+
+Since the introduction of the OF bindings, DSA has always had a policy that
+in case multiple CPU ports are present in the device tree, the numerically
+smallest one is always chosen.
+
+The MT7530 switch family, except the switch on the MT7988 SoC, has 2 CPU
+ports, 5 and 6, where port 6 is preferable on the MT7531BE switch because
+it has higher bandwidth.
+
+The MT7530 driver developers had 3 options:
+- to modify DSA when the MT7531 switch support was introduced, such as to
+  prefer the better port
+- to declare both CPU ports in device trees as CPU ports, and live with the
+  sub-optimal performance resulting from not preferring the better port
+- to declare just port 6 in the device tree as a CPU port
+
+Of course they chose the path of least resistance (3rd option), kicking the
+can down the road. The hardware description in the device tree is supposed
+to be stable - developers are not supposed to adopt the strategy of
+piecemeal hardware description, where the device tree is updated in
+lockstep with the features that the kernel currently supports.
+
+Now, as a result of the fact that they did that, any attempts to modify the
+device tree and describe both CPU ports as CPU ports would make DSA change
+its default selection from port 6 to 5, effectively resulting in a
+performance degradation visible to users with the MT7531BE switch as can be
+seen below.
+
+Without preferring port 6:
+
+[ ID][Role] Interval           Transfer     Bitrate         Retr
+[  5][TX-C]   0.00-20.00  sec   374 MBytes   157 Mbits/sec  734    sender
+[  5][TX-C]   0.00-20.00  sec   373 MBytes   156 Mbits/sec    receiver
+[  7][RX-C]   0.00-20.00  sec  1.81 GBytes   778 Mbits/sec    0    sender
+[  7][RX-C]   0.00-20.00  sec  1.81 GBytes   777 Mbits/sec    receiver
+
+With preferring port 6:
+
+[ ID][Role] Interval           Transfer     Bitrate         Retr
+[  5][TX-C]   0.00-20.00  sec  1.99 GBytes   856 Mbits/sec  273    sender
+[  5][TX-C]   0.00-20.00  sec  1.99 GBytes   855 Mbits/sec    receiver
+[  7][RX-C]   0.00-20.00  sec  1.72 GBytes   737 Mbits/sec   15    sender
+[  7][RX-C]   0.00-20.00  sec  1.71 GBytes   736 Mbits/sec    receiver
+
+Using one port for WAN and the other ports for LAN is a very popular use
+case which is what this test emulates.
+
+As such, this change proposes that we retroactively modify stable kernels
+(which don't support the modification of the CPU port assignments, so as to
+let user space fix the problem and restore the throughput) to keep the
+mt7530 driver preferring port 6 even with device trees where the hardware
+is more fully described.
+
+Fixes: c288575f7810 ("net: dsa: mt7530: Add the support of MT7531 switch")
+Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/dsa/mt7530.c |   15 +++++++++++++++
+ include/net/dsa.h        |    8 ++++++++
+ net/dsa/dsa2.c           |   24 +++++++++++++++++++++++-
+ 3 files changed, 46 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -419,6 +419,20 @@ static void mt7530_pll_setup(struct mt75
+       core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN);
+ }
++/* If port 6 is available as a CPU port, always prefer that as the default,
++ * otherwise don't care.
++ */
++static struct dsa_port *
++mt753x_preferred_default_local_cpu_port(struct dsa_switch *ds)
++{
++      struct dsa_port *cpu_dp = dsa_to_port(ds, 6);
++
++      if (dsa_port_is_cpu(cpu_dp))
++              return cpu_dp;
++
++      return NULL;
++}
++
+ /* Setup port 6 interface mode and TRGMII TX circuit */
+ static int
+ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
+@@ -3405,6 +3419,7 @@ static int mt753x_set_mac_eee(struct dsa
+ static const struct dsa_switch_ops mt7530_switch_ops = {
+       .get_tag_protocol       = mtk_get_tag_protocol,
+       .setup                  = mt753x_setup,
++      .preferred_default_local_cpu_port = mt753x_preferred_default_local_cpu_port,
+       .get_strings            = mt7530_get_strings,
+       .get_ethtool_stats      = mt7530_get_ethtool_stats,
+       .get_sset_count         = mt7530_get_sset_count,
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -969,6 +969,14 @@ struct dsa_switch_ops {
+       void    (*port_disable)(struct dsa_switch *ds, int port);
+       /*
++       * Compatibility between device trees defining multiple CPU ports and
++       * drivers which are not OK to use by default the numerically smallest
++       * CPU port of a switch for its local ports. This can return NULL,
++       * meaning "don't know/don't care".
++       */
++      struct dsa_port *(*preferred_default_local_cpu_port)(struct dsa_switch *ds);
++
++      /*
+        * Port's MAC EEE settings
+        */
+       int     (*set_mac_eee)(struct dsa_switch *ds, int port,
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -425,6 +425,24 @@ static int dsa_tree_setup_default_cpu(st
+       return 0;
+ }
++static struct dsa_port *
++dsa_switch_preferred_default_local_cpu_port(struct dsa_switch *ds)
++{
++      struct dsa_port *cpu_dp;
++
++      if (!ds->ops->preferred_default_local_cpu_port)
++              return NULL;
++
++      cpu_dp = ds->ops->preferred_default_local_cpu_port(ds);
++      if (!cpu_dp)
++              return NULL;
++
++      if (WARN_ON(!dsa_port_is_cpu(cpu_dp) || cpu_dp->ds != ds))
++              return NULL;
++
++      return cpu_dp;
++}
++
+ /* Perform initial assignment of CPU ports to user ports and DSA links in the
+  * fabric, giving preference to CPU ports local to each switch. Default to
+  * using the first CPU port in the switch tree if the port does not have a CPU
+@@ -432,12 +450,16 @@ static int dsa_tree_setup_default_cpu(st
+  */
+ static int dsa_tree_setup_cpu_ports(struct dsa_switch_tree *dst)
+ {
+-      struct dsa_port *cpu_dp, *dp;
++      struct dsa_port *preferred_cpu_dp, *cpu_dp, *dp;
+       list_for_each_entry(cpu_dp, &dst->ports, list) {
+               if (!dsa_port_is_cpu(cpu_dp))
+                       continue;
++              preferred_cpu_dp = dsa_switch_preferred_default_local_cpu_port(cpu_dp->ds);
++              if (preferred_cpu_dp && preferred_cpu_dp != cpu_dp)
++                      continue;
++
+               /* Prefer a local CPU port */
+               dsa_switch_for_each_port(dp, cpu_dp->ds) {
+                       /* Prefer the first local CPU port found */