From b16585dd95e738ab4500c4778c96b216be5fd883 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Thu, 29 Nov 2018 11:34:09 +0100 Subject: [PATCH 1/8] net: dsa: adding fields for holding information about upstream-port for multiple cpu-Ports aech port needs storing the the cpu-port to be used this Patch adds the needed fields for this based on https://github.com/openwrt/openwrt/blob/master/target/linux/mediatek/patches-4.14/0033-dsa-multi-cpu.patch Signed-off-by: Frank Wunderlich --- include/net/dsa.h | 4 ++++ net/dsa/dsa_priv.h | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/include/net/dsa.h b/include/net/dsa.h index 461e8a7661b78..6e0c95625a211 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -202,6 +202,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 */ diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 3964c6f7a7c0d..559a3a250c880 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -81,6 +81,8 @@ struct dsa_slave_priv { /* TC context */ struct list_head mall_tc_list; + + struct net_device *master; }; /* dsa.c */ @@ -187,7 +189,10 @@ static inline struct net_device * dsa_slave_to_master(const struct net_device *dev) { struct dsa_port *dp = dsa_slave_to_port(dev); + struct dsa_slave_priv *p = netdev_priv(dev); + if (p->master) + return p->master; return dp->cpu_dp->master; } From 9bc5728344269989932cdc57279aeb281e21fbce Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Thu, 29 Nov 2018 11:27:12 +0100 Subject: [PATCH 2/8] net: dsa: add helper functions for using mutliple cpu-Ports 3 additional functions are defined to read dts-option (dsa_user_parse) and check if current port is a upstream-port (dsa_port_upstream_port, dsa_is_upstream_port) based on https://github.com/openwrt/openwrt/blob/master/target/linux/mediatek/patches-4.14/0033-dsa-multi-cpu.patch Signed-off-by: Frank Wunderlich --- include/net/dsa.h | 18 ++++++++++++++++++ net/dsa/dsa2.c | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/net/dsa.h b/include/net/dsa.h index 6e0c95625a211..36db2ee83da62 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -318,6 +318,12 @@ static inline unsigned int dsa_towards_port(struct dsa_switch *ds, int device, return ds->rtable[device]; } + +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); +} + /* Return the local port used to reach the dedicated CPU port */ static inline unsigned int dsa_upstream_port(struct dsa_switch *ds, int port) { @@ -330,6 +336,18 @@ static inline unsigned int dsa_upstream_port(struct dsa_switch *ds, int port) return dsa_towards_port(ds, cpu_dp->ds->index, cpu_dp->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, port); +} + typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid, bool is_static, void *data); struct dsa_switch_ops { diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index a1917025e155b..b7c6da2f1f08a 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -255,6 +255,24 @@ static void dsa_tree_teardown_default_cpu(struct dsa_switch_tree *dst) dst->cpu_dp = NULL; } +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, "default_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); + ds->ports[index].upstream = cpu_port_index; + } + return 0; +} + static int dsa_port_setup(struct dsa_port *dp) { struct dsa_switch *ds = dp->ds; From 384f0e11fa2dc056a6f087589adbb3ddbfb7896e Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Thu, 29 Nov 2018 11:38:27 +0100 Subject: [PATCH 3/8] net: dsa: adding handling of second CPU-Port this patch adds the core-functionality of multiple cpu-ports currently it uses definition in dts to make connection between cpu and user-port based on https://github.com/openwrt/openwrt/blob/master/target/linux/mediatek/patches-4.14/0033-dsa-multi-cpu.patch Signed-off-by: Frank Wunderlich --- net/dsa/dsa2.c | 18 ++++++++++++++++++ net/dsa/slave.c | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index b7c6da2f1f08a..8f64535fd2a00 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -303,6 +303,8 @@ static int dsa_port_setup(struct dsa_port *dp) ds->index, dp->index); return err; } + if (dp->master) + dp->master->dsa_ptr = dp; break; case DSA_PORT_TYPE_DSA: /* dp->index is used now as port_number. However @@ -323,12 +325,17 @@ static int dsa_port_setup(struct dsa_port *dp) devlink_port_attrs_set(&dp->devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL, dp->index, false, 0); + err = dsa_user_parse(dp, dp->index, ds); + if (err) + return err; + err = dsa_slave_create(dp); if (err) dev_err(ds->dev, "failed to create slave for port %d.%d\n", ds->index, dp->index); else devlink_port_type_eth_set(&dp->devlink_port, dp->slave); + break; } @@ -344,6 +351,14 @@ static void dsa_port_teardown(struct dsa_port *dp) case DSA_PORT_TYPE_UNUSED: break; case DSA_PORT_TYPE_CPU: + dsa_port_link_unregister_of(dp); + if (dp->master) + dp->master->dsa_ptr = NULL; + if (dp->ethernet) { + dev_put(dp->ethernet); + dp->ethernet = NULL; + } + break; case DSA_PORT_TYPE_DSA: dsa_port_link_unregister_of(dp); break; @@ -598,6 +613,9 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master) dp->master = master; dp->dst = dst; + dev_hold(master); + ds->ports[dp->index].ethernet = master; + return 0; } diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 1c45c1d6d241d..3bdbd53d34202 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1291,11 +1291,11 @@ static void dsa_slave_notify(struct net_device *dev, unsigned long val) int dsa_slave_create(struct dsa_port *port) { const struct dsa_port *cpu_dp = port->cpu_dp; - struct net_device *master = cpu_dp->master; struct dsa_switch *ds = port->ds; const char *name = port->name; struct net_device *slave_dev; struct dsa_slave_priv *p; + struct net_device *master = ds->ports[port->upstream].ethernet; int ret; if (!ds->num_tx_queues) @@ -1334,6 +1334,7 @@ int dsa_slave_create(struct dsa_port *port) p->dp = port; INIT_LIST_HEAD(&p->mall_tc_list); p->xmit = cpu_dp->tag_ops->xmit; + p->master = master; port->slave = slave_dev; netif_carrier_off(slave_dev); From 0cbd2a5f884469891b5f593c16e86eb875e86261 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Sat, 8 Dec 2018 19:22:22 +0100 Subject: [PATCH 4/8] net: dsa: add support for GMAC2 wired to ext cpu-ports of mt7530 need some special flags to be set based on https://github.com/openwrt/openwrt/blob/master/target/linux/mediatek/patches-4.14/0032-net-dsa-mediatek-add-support-for-GMAC2-wired-to-ext-.patch Signed-off-by: Frank Wunderlich --- drivers/net/dsa/mt7530.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 62e486652e622..8ed0af6abe7dc 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -1281,6 +1281,11 @@ mt7530_setup(struct dsa_switch *ds) val = mt7530_read(priv, MT7530_MHWTRAP); val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; val |= MHWTRAP_MANUAL; + if (!dsa_is_cpu_port(ds, 5)) { + val |= MHWTRAP_P5_DIS; + val |= MHWTRAP_P5_MAC_SEL; + val |= MHWTRAP_P5_RGMII_MODE; + } mt7530_write(priv, MT7530_MHWTRAP, val); /* Enable and reset MIB counters */ From 92fb62e636aa94fe26fd7291fa937896e4796328 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Sat, 8 Dec 2018 19:25:57 +0100 Subject: [PATCH 5/8] net: dsa: dsa multi cpu (mt7530.c) implementing changes to mt7530 switch driver for supporting multiple (2) cpu-ports based on https://github.com/openwrt/openwrt/blob/master/target/linux/mediatek/patches-4.14/0033-dsa-multi-cpu.patch Signed-off-by: Frank Wunderlich --- drivers/net/dsa/mt7530.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 8ed0af6abe7dc..fda1b67dfeac9 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -678,6 +678,9 @@ static int mt7530_cpu_port_enable(struct mt7530_priv *priv, int port) { + u8 port_mask = 0; + int i; + /* Enable Mediatek header mode on the cpu port */ mt7530_write(priv, MT7530_PVC_P(port), PORT_SPEC_TAG); @@ -694,8 +697,14 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv, /* CPU port gets connected to all user ports of * the switch */ + + for (i = 0; i < MT7530_NUM_PORTS; i++) + if ((priv->ds->ports[port].type == DSA_PORT_TYPE_USER) && + (dsa_port_upstream_port(priv->ds, i) == port)) + port_mask |= BIT(i); + mt7530_write(priv, MT7530_PCR_P(port), - PCR_MATRIX(dsa_user_ports(priv->ds))); + PCR_MATRIX(port_mask)); return 0; } @@ -705,6 +714,7 @@ mt7530_port_enable(struct dsa_switch *ds, int port, struct phy_device *phy) { struct mt7530_priv *priv = ds->priv; + u8 upstream = dsa_port_upstream_port(ds, port); mutex_lock(&priv->reg_mutex); @@ -715,7 +725,7 @@ mt7530_port_enable(struct dsa_switch *ds, int port, * restore the port matrix if the port is the member of a certain * bridge. */ - priv->ports[port].pm |= PCR_MATRIX(BIT(MT7530_CPU_PORT)); + priv->ports[port].pm |= PCR_MATRIX(BIT(upstream)); priv->ports[port].enable = true; mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, priv->ports[port].pm); @@ -778,7 +788,8 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *bridge) { struct mt7530_priv *priv = ds->priv; - u32 port_bitmap = BIT(MT7530_CPU_PORT); + u8 upstream = dsa_port_upstream_port(ds, port); + u32 port_bitmap = BIT(upstream); int i; mutex_lock(&priv->reg_mutex); @@ -879,6 +890,7 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *bridge) { struct mt7530_priv *priv = ds->priv; + u8 upstream = dsa_port_upstream_port(ds, port); int i; mutex_lock(&priv->reg_mutex); @@ -906,8 +918,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port, */ if (priv->ports[port].enable) mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, - PCR_MATRIX(BIT(MT7530_CPU_PORT))); - priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT)); + PCR_MATRIX(BIT(upstream))); + priv->ports[port].pm = PCR_MATRIX(BIT(upstream)); mt7530_port_set_vlan_unaware(ds, port); @@ -1198,15 +1210,7 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port, static enum dsa_tag_protocol mtk_get_tag_protocol(struct dsa_switch *ds, int port) { - struct mt7530_priv *priv = ds->priv; - - if (port != MT7530_CPU_PORT) { - dev_warn(priv->dev, - "port not matched with tagging CPU port\n"); - return DSA_TAG_PROTO_NONE; - } else { - return DSA_TAG_PROTO_MTK; - } + return DSA_TAG_PROTO_MTK; } static int @@ -1279,7 +1283,7 @@ mt7530_setup(struct dsa_switch *ds) /* Enable Port 6 only; P5 as GMAC5 which currently is not supported */ val = mt7530_read(priv, MT7530_MHWTRAP); - val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; + val &= ~MHWTRAP_P5_DIS & ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; val |= MHWTRAP_MANUAL; if (!dsa_is_cpu_port(ds, 5)) { val |= MHWTRAP_P5_DIS; From 807d2e2864c18834651191537562b1053ab6b599 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Sat, 8 Dec 2018 20:59:09 +0100 Subject: [PATCH 6/8] net: dsa: tell GDMA when we are turning on the special tag Enabling this bit will make the RX DMA descriptor enable the SP bit for all ingress traffic inside the return descriptor. The PPE needs this to know that a SP is present. based on https://github.com/openwrt/openwrt/blob/master/target/linux/mediatek/patches-4.14/0044-net-next-dsa-mediatek-tell-GDMA-when-we-are-turning-.patch Signed-off-by: Frank Wunderlich --- drivers/net/dsa/mt7530.c | 6 ++++++ drivers/net/dsa/mt7530.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index fda1b67dfeac9..9690a9b59fce5 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -685,6 +685,12 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv, mt7530_write(priv, MT7530_PVC_P(port), PORT_SPEC_TAG); + /* Enable Mediatek header mode on the GMAC that the cpu port + * connects to + */ + regmap_write_bits(priv->ethernet, MTK_GDMA_FWD_CFG(port), + GDMA_SPEC_TAG, GDMA_SPEC_TAG); + /* Setup the MAC by default for the cpu port */ mt7530_write(priv, MT7530_PMCR_P(port), PMCR_CPUP_LINK); diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h index d9b407a22a584..310f2536175b0 100644 --- a/drivers/net/dsa/mt7530.h +++ b/drivers/net/dsa/mt7530.h @@ -23,6 +23,10 @@ #define TRGMII_BASE(x) (0x10000 + (x)) +/* Registers for GDMA configuration access */ +#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000)) +#define GDMA_SPEC_TAG BIT(24) + /* Registers to ethsys access */ #define ETHSYS_CLKCFG0 0x2c #define ETHSYS_TRGMII_CLK_SEL362_5 BIT(11) From bec789d7e739b7ed5ff9ce84d331c1b0e6a2ec8b Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Sat, 8 Dec 2018 20:59:40 +0100 Subject: [PATCH 7/8] net: dsa: mt7530 add linking to mdio switch (7530) needs to to be linked to mdio-bus based on https://github.com/openwrt/openwrt/blob/master/target/linux/mediatek/patches-4.14/0045-net-dsa-mediatek-turn-into-platform-driver.patch Signed-off-by: Frank Wunderlich --- drivers/net/dsa/mt7530.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 9690a9b59fce5..8f95e22a33f65 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -1349,7 +1349,7 @@ static int mt7530_probe(struct mdio_device *mdiodev) { struct mt7530_priv *priv; - struct device_node *dn; + struct device_node *dn, *mdio; dn = mdiodev->dev.of_node; @@ -1396,8 +1396,14 @@ mt7530_probe(struct mdio_device *mdiodev) return PTR_ERR(priv->reset); } } + mdio = of_get_parent(dn); + if (!mdio) + return -EINVAL; + + priv->bus = of_mdio_find_bus(mdio); + if (!priv->bus) + return -EPROBE_DEFER; - priv->bus = mdiodev->bus; priv->dev = &mdiodev->dev; priv->ds->priv = priv; priv->ds->ops = &mt7530_switch_ops; From d973a238e7775f669c3f698adb6eef9ed682e72e Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Thu, 29 Nov 2018 10:53:44 +0100 Subject: [PATCH 8/8] net: dsa: changes to dts --- arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts index 465fb887b2ca6..0e797be0396d3 100644 --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts @@ -155,6 +155,18 @@ }; }; + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "trgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + pause; + }; + }; + mdio: mdio-bus { #address-cells = <1>; #size-cells = <0>; @@ -173,29 +185,44 @@ port@0 { reg = <0>; label = "wan"; + default_cpu = <&cpu_port1>; }; port@1 { reg = <1>; label = "lan0"; + default_cpu = <&cpu_port0>; }; port@2 { reg = <2>; label = "lan1"; + default_cpu = <&cpu_port0>; }; port@3 { reg = <3>; label = "lan2"; + default_cpu = <&cpu_port0>; }; port@4 { reg = <4>; label = "lan3"; + default_cpu = <&cpu_port0>; }; - port@6 { + cpu_port1: port@5 { + reg = <5>; + label = "cpu"; + ethernet = <&gmac1>; + phy-mode = "trgmii"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + cpu_port0: port@6 { reg = <6>; label = "cpu"; ethernet = <&gmac0>;