From 28a134f5a0553110c623c31ceb653a21fbe92be7 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 24 Feb 2020 14:15:33 +0200 Subject: net: dsa: felix: Use PHY_INTERFACE_MODE_INTERNAL instead of GMII phy-mode = "gmii" is confusing because it may mean that the port supports the 8-bit-wide parallel data interface pinout, which it doesn't. It may also be confusing because one of the "gmii" internal ports is actually overclocked to run at 2.5Gbps (even though, yes, as far as the switch MAC is concerned, it still thinks it's gigabit). So use the phy-mode = "internal" property to describe the internal ports inside the NXP LS1028A chip (the ones facing the ENETC). The change should be fine, because the device tree bindings document is yet to be introduced, and there are no stable DT blobs in use. Signed-off-by: Vladimir Oltean Reviewed-by: Andrew Lunn Tested-by: Michael Walle Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net/dsa/ocelot/felix.c') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 3257962c147e..35124ef7e75b 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -176,8 +176,7 @@ static void felix_phylink_validate(struct dsa_switch *ds, int port, phylink_set(mask, 100baseT_Full); phylink_set(mask, 1000baseT_Full); - /* The internal ports that run at 2.5G are overclocked GMII */ - if (state->interface == PHY_INTERFACE_MODE_GMII || + if (state->interface == PHY_INTERFACE_MODE_INTERNAL || state->interface == PHY_INTERFACE_MODE_2500BASEX || state->interface == PHY_INTERFACE_MODE_USXGMII) { phylink_set(mask, 2500baseT_Full); -- cgit From 5b502a7b2992008a1fd5962ba032771b03c4e840 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 26 Feb 2020 10:23:46 +0000 Subject: net: dsa: propagate resolved link config via mac_link_up() Propagate the resolved link configuration down via DSA's phylink_mac_link_up() operation to allow split PCS/MAC to work. Tested-by: Vladimir Oltean Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net/dsa/ocelot/felix.c') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 35124ef7e75b..7e66821b05b4 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -263,7 +263,9 @@ static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port, static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int link_an_mode, phy_interface_t interface, - struct phy_device *phydev) + struct phy_device *phydev, + int speed, int duplex, + bool tx_pause, bool rx_pause) { struct ocelot *ocelot = ds->priv; struct ocelot_port *ocelot_port = ocelot->ports[port]; -- cgit From 07d985eef07348345870f1062797852cb4489b83 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 29 Feb 2020 16:31:14 +0200 Subject: net: dsa: felix: Wire up the ocelot cls_flower methods Export the cls_flower methods from the ocelot driver and hook them up to the DSA passthrough layer. Tables for the VCAP IS2 parameters, as well as half key packing (field offsets and lengths) need to be defined for the VSC9959 core, as they are different from Ocelot, mainly due to the different port count. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers/net/dsa/ocelot/felix.c') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 7e66821b05b4..c0acd7dc7f48 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -2,6 +2,7 @@ /* Copyright 2019 NXP Semiconductors */ #include +#include #include #include #include @@ -401,6 +402,9 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) ocelot->stats_layout = felix->info->stats_layout; ocelot->num_stats = felix->info->num_stats; ocelot->shared_queue_sz = felix->info->shared_queue_sz; + ocelot->vcap_is2_keys = felix->info->vcap_is2_keys; + ocelot->vcap_is2_actions= felix->info->vcap_is2_actions; + ocelot->vcap = felix->info->vcap; ocelot->ops = felix->info->ops; port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t), @@ -595,6 +599,30 @@ static bool felix_txtstamp(struct dsa_switch *ds, int port, return false; } +static int felix_cls_flower_add(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress) +{ + struct ocelot *ocelot = ds->priv; + + return ocelot_cls_flower_replace(ocelot, port, cls, ingress); +} + +static int felix_cls_flower_del(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress) +{ + struct ocelot *ocelot = ds->priv; + + return ocelot_cls_flower_destroy(ocelot, port, cls, ingress); +} + +static int felix_cls_flower_stats(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress) +{ + struct ocelot *ocelot = ds->priv; + + return ocelot_cls_flower_stats(ocelot, port, cls, ingress); +} + static const struct dsa_switch_ops felix_switch_ops = { .get_tag_protocol = felix_get_tag_protocol, .setup = felix_setup, @@ -626,6 +654,9 @@ static const struct dsa_switch_ops felix_switch_ops = { .port_hwtstamp_set = felix_hwtstamp_set, .port_rxtstamp = felix_rxtstamp, .port_txtstamp = felix_txtstamp, + .cls_flower_add = felix_cls_flower_add, + .cls_flower_del = felix_cls_flower_del, + .cls_flower_stats = felix_cls_flower_stats, }; static struct felix_info *felix_instance_tbl[] = { -- cgit From 69df578c5f4b1f9d9b649e5fb06b5d337c25d27f Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 29 Feb 2020 16:50:02 +0200 Subject: net: mscc: ocelot: eliminate confusion between CPU and NPI port Ocelot has the concept of a CPU port. The CPU port is represented in the forwarding and the queueing system, but it is not a physical device. The CPU port can either be accessed via register-based injection/extraction (which is the case of Ocelot), via Frame-DMA (similar to the first one), or "connected" to a physical Ethernet port (called NPI in the datasheet) which is the case of the Felix DSA switch. In Ocelot the CPU port is at index 11. In Felix the CPU port is at index 6. The CPU bit is treated special in the forwarding, as it is never cleared from the forwarding port mask (once added to it). Other than that, it is treated the same as a normal front port. Both Felix and Ocelot should use the CPU port in the same way. This means that Felix should not use the NPI port directly when forwarding to the CPU, but instead use the CPU port. This patch is fixing this such that Felix will use port 6 as its CPU port, and just use the NPI port to carry the traffic. Therefore, eliminate the "ocelot->cpu" variable which was holding the index of the NPI port for Felix, and the index of the CPU port module for Ocelot, so the variable was actually configuring different things for different drivers and causing at least part of the confusion. Also remove the "ocelot->num_cpu_ports" variable, which is the result of another confusion. The 2 CPU ports mentioned in the datasheet are because there are two frame extraction channels (register based or DMA based). This is of no relevance to the driver at the moment, and invisible to the analyzer module. Signed-off-by: Vladimir Oltean Suggested-by: Allan W. Nielsen Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net/dsa/ocelot/felix.c') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index c0acd7dc7f48..3e87ac6c07e6 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -516,10 +516,11 @@ static int felix_setup(struct dsa_switch *ds) for (port = 0; port < ds->num_ports; port++) { ocelot_init_port(ocelot, port); + /* Bring up the CPU port module and configure the NPI port */ if (dsa_is_cpu_port(ds, port)) - ocelot_set_cpu_port(ocelot, port, - OCELOT_TAG_PREFIX_NONE, - OCELOT_TAG_PREFIX_LONG); + ocelot_configure_cpu(ocelot, port, + OCELOT_TAG_PREFIX_NONE, + OCELOT_TAG_PREFIX_LONG); } /* It looks like the MAC/PCS interrupt register - PM0_IEVENT (0x8040) -- cgit From 1cf3299b038b9083cb62012d6050ac565d277f59 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 29 Feb 2020 16:50:03 +0200 Subject: net: dsa: felix: Allow unknown unicast traffic towards the CPU port module Compared to other DSA switches, in the Ocelot cores, the RX filtering is a much more important concern. Firstly, the primary use case for Ocelot is non-DSA, so there isn't any secondary Ethernet MAC [the DSA master's one] to implicitly drop frames having a DMAC we are not interested in. So the switch driver itself needs to install FDB entries towards the CPU port module (PGID_CPU) for the MAC address of each switch port, in each VLAN installed on the port. Every address that is not whitelisted is implicitly dropped. This is in order to achieve a behavior similar to N standalone net devices. Secondly, even in the secondary use case of DSA, such as illustrated by Felix with the NPI port mode, that secondary Ethernet MAC is present, but its RX filter is bypassed. This is because the DSA tags themselves are placed before Ethernet, so the DMAC that the switch ports see is not seen by the DSA master too (since it's shifter to the right). So RX filtering is pretty important. A good RX filter won't bother the CPU in case the switch port receives a frame that it's not interested in, and there exists no other line of defense. Ocelot is pretty strict when it comes to RX filtering: non-IP multicast and broadcast traffic is allowed to go to the CPU port module, but unknown unicast isn't. This means that traffic reception for any other MAC addresses than the ones configured on each switch port net device won't work. This includes use cases such as macvlan or bridging with a non-Ocelot (so-called "foreign") interface. But this seems to be fine for the scenarios that the Linux system embedded inside an Ocelot switch is intended for - it is simply not interested in unknown unicast traffic, as explained in Allan Nielsen's presentation [0]. On the other hand, the Felix DSA switch is integrated in more general-purpose Linux systems, so it can't afford to drop that sort of traffic in hardware, even if it will end up doing so later, in software. Actually, unknown unicast means more for Felix than it does for Ocelot. Felix doesn't attempt to perform the whitelisting of switch port MAC addresses towards PGID_CPU at all, mainly because it is too complicated to be feasible: while the MAC addresses are unique in Ocelot, by default in DSA all ports are equal and inherited from the DSA master. This adds into account the question of reference counting MAC addresses (delayed ocelot_mact_forget), not to mention reference counting for the VLAN IDs that those MAC addresses are installed in. This reference counting should be done in the DSA core, and the fact that it wasn't needed so far is due to the fact that the other DSA switches don't have the DSA tag placed before Ethernet, so the DSA master is able to whitelist the MAC addresses in hardware. So this means that even regular traffic termination on a Felix switch port happens through flooding (because neither Felix nor Ocelot learn source MAC addresses from CPU-injected frames). So far we've explained that whitelisting towards PGID_CPU: - helps to reduce the likelihood of spamming the CPU with frames it won't process very far anyway - is implemented in the ocelot driver - is sufficient for the ocelot use cases - is not feasible in DSA - breaks use cases in DSA, in the current status (whitelisting enabled but no MAC address whitelisted) So the proposed patch allows unknown unicast frames to be sent to the CPU port module. This is done for the Felix DSA driver only, as Ocelot seems to be happy without it. [0]: https://www.youtube.com/watch?v=B1HhxEcU7Jg Suggested-by: Allan W. Nielsen Signed-off-by: Vladimir Oltean Reviewed-by: Allan W. Nielsen Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/net/dsa/ocelot/felix.c') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 3e87ac6c07e6..69546383a382 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -523,6 +523,15 @@ static int felix_setup(struct dsa_switch *ds) OCELOT_TAG_PREFIX_LONG); } + /* Include the CPU port module in the forwarding mask for unknown + * unicast - the hardware default value for ANA_FLOODING_FLD_UNICAST + * excludes BIT(ocelot->num_phys_ports), and so does ocelot_init, since + * Ocelot relies on whitelisting MAC addresses towards PGID_CPU. + */ + ocelot_write_rix(ocelot, + ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)), + ANA_PGID_PGID, PGID_UC); + /* It looks like the MAC/PCS interrupt register - PM0_IEVENT (0x8040) * isn't instantiated for the Felix PF. * In-band AN may take a few ms to complete, so we need to poll. -- cgit From 0b912fc93a680ab6105a63c36222923fbe09065e Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 27 Mar 2020 21:55:47 +0200 Subject: net: dsa: felix: support changing the MTU Changing the MTU for this switch means altering the DEV_GMII:MAC_CFG_STATUS:MAC_MAXLEN_CFG field MAX_LEN, which in turn limits the size of frames that can be received. Special accounting needs to be done for the DSA CPU port (NPI port in hardware terms). The NPI port configuration needs to be held inside the private ocelot structure, since it is now accessed from multiple places. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/net/dsa/ocelot/felix.c') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 69546383a382..e2effeaa685e 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -532,6 +532,7 @@ static int felix_setup(struct dsa_switch *ds) ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)), ANA_PGID_PGID, PGID_UC); + ds->mtu_enforcement_ingress = true; /* It looks like the MAC/PCS interrupt register - PM0_IEVENT (0x8040) * isn't instantiated for the Felix PF. * In-band AN may take a few ms to complete, so we need to poll. @@ -609,6 +610,22 @@ static bool felix_txtstamp(struct dsa_switch *ds, int port, return false; } +static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu) +{ + struct ocelot *ocelot = ds->priv; + + ocelot_port_set_maxlen(ocelot, port, new_mtu); + + return 0; +} + +static int felix_get_max_mtu(struct dsa_switch *ds, int port) +{ + struct ocelot *ocelot = ds->priv; + + return ocelot_get_max_mtu(ocelot, port); +} + static int felix_cls_flower_add(struct dsa_switch *ds, int port, struct flow_cls_offload *cls, bool ingress) { @@ -664,6 +681,8 @@ static const struct dsa_switch_ops felix_switch_ops = { .port_hwtstamp_set = felix_hwtstamp_set, .port_rxtstamp = felix_rxtstamp, .port_txtstamp = felix_txtstamp, + .port_change_mtu = felix_change_mtu, + .port_max_mtu = felix_get_max_mtu, .cls_flower_add = felix_cls_flower_add, .cls_flower_del = felix_cls_flower_del, .cls_flower_stats = felix_cls_flower_stats, -- cgit From fc411eaac8db7bd2cf3d9b67fd4b5651345a2cef Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 29 Mar 2020 14:52:00 +0300 Subject: net: dsa: felix: add port policers This patch is a trivial passthrough towards the ocelot library, which support port policers since commit 2c1d029a017f ("net: mscc: ocelot: Implement port policers via tc command"). Some data structure conversion between the DSA core and the Ocelot library is necessary, for policer parameters. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/net/dsa/ocelot/felix.c') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index e2effeaa685e..79ca3aadb864 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "felix.h" @@ -650,6 +651,27 @@ static int felix_cls_flower_stats(struct dsa_switch *ds, int port, return ocelot_cls_flower_stats(ocelot, port, cls, ingress); } +static int felix_port_policer_add(struct dsa_switch *ds, int port, + struct dsa_mall_policer_tc_entry *policer) +{ + struct ocelot *ocelot = ds->priv; + struct ocelot_policer pol = { + .rate = div_u64(policer->rate_bytes_per_sec, 1000) * 8, + .burst = div_u64(policer->rate_bytes_per_sec * + PSCHED_NS2TICKS(policer->burst), + PSCHED_TICKS_PER_SEC), + }; + + return ocelot_port_policer_add(ocelot, port, &pol); +} + +static void felix_port_policer_del(struct dsa_switch *ds, int port) +{ + struct ocelot *ocelot = ds->priv; + + ocelot_port_policer_del(ocelot, port); +} + static const struct dsa_switch_ops felix_switch_ops = { .get_tag_protocol = felix_get_tag_protocol, .setup = felix_setup, @@ -683,6 +705,8 @@ static const struct dsa_switch_ops felix_switch_ops = { .port_txtstamp = felix_txtstamp, .port_change_mtu = felix_change_mtu, .port_max_mtu = felix_get_max_mtu, + .port_policer_add = felix_port_policer_add, + .port_policer_del = felix_port_policer_del, .cls_flower_add = felix_cls_flower_add, .cls_flower_del = felix_cls_flower_del, .cls_flower_stats = felix_cls_flower_stats, -- cgit