Skip to content
Snippets Groups Projects
0009-mvebu-turris-omnia-multi-cpu-dsa.patch 10.00 KiB
From 9e8821be8d387c40aa801e098821978da75722d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <marek.behun@nic.cz>
Date: Tue, 27 Aug 2019 19:56:07 +0200
Subject: [PATCH] mvebu: turris-omnia: multi cpu dsa
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Marek Behún <marek.behun@nic.cz>
---
 .../90500-net-dsa-multi-cpu.patch             | 253 ++++++++++++++++++
 .../90501-omnia-dts-dsa-multi-cpu.patch       |  58 ++++
 2 files changed, 311 insertions(+)
 create mode 100644 target/linux/mvebu/patches-4.14/90500-net-dsa-multi-cpu.patch
 create mode 100644 target/linux/mvebu/patches-4.14/90501-omnia-dts-dsa-multi-cpu.patch

diff --git a/target/linux/mvebu/patches-4.14/90500-net-dsa-multi-cpu.patch b/target/linux/mvebu/patches-4.14/90500-net-dsa-multi-cpu.patch
new file mode 100644
index 0000000..e51ee19
--- /dev/null
+++ b/target/linux/mvebu/patches-4.14/90500-net-dsa-multi-cpu.patch
@@ -0,0 +1,253 @@
+diff -Naurp a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+--- a/drivers/net/dsa/mv88e6xxx/chip.c	2019-08-22 10:27:11.763008277 +0200
++++ b/drivers/net/dsa/mv88e6xxx/chip.c	2019-08-27 19:27:30.435568033 +0200
+@@ -1087,6 +1087,7 @@ static u16 mv88e6xxx_port_vlan(struct mv
+ 	struct dsa_switch *ds = NULL;
+ 	struct net_device *br;
+ 	u16 pvlan;
++	u8 upstream;
+ 	int i;
+ 
+ 	if (dev < DSA_MAX_SWITCHES)
+@@ -1097,8 +1098,22 @@ static u16 mv88e6xxx_port_vlan(struct mv
+ 		return 0;
+ 
+ 	/* Frames from DSA links and CPU ports can egress any local port */
+-	if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
+-		return mv88e6xxx_port_mask(chip);
++	if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
++		u16 pmask = mv88e6xxx_port_mask(chip);
++		pvlan = 0;
++
++		for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
++			if (dsa_is_cpu_port(ds, i)) {
++				if (i == port)
++					pvlan |= BIT(i);
++				continue;
++			}
++			if ((pmask & BIT(i)) && dsa_port_upstream_port(chip->ds, i) == port)
++				pvlan |= BIT(i);
++		}
++
++		return pvlan;
++	}
+ 
+ 	br = ds->ports[port].bridge_dev;
+ 	pvlan = 0;
+@@ -1106,8 +1121,9 @@ static u16 mv88e6xxx_port_vlan(struct mv
+ 	/* Frames from user ports can egress any local DSA links and CPU ports,
+ 	 * as well as any local member of their bridge group.
+ 	 */
++	upstream = dsa_port_upstream_port(ds, port);
+ 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
+-		if (dsa_is_cpu_port(chip->ds, i) ||
++		if ((dsa_is_cpu_port(chip->ds, i) && i == upstream) ||
+ 		    dsa_is_dsa_port(chip->ds, i) ||
+ 		    (br && chip->ds->ports[i].bridge_dev == br))
+ 			pvlan |= BIT(i);
+@@ -1943,9 +1959,11 @@ static int mv88e6xxx_setup_message_port(
+ 
+ static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port)
+ {
+-	bool flood = port == dsa_upstream_port(chip->ds);
++	struct dsa_switch *ds = chip->ds;
++	bool flood;
+ 
+ 	/* Upstream ports flood frames with unknown unicast or multicast DA */
++	flood = dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port);
+ 	if (chip->info->ops->port_set_egress_floods)
+ 		return chip->info->ops->port_set_egress_floods(chip, port,
+ 							       flood, flood);
+diff -Naurp a/include/net/dsa.h b/include/net/dsa.h
+--- a/include/net/dsa.h	2019-08-22 10:27:11.723008277 +0200
++++ b/include/net/dsa.h	2019-08-27 15:56:37.053514380 +0200
+@@ -188,6 +188,10 @@ struct dsa_port {
+ 	struct net_device	*bridge_dev;
+ 	struct devlink_port	devlink_port;
+ 	struct phylink		*pl;
++
++	struct net_device	*ethernet;
++	int			upstream;
++
+ 	/*
+ 	 * Original copy of the master netdev ethtool_ops
+ 	 */
+@@ -269,6 +273,11 @@ static inline bool dsa_is_normal_port(st
+ 	return !dsa_is_cpu_port(ds, p) && !dsa_is_dsa_port(ds, p);
+ }
+ 
++static inline bool dsa_is_upstream_port(struct dsa_switch *ds, int p)
++{
++	return dsa_is_cpu_port(ds, p) || dsa_is_dsa_port(ds, p);
++}
++
+ static inline u8 dsa_upstream_port(struct dsa_switch *ds)
+ {
+ 	struct dsa_switch_tree *dst = ds->dst;
+@@ -285,6 +294,18 @@ static inline u8 dsa_upstream_port(struc
+ 		return ds->rtable[dst->cpu_dp->ds->index];
+ }
+ 
++static inline u8 dsa_port_upstream_port(struct dsa_switch *ds, int port)
++{
++	/*
++	 * If this port has a specific upstream cpu port, use it,
++	 * otherwise use the switch default.
++	 */
++	if (ds->ports[port].upstream)
++		return ds->ports[port].upstream;
++	else
++		return dsa_upstream_port(ds);
++}
++
+ typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
+ 			      bool is_static, void *data);
+ struct dsa_switch_ops {
+diff -Naurp a/net/dsa/dsa2.c b/net/dsa/dsa2.c
+--- a/net/dsa/dsa2.c	2019-08-09 17:53:37.000000000 +0200
++++ b/net/dsa/dsa2.c	2019-08-27 19:44:55.481541248 +0200
+@@ -253,6 +253,8 @@ static int dsa_cpu_port_apply(struct dsa
+ 	memset(&port->devlink_port, 0, sizeof(port->devlink_port));
+ 	err = devlink_port_register(ds->devlink, &port->devlink_port,
+ 				    port->index);
++	if (port->netdev)
++		port->netdev->dsa_ptr = ds->dst;
+ 	return err;
+ }
+ 
+@@ -262,6 +264,12 @@ static void dsa_cpu_port_unapply(struct
+ 	dsa_cpu_dsa_destroy(port);
+ 	port->ds->cpu_port_mask &= ~BIT(port->index);
+ 
++	if (port->netdev)
++		port->netdev->dsa_ptr = NULL;
++	if (port->ethernet) {
++		dev_put(port->ethernet);
++		port->ethernet = NULL;
++	}
+ }
+ 
+ static int dsa_user_port_apply(struct dsa_port *port)
+@@ -505,10 +513,9 @@ static int dsa_cpu_parse(struct dsa_port
+ 		dev_put(ethernet_dev);
+ 	}
+ 
+-	if (!dst->cpu_dp) {
++	if (!dst->cpu_dp)
+ 		dst->cpu_dp = port;
+-		dst->cpu_dp->netdev = ethernet_dev;
+-	}
++	port->netdev = ethernet_dev;
+ 
+ 	/* Initialize cpu_port_mask now for drv->setup()
+ 	 * to have access to a correct value, just like what
+@@ -526,6 +533,32 @@ static int dsa_cpu_parse(struct dsa_port
+ 
+ 	dst->rcv = dst->tag_ops->rcv;
+ 
++	dev_hold(ethernet_dev);
++	ds->ports[index].ethernet = ethernet_dev;
++	ds->cpu_port_mask |= BIT(index);
++
++	return 0;
++}
++
++static int dsa_user_parse(struct dsa_port *port, u32 index,
++			  struct dsa_switch *ds)
++{
++	struct device_node *cpu_port;
++	const unsigned int *cpu_port_reg;
++	int cpu_port_index;
++
++	cpu_port = of_parse_phandle(port->dn, "cpu", 0);
++	if (cpu_port) {
++		cpu_port_reg = of_get_property(cpu_port, "reg", NULL);
++		if (!cpu_port_reg)
++			return -EINVAL;
++		cpu_port_index = be32_to_cpup(cpu_port_reg);
++	} else {
++		cpu_port_index = ds->dst->cpu_dp->index;
++	}
++
++	ds->ports[index].upstream = cpu_port_index;
++
+ 	return 0;
+ }
+ 
+@@ -533,8 +566,9 @@ static int dsa_ds_parse(struct dsa_switc
+ {
+ 	struct dsa_port *port;
+ 	u32 index;
+-	int err;
++	int err = 0;
+ 
++	/* first parse only CPU ports */
+ 	for (index = 0; index < ds->num_ports; index++) {
+ 		port = &ds->ports[index];
+ 		if (!dsa_port_is_valid(port) ||
+@@ -545,7 +579,20 @@ static int dsa_ds_parse(struct dsa_switc
+ 			err = dsa_cpu_parse(port, index, dst, ds);
+ 			if (err)
+ 				return err;
+-		} else {
++		}
++	}
++
++	/* now parse normal ports */
++	for (index = 0; index < ds->num_ports; index++) {
++		port = &ds->ports[index];
++		if (!dsa_port_is_valid(port) ||
++		    dsa_port_is_dsa(port))
++			continue;
++
++		if (!dsa_port_is_cpu(port)) {
++			err = dsa_user_parse(port, index, ds);
++			if (err)
++				return err;
+ 			/* Initialize enabled_port_mask now for drv->setup()
+ 			 * to have access to a correct value, just like what
+ 			 * net/dsa/dsa.c::dsa_switch_setup_one does.
+diff -Naurp a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
+--- a/net/dsa/dsa_priv.h	2019-08-22 10:27:11.723008277 +0200
++++ b/net/dsa/dsa_priv.h	2019-08-27 15:57:31.323513820 +0200
+@@ -81,6 +81,8 @@ struct dsa_slave_priv {
+ 
+ 	/* TC context */
+ 	struct list_head	mall_tc_list;
++
++	struct net_device	*master;
+ };
+ 
+ /* dsa.c */
+@@ -167,7 +169,10 @@ extern const struct dsa_device_ops trail
+ 
+ static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
+ {
+-	return p->dp->cpu_dp->netdev;
++	if (p->master)
++		return p->master;
++	else
++		return p->dp->cpu_dp->netdev;
+ }
+ 
+ static inline struct dsa_port *dsa_get_cpu_port(struct dsa_switch_tree *dst)
+diff -Naurp a/net/dsa/slave.c b/net/dsa/slave.c
+--- a/net/dsa/slave.c	2019-08-22 10:27:11.723008277 +0200
++++ b/net/dsa/slave.c	2019-08-27 15:58:17.039789880 +0200
+@@ -1242,7 +1242,7 @@ int dsa_slave_create(struct dsa_port *po
+ 	int ret;
+ 
+ 	cpu_dp = ds->dst->cpu_dp;
+-	master = cpu_dp->netdev;
++	master = ds->ports[port->upstream].ethernet;
+ 
+ 	if (!ds->num_tx_queues)
+ 		ds->num_tx_queues = 1;
+@@ -1280,6 +1280,7 @@ int dsa_slave_create(struct dsa_port *po
+ 	p->dp = port;
+ 	INIT_LIST_HEAD(&p->mall_tc_list);
+ 	p->xmit = dst->tag_ops->xmit;
++	p->master = master;
+ 
+ 	port->netdev = slave_dev;
+ 
diff --git a/target/linux/mvebu/patches-4.14/90501-omnia-dts-dsa-multi-cpu.patch b/target/linux/mvebu/patches-4.14/90501-omnia-dts-dsa-multi-cpu.patch
new file mode 100644
index 0000000..07b6e12
--- /dev/null
+++ b/target/linux/mvebu/patches-4.14/90501-omnia-dts-dsa-multi-cpu.patch
@@ -0,0 +1,58 @@
+diff -Naurp a/arch/arm/boot/dts/armada-385-turris-omnia.dtsi b/arch/arm/boot/dts/armada-385-turris-omnia.dtsi
+--- a/arch/arm/boot/dts/armada-385-turris-omnia.dtsi	2019-08-22 10:27:11.626341612 +0200
++++ b/arch/arm/boot/dts/armada-385-turris-omnia.dtsi	2019-08-27 19:54:51.811729285 +0200
+@@ -369,29 +369,34 @@
+ 			ports@0 {
+ 				reg = <0>;
+ 				label = "lan0";
++				cpu = <&cpu_port5>;
+ 			};
+ 
+ 			ports@1 {
+ 				reg = <1>;
+ 				label = "lan1";
++				cpu = <&cpu_port5>;
+ 			};
+ 
+ 			ports@2 {
+ 				reg = <2>;
+ 				label = "lan2";
++				cpu = <&cpu_port5>;
+ 			};
+ 
+ 			ports@3 {
+ 				reg = <3>;
+ 				label = "lan3";
++				cpu = <&cpu_port5>;
+ 			};
+ 
+ 			ports@4 {
+ 				reg = <4>;
+ 				label = "lan4";
++				cpu = <&cpu_port6>;
+ 			};
+ 
+-			ports@5 {
++			cpu_port5: ports@5 {
+ 				reg = <5>;
+ 				label = "cpu";
+ 				ethernet = <&eth1>;
+@@ -403,7 +408,17 @@
+ 				};
+ 			};
+ 
+-			/* port 6 is connected to eth0 */
++			cpu_port6: ports@6 {
++				reg = <6>;
++				label = "cpu";
++				ethernet = <&eth0>;
++				phy-mode = "rgmii-id";
++
++				fixed-link {
++					speed = <1000>;
++					full-duplex;
++				};
++			};
+ 		};
+ 	};
+ };
-- 
2.21.0