Commit 3101f3e1 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'dsa-simple-hsr-offload'

Vladimir Oltean says:

====================
DSA simple HSR offload

Provide a "simple" form of HSR offload for 8 DSA drivers (just the
NETIF_F_HW_HSR_DUP feature) based on the fact that their taggers use the
dsa_xmit_port_mask() function. This is in patches 6-13/15.

The helpers per se are introduced in patch 5/15, and documented in patch
15/15. Patch 14/15 is another small (and related) documentation update.

For HSR interlink ports the offloading rules are not quite so clear, and
for now we completely reject the offload. We can revise that once we see
a full offload implementation and understand what is needed.

To reject the offload, we need to know the port type, and patch 2/15
helps with that.

xrs700x is another driver which should have rejected offload based on
port type (patch 4/15). This is a bug fix submitted through net-next due
to the extra API required to fix it. If necessary, it could also be
picked up separately for backporting.

There is also patch 3/15, which makes the HSR offload like the others
supported by DSA: if we fall back to the software implementation, don't
call port_hsr_leave(), because by definition there won't be anything to
do.

A slightly unrelated change is patch 1/15, but I noticed this along the
way, and if I were to submit it separately, it would conflict with this
work (it would appear in patch 12/15's context).

Most of the driver additions are trivial. By far the most complex was
ocelot (which I could test). Microchip ksz (which I cannot test, and did
not patch) would also have some complexity. Essentially, ksz_hsr_join()
could fall back to a partial offload through the simple helpers, if the
full offload is not possible. But keeping track of which offload kind
was used is necessary later in ksz_hsr_leave(). This is left as homework
for interested developers.

With this patch set, one can observe a 50% reduction in transmitted
traffic over HSR interfaces.
====================

Link: https://patch.msgid.link/20251130131657.65080-1-vladimir.oltean@nxp.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents b4dcaeea 4e4c00f3
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -1104,12 +1104,11 @@ health of the network and for discovery of other nodes.
In Linux, both HSR and PRP are implemented in the hsr driver, which
instantiates a virtual, stackable network interface with two member ports.
The driver only implements the basic roles of DANH (Doubly Attached Node
implementing HSR) and DANP (Doubly Attached Node implementing PRP); the roles
of RedBox and QuadBox are not implemented (therefore, bridging a hsr network
interface with a physical switch port does not produce the expected result).
implementing HSR), DANP (Doubly Attached Node implementing PRP) and RedBox
(allows non-HSR devices to connect to the ring via Interlink ports).

A driver which is able of offloading certain functions of a DANP or DANH should
declare the corresponding netdev features as indicated by the documentation at
A driver which is able of offloading certain functions should declare the
corresponding netdev features as indicated by the documentation at
``Documentation/networking/netdev-features.rst``. Additionally, the following
methods must be implemented:

@@ -1120,6 +1119,14 @@ methods must be implemented:
- ``port_hsr_leave``: function invoked when a given switch port leaves a
  DANP/DANH and returns to normal operation as a standalone port.

Note that the ``NETIF_F_HW_HSR_DUP`` feature relies on transmission towards
multiple ports, which is generally available whenever the tagging protocol uses
the ``dsa_xmit_port_mask()`` helper function. If the helper is used, the HSR
offload feature should also be set. The ``dsa_port_simple_hsr_join()`` and
``dsa_port_simple_hsr_leave()`` methods can be used as generic implementations
of ``port_hsr_join`` and ``port_hsr_leave``, if this is the only supported
offload feature.

TODO
====

+2 −0
Original line number Diff line number Diff line
@@ -1926,6 +1926,8 @@ static const struct dsa_switch_ops hellcreek_ds_ops = {
	.port_vlan_filtering   = hellcreek_vlan_filtering,
	.setup		       = hellcreek_setup,
	.teardown	       = hellcreek_teardown,
	.port_hsr_join	       = dsa_port_simple_hsr_join,
	.port_hsr_leave	       = dsa_port_simple_hsr_leave,
};

static int hellcreek_probe(struct platform_device *pdev)
+2 −0
Original line number Diff line number Diff line
@@ -1652,6 +1652,8 @@ static const struct dsa_switch_ops gswip_switch_ops = {
	.get_sset_count		= gswip_get_sset_count,
	.set_mac_eee		= gswip_set_mac_eee,
	.support_eee		= gswip_support_eee,
	.port_hsr_join		= dsa_port_simple_hsr_join,
	.port_hsr_leave		= dsa_port_simple_hsr_leave,
};

void gswip_disable_switch(struct gswip_priv *priv)
+3 −2
Original line number Diff line number Diff line
@@ -3254,7 +3254,7 @@ static int mt7988_setup(struct dsa_switch *ds)
	return mt7531_setup_common(ds);
}

const struct dsa_switch_ops mt7530_switch_ops = {
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,
@@ -3290,8 +3290,9 @@ const struct dsa_switch_ops mt7530_switch_ops = {
	.set_mac_eee		= mt753x_set_mac_eee,
	.conduit_state_change	= mt753x_conduit_state_change,
	.port_setup_tc		= mt753x_setup_tc,
	.port_hsr_join		= dsa_port_simple_hsr_join,
	.port_hsr_leave		= dsa_port_simple_hsr_leave,
};
EXPORT_SYMBOL_GPL(mt7530_switch_ops);

static const struct phylink_mac_ops mt753x_phylink_mac_ops = {
	.mac_select_pcs	= mt753x_phylink_mac_select_pcs,
+0 −1
Original line number Diff line number Diff line
@@ -939,7 +939,6 @@ static inline void INIT_MT7530_DUMMY_POLL(struct mt7530_dummy_poll *p,
int mt7530_probe_common(struct mt7530_priv *priv);
void mt7530_remove_common(struct mt7530_priv *priv);

extern const struct dsa_switch_ops mt7530_switch_ops;
extern const struct mt753x_info mt753x_table[];

#endif /* __MT7530_H */
Loading