commit 79267ae226 upstream.
The blamed commit was too aggressive, and it made ocelot_netdevice_event
react only to network interface events emitted for the ocelot switch
ports.
In fact, only the PRECHANGEUPPER should have had that check.
When we ignore all events that are not for us, we miss the fact that the
upper of the LAG changes, and the bonding interface gets enslaved to a
bridge. This is an operation we could offload under certain conditions.
Fixes: 7afb3e575e ("net: mscc: ocelot: don't handle netdev events for other netdevs")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20210118135210.2666246-1-olteanv@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Switch cpu port doesn't learn MAC addresses and the local bridge dev_addr
must be explicitly added to the bridge.
This is done whenever a port is added to a bridge, ports following the
1st one will just overwrite the same entry.
Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
(cherry picked from commit 9330e20682ce0bfad00c5ad72d1f10004bc824e9)
The Ocelot switchdev driver and the Felix DSA one need it for different
reasons. Felix (or at least the VSC9959 instantiation in NXP LS1028A) is
integrated with the traditional NXP Layerscape PCS design which does not
support runtime configuration of SerDes protocol. So it needs to
pre-validate the phy-mode from the device tree and prevent PHYLINK from
attempting to change it. For this, it needs to cache it in a private
variable.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
(cherry picked from commit 3076e319e82100cbb2eef6f2e4086ba802935aa0)
This reverts commit f3ebad1269.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
(cherry picked from commit 7a7928a5246b0bd1c44c6a015d8925fb576020ac)
This reverts commit e51cc023c3.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
(cherry picked from commit 2f4ee70a6f7b4fb56aae5d782955217a5c0dc5a9)
This reverts commit 423c8b0400.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
(cherry picked from commit 0b21bb2374f393db12851e974b681fbc572d862c)
The Ocelot switches have what is, in my opinion, a design flaw: their
DSA header is in front of the Ethernet header, which means that they
subvert the DSA master's RX filter, which for all practical purposes,
either needs to be in promiscuous mode, or the OCELOT_TAG_PREFIX_LONG
needs to be used for extraction, which makes the switch add a fake DMAC
of ff:ff:ff:ff:ff:ff so that the DSA master accepts the frame.
The issue with this design, of course, is that the CPU will be spammed
with frames that it doesn't want to respond to, and there isn't any
hardware offload in place by default to drop them.
What is being done in the VSC7514 Ocelot driver is a process of
selective whitelisting. The "MAC address" of each Ocelot switch net
device, with all VLANs installed on that port, is being added as a FDB
entry towards PGID_CPU.
Some background first: Port Group IDs (PGIDs) are masks of destination
ports. The switch performs 3 lookups in the PGID table for each frame,
and forwards the frame to the ports that are present in the logical AND
of all 3 PGIDs (for the most part, see below).
The first PGID lookup is for the destination masks and the PGID table is
indexed by the DEST_IDX field from the MAC table (FDB).
The PGID can be an unicast set: PGIDs 0-11 are the per-port PGIDs, and
by convention PGID i has only BIT(i) set, aka only this port is set in
the destination mask.
Or the PGID can be a multicast set: PGIDs 12-63 can (again, still by
convention) hold a richer destination mask comprised of multiple ports.
[ Ignoring the second PGID lookup, for aggregation, since it doesn't
interfere. ]
The third PGID lookup is for source masks: PGID entries 80-91 answer the
question: is port i allowed to forward traffic to port j? If yes, then
BIT(j) of PGID 80+i will be found set.
What is interesting about the CPU port in this whole story is that, in
the way the driver sets up the PGIDs, its bit isn't set in any source
mask PGID of any other port (therefore, the third lookup would always
decide to exclude the CPU port from this list). So frames are never
_forwarded_ to the CPU.
There is a loophole in this PGID mechanism which is described in the
VSC7514 manual:
If an entry is found in the MAC table entry of ENTRY_TYPE 0 or 1
and the CPU port is set in the PGID pointed to by the MAC table
entry, CPU extraction queue PGID.DST_PGID is added to the CPUQ.
In other words, the CPU port is special, and frames are "copied" to the
CPU, disregarding the source masks (third PGID lookup), if BIT(cpu) is
found to be set in the destination masks (first PGID lookup).
Now back to the story: what is PGID_CPU? It is a multicast set
containing only BIT(cpu). I don't know why it was chosen to be a
multicast PGID (59) and not simply the unicast one of this port, but it
doesn't matter.
The point is that frames that match the FDB will go to PGID_CPU by
virtue of the DEST_IDX from the respective MAC table entry, and frames
that don't will go to PGID_UC or PGID_MC, by virtue of the FLD_UNICAST,
FLD_BROADCAST etc settings for flooding. And that is where the
distinction is made: flooded frames will be subject to the third PGID
lookup, while frames that are whitelisted to the PGID_CPU by the MAC
table aren't.
So we can use this mechanism to simulate an RX filter, given that we are
subverting the DSA master's implicit one, as mentioned in the first
paragraph. But this has some limitations:
- In Ocelot each net device has its own MAC address. When simulating
this with MAC table entries, it will practically result in having N
MAC addresses for each of the N front-panel ports (because FDB entries
are not per source port). A bit strange, I think.
- In DSA we don't have the infrastructure in place to support this
whitelisting mechanism. Calling .port_fdb_add on the CPU port for each
slave net device dev_addr isn't, in itself, hard. The problem is with
the VLANs that this port is part of. We would need to keep a duplicate
list of the VLANs from the bridge, plus the ones added from 8021q, for
each port. And we would need reference counting on each MAC address,
such that when a front-panel port changes its MAC address and we need
to delete the old FDB entry, we don't actually delete it if the other
front-panel ports are still using it. Not to mention that this FDB
entry would have to be added on the whole net of upstream DSA switches.
So... it's complicated. What this patch does is to simply allow frames
to be flooded to the CPU, which is anyway what the Ocelot driver is
doing after removing the bridge from the net devices, see this snippet
from ocelot_bridge_stp_state_set:
/* Apply FWD mask. The loop is needed to add/remove the current port as
* a source for the other ports.
*/
for (p = 0; p < ocelot->num_phys_ports; p++) {
if (p == ocelot->cpu || (ocelot->bridge_fwd_mask & BIT(p))) {
(...)
} else {
/* Only the CPU port, this is compatible with link
* aggregation.
*/
ocelot_write_rix(ocelot,
BIT(ocelot->cpu),
ANA_PGID_PGID, PGID_SRC + p);
}
Otherwise said, the ocelot driver itself is already not self-coherent,
since immediately after probe time, and immediately after removal from a
bridge, it behaves in different ways, although the front panel ports are
standalone in both cases.
While standalone traffic _does_ work for the Felix DSA wrapper after
enslaving and removing the ports from a bridge, this patch makes
standalone traffic work at probe time too, with the caveat that even
irrelevant frames will get processed by software, making it more
susceptible to denial of service.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
(cherry picked from commit 8a4c7e0e0545d1f37c559926b1c85f3b7e6bc9b1)
The reason for doing this is that the 2 mainline Ocelot switches so far,
VSC7514 and VSC9959, have radically different SoC/SerDes integration. So
although the PHYLINK callbacks are common, the implementations will
actually lie in device-specific function pointers.
Also, there was a duplicated and unused function pointer for pcs_init in
struct ocelot, remove that.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
This patch reworks ocelot_board.c (aka the MIPS on the VSC7514) to
register a PHYLINK instance for each port. The registration code is
local to the VSC7514, but the PHYLINK callback implementation is common
so that the Felix DSA front-end can use it as well (but DSA does its own
registration).
Now Felix can use native PHYLINK callbacks instead of the PHYLIB
adaptation layer in DSA, which had issues supporting fixed-link slave
ports (no struct phy_device to pass to the adjust_link callback), as
well as fixed-link CPU port at 2.5Gbps.
The old code from ocelot_port_enable and ocelot_port_disable has been
moved into ocelot_phylink_mac_link_up and ocelot_phylink_mac_link_down.
The PHY connect operation has been moved from ocelot_port_open to
mscc_ocelot_probe in ocelot_board.c.
The phy_set_mode_ext() call for the SerDes PHY has also been moved into
mscc_ocelot_probe from ocelot_port_open, and since that was the only
reason why a reference to it was kept in ocelot_port_private, that
reference was removed.
Again, the usage of phy_interface_t phy_mode is now local to
mscc_ocelot_probe only, after moving the PHY connect operation.
So it was also removed from ocelot_port_private.
*Maybe* in the future, it can be added back to the common struct
ocelot_port, with the purpose of validating mismatches between
state->phy_interface and ocelot_port->phy_mode in PHYLINK callbacks.
But at the moment that is not critical, since other DSA drivers are not
doing that either. No SFP+ modules are in use with Felix/Ocelot yet, to
my knowledge.
In-band AN is not yet supported, due to the fact that this is a mostly
mechanical patch for the moment. The mac_an_restart PHYLINK operation
needs to be implemented, as well as mac_link_state. Both are SerDes
specific, and Felix does not have its PCS configured yet (it works just
by virtue of U-Boot initialization at the moment).
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
In the LS1028A, the VSC9959 switch was integrated with an NXP PCS which
performs SGMII AN and rate adaptation autonomously. The MAC does not
need to know about this, and forcing the MAC speed to something else,
when connected to a 10/100 link partner, actually breaks the GMII
internal link between the MAC and the PCS.
Add a quirk system in the ocelot driver, and a first quirk called "PCS
performs rate adaptation", to distinguish the VSC7514 from the VSC9959
regarding this behavior.
Signed-off-by: Catalin Horghidan <catalin.horghidan@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Support TSN configuration for ocelot switch. The TSN configuration
fucntions are based on tsn netlink interface, it can support Qbv,
Qbu, Qci, 802.1CB, and Qav configuration now.
Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
Convert to use skb queue instead of the list of skbs.
The skb queue could provide protection with lock.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Break the matching loop when find the matching skb for TX timestamp.
This is to avoid consuming more skbs incorrectly. The timestamp ID
is from 0 to 3 while the FIFO could support 128 timestamps at most.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Convert to use ocelot_port_add_txtstamp_skb() for adding skbs which
require TX timestamp into list. Export it so that DSA Felix driver
could reuse it too.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
The method getting TX timestamp by reading timestamp FIFO and
matching skbs list is common for DSA Felix driver too.
So move code out of ocelot_board.c, convert to use
ocelot_get_txtstamp() function and export it.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Export ocelot_hwstamp_get/set functions so that DSA driver
is able to reuse them.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
We will be registering another switch driver based on ocelot, which
lives under drivers/net/dsa.
Make sure the Felix DSA front-end has the necessary abstractions to
implement a new Ocelot driver instantiation. This includes the function
prototypes for implementing DSA callbacks.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
The Felix switch has a different reset procedure, so a function pointer
needs to be created and added to the ocelot_ops structure.
The reset procedure has been moved into ocelot_init.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
When using the NPI port, the DSA tag is passed through Ethernet, so the
switch's MAC needs to accept it as it comes from the DSA master. Increase
the MTU on the external CPU port to account for the length of the
injection header.
Without this patch, MTU-sized frames are dropped by the switch's CPU
port on xmit, which is especially obvious in TCP sessions.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This constant will be used in a future patch to increase the MTU on NPI
ports, and will also be used in the tagger driver for Felix.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Since in an NPI/DSA setup, not all ports will have the same MTU, we need
to make sure the watermarks for pause frames and/or tail dropping logic
that existed in the driver is still coherent for the new MTU values.
We need to do this because the NPI (aka external CPU) port needs an
increased MTU for the DSA tag. This will be done in a future patch.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
It doesn't make sense to rewrite all these registers every time the PHY
library notifies us about a link state change.
In a future patch we will customize the MTU for the CPU port, and since
the MTU was previously configured from adjust_link, if we don't make
this change, its value would have got overridden.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
The adjust_link routine should be generic enough to be (re)used by
any SoC that integrates a switch core compatible with the Ocelot
core switch driver. Currently all configurations are generic except
for the PCS settings that are SoC specific. Move these out to the
Ocelot SoC/board instance.
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
VSC7514 is a 10-port switch with 2 extra "CPU ports" (targets in the
queuing subsystem for terminating traffic locally).
There are 2 issues with hardcoding the CPU port as #10:
- It is not clear which snippets of the code are configuring something
for one of the CPU ports, and which snippets are just doing something
related to the number of physical ports.
- Actually any physical port can act as a CPU port connected to an
external CPU (in addition to the local CPU). This is called NPI mode
(Node Processor Interface) and is the way that the 6-port VSC9959
(Felix) switch is integrated inside NXP LS1028A (the "local management
CPU" functionality is not used there).
This patch makes it clear that the ocelot_bridge_stp_state_set function
operates on the CPU port (by making it an implicit member of the
bridging domain), and at the same time adds logic for the NPI port (aka
a physical port) to play the role of a CPU port (it shouldn't be part of
bridge_fwd_mask, as it's not explicitly enslaved to a bridge).
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Now that the places that configure routing destinations for the CPU port
have been marked as such, allow callers to specify their own CPU port
that is different than ocelot->num_phys_ports. A user will be the Felix
DSA driver, where the CPU port is one of the physical ports (NPI mode).
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This will be called from the Felix DSA frontend, which will work in
PHYLIB compatibility mode initially.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This is just common path code that belongs to ocelot_init,
it has nothing to do with a specific SoC/board instance.
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Allow these functions to be called from the .port_enable and
.port_disable callbacks of DSA.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
We need a function for the DSA front-end that does none of the
net_device registration, but initializes the hardware ports.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
The VSC7514 switch (Ocelot) is a 10-port device, while VSC9959 (Felix)
is 6-port. Therefore the VLAN filtering mask would be out of bounds when
calling for this new switch. Fix that.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Convert them into an implementation that can be called from DSA as well.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
The ocelot and ocelot_port structures will be used by a new DSA driver,
so the ocelot_board.c file will have to allocate and work with a private
structure (ocelot_port_private), which embeds the generic struct
ocelot_port. This is because in DSA, at least one interface does not
have a net_device, and the DSA driver API does not interact with that
anyway.
The ocelot_port structure is equivalent to dsa_port, and ocelot to
dsa_switch. The members of ocelot_port which have an equivalent in
dsa_port (such as dp->vlan_filtering) have been moved to
ocelot_port_private.
We want to enforce the coding convention that "ocelot_port" refers to
the structure, and "port" refers to the integer index. One can retrieve
the structure at any time from ocelot->ports[port].
The patch is large but only contains variable renaming and mechanical
movement of fields from one structure to another.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
The ocelot_port structure has a net_device embedded in it, which makes
it unsuitable for leaving it in the driver implementation functions.
Leave ocelot_flower.c untouched. In that file, ocelot_port is used as an
interface to the tc shared blocks. That will be addressed in the next
patch.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This is needed so that the Felix DSA front-end can call the Ocelot
implementations.
The implementation of the "mc_disabled" switchdev attribute has also
been simplified by using the read-modify-write macro instead of
open-coding that operation.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This is needed in order to present a simpler prototype to the DSA
front-end of ocelot.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
To be able to implement a DSA front-end over ocelot_fdb_add,
ocelot_fdb_del, ocelot_fdb_dump, these need to have a simple function
prototype that is independent of struct net_device, netlink skb, etc.
So rename the ndo ops of the ocelot driver into
ocelot_port_fdb_{add,del,dump}, and have them all call the abstract
implementations. At the same time, refactor ocelot_port_fdb_do_dump into
a function whose prototype is compatible with dsa_fdb_dump_cb_t, so that
the do_dump implementations can live together and be called by the
ocelot_fdb_dump through a function pointer.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
We need an implementation of these functions that is agnostic to the
higher layer (switchdev or dsa).
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This patch transforms the ocelot_vlan_port_apply function ("apply
what?") into 3 standalone functions:
- ocelot_port_vlan_filtering
- ocelot_port_set_native_vlan
- ocelot_port_set_pvid
These functions have a prototype that is better aligned to the DSA API.
The function also had some static initialization (TPID, drop frames with
multicast source MAC) which was not being changed from any place, so
that was just moved to ocelot_probe_port (one of the 6 callers of
ocelot_vlan_port_apply).
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
lag_upper_info may be NULL on slave removal.
Fixes: dc96ee3730 ("net: mscc: ocelot: add bonding support")
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
The check that the event is actually for this device should be moved
from the "port" handler to the net device handler.
Otherwise the port handler will deny bonding configuration for other
net devices in the same system (like enetc in the LS1028A) that don't
have the lag_upper_info->tx_type restriction that ocelot has.
Fixes: dc96ee3730 ("net: mscc: ocelot: add bonding support")
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
The switch driver keeps a "vid" variable per port, which signifies _the_
VLAN ID that is stripped on that port's egress (aka the native VLAN on a
trunk port).
That is the way the hardware is designed (mostly). The port->vid is
programmed into REW:PORT:PORT_VLAN_CFG:PORT_VID and the rewriter is told
to send all traffic as tagged except the one having port->vid.
There exists a possibility of finer-grained egress untagging decisions:
using the VCAP IS1 engine, one rule can be added to match every
VLAN-tagged frame whose VLAN should be untagged, and set POP_CNT=1 as
action. However, the IS1 can hold at most 512 entries, and the VLANs are
in the order of 6 * 4096.
So the code is fine for now. But this sequence of commands:
$ bridge vlan add dev swp0 vid 1 pvid untagged
$ bridge vlan add dev swp0 vid 2 untagged
makes untagged and pvid-tagged traffic be sent out of swp0 as tagged
with VID 1, despite user's request.
Prevent that from happening. The user should temporarily remove the
existing untagged VLAN (1 in this case), add it back as tagged, and then
add the new untagged VLAN (2 in this case).
Cc: Antoine Tenart <antoine.tenart@bootlin.com>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Fixes: 7142529f16 ("net: mscc: ocelot: add VLAN filtering")
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Background information: the driver operates the hardware in a mode where
a single VLAN can be transmitted as untagged on a particular egress
port. That is the "native VLAN on trunk port" use case. Its value is
held in port->vid.
Consider the following command sequence (no network manager, all
interfaces are down, debugging prints added by me):
$ ip link add dev br0 type bridge vlan_filtering 1
$ ip link set dev swp0 master br0
Kernel code path during last command:
br_add_slave -> ocelot_netdevice_port_event (NETDEV_CHANGEUPPER):
[ 21.401901] ocelot_vlan_port_apply: port 0 vlan aware 0 pvid 0 vid 0
br_add_slave -> nbp_vlan_init -> switchdev_port_attr_set -> ocelot_port_attr_set (SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING):
[ 21.413335] ocelot_vlan_port_apply: port 0 vlan aware 1 pvid 0 vid 0
br_add_slave -> nbp_vlan_init -> nbp_vlan_add -> br_switchdev_port_vlan_add -> switchdev_port_obj_add -> ocelot_port_obj_add -> ocelot_vlan_vid_add
[ 21.667421] ocelot_vlan_port_apply: port 0 vlan aware 1 pvid 1 vid 1
So far so good. The bridge has replaced the driver's default pvid used
in standalone mode (0) with its own default_pvid (1). The port's vid
(native VLAN) has also changed from 0 to 1.
$ ip link set dev swp0 up
[ 31.722956] 8021q: adding VLAN 0 to HW filter on device swp0
do_setlink -> dev_change_flags -> vlan_vid_add -> ocelot_vlan_rx_add_vid -> ocelot_vlan_vid_add:
[ 31.728700] ocelot_vlan_port_apply: port 0 vlan aware 1 pvid 1 vid 0
The 8021q module uses the .ndo_vlan_rx_add_vid API on .ndo_open to make
ports be able to transmit and receive 802.1p-tagged traffic by default.
This API is supposed to offload a VLAN sub-interface, which for a switch
port means to add a VLAN that is not a pvid, and tagged on egress.
But the driver implementation of .ndo_vlan_rx_add_vid is wrong: it adds
back vid 0 as "egress untagged". Now back to the initial paragraph:
there is a single untagged VID that the driver keeps track of, and that
has just changed from 1 (the pvid) to 0. So this breaks the bridge
core's expectation, because it has changed vid 1 from untagged to
tagged, when what the user sees is.
$ bridge vlan
port vlan ids
swp0 1 PVID Egress Untagged
br0 1 PVID Egress Untagged
But curiously, instead of manifesting itself as "untagged and
pvid-tagged traffic gets sent as tagged on egress", the bug:
- is hidden when vlan_filtering=0
- manifests as dropped traffic when vlan_filtering=1, due to this setting:
if (port->vlan_aware && !port->vid)
/* If port is vlan-aware and tagged, drop untagged and priority
* tagged frames.
*/
val |= ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA |
ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA;
which would have made sense if it weren't for this bug. The setting's
intention was "this is a trunk port with no native VLAN, so don't accept
untagged traffic". So the driver was never expecting to set VLAN 0 as
the value of the native VLAN, 0 was just encoding for "invalid".
So the fix is to not send 802.1p traffic as untagged, because that would
change the port's native vlan to 0, unbeknownst to the bridge, and
trigger unexpected code paths in the driver.
Cc: Antoine Tenart <antoine.tenart@bootlin.com>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Fixes: 7142529f16 ("net: mscc: ocelot: add VLAN filtering")
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Reviewed-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This patch adds support for PTP Hardware Clock (PHC) to the Ocelot
switch for both PTP 1-step and 2-step modes.
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Make sure the delayed work for stats update is not pending before
wq destruction.
This fixes the module unload path.
The issue is there since day 1.
Fixes: a556c76adc ("net: mscc: Add initial Ocelot switch support")
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Add ACL support using the TCAM. Using ACL it is possible to create rules
in hardware to filter/redirect frames.
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>