Skip to content

Commit 4b65d44

Browse files
vladimirolteankuba-moo
authored andcommitted
net: dsa: ocelot: use simple HSR offload helpers
Accelerate TX packet duplication with HSR rings. This is only possible with the NPI-based "ocelot" tagging protocol, not with "ocelot-8021q", because the latter does not use dsa_xmit_port_mask(). This has 2 implications: - Depending on tagging protocol, we should set (or not set) the offload feature flags. Switching tagging protocols is done with ports down, by design. Additional calls to dsa_port_simple_hsr_join() can be put in the ds->ops->change_tag_protocol() path, as I had originally tried, but this would not work: dsa_user_setup_tagger() would later clear the feature flag that we just set. So the additional call to dsa_port_simple_hsr_join() should sit in the ds->ops->port_enable() call. - When joining a HSR ring and we are currently using "ocelot-8021q", there are cases when we should return -EOPNOTSUPP (pessimistic) and cases when we shouldn't (optimistic). In the pessimistic case, it is a configuration that the port won't support even with the right tagging protocol. Distinguishing between these 2 cases matters because if we just return -EOPNOTSUPP regardless, we lose the dp->hsr_dev pointer and can no longer replay the offload later for the optimistic case, from felix_port_enable(). Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://patch.msgid.link/20251130131657.65080-8-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 42e63b1 commit 4b65d44

1 file changed

Lines changed: 69 additions & 1 deletion

File tree

drivers/net/dsa/ocelot/felix.c

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,7 @@ static int felix_port_enable(struct dsa_switch *ds, int port,
12331233
{
12341234
struct dsa_port *dp = dsa_to_port(ds, port);
12351235
struct ocelot *ocelot = ds->priv;
1236+
struct felix *felix = ocelot_to_felix(ocelot);
12361237

12371238
if (!dsa_port_is_user(dp))
12381239
return 0;
@@ -1246,7 +1247,25 @@ static int felix_port_enable(struct dsa_switch *ds, int port,
12461247
}
12471248
}
12481249

1249-
return 0;
1250+
if (!dp->hsr_dev || felix->tag_proto == DSA_TAG_PROTO_OCELOT_8021Q)
1251+
return 0;
1252+
1253+
return dsa_port_simple_hsr_join(ds, port, dp->hsr_dev, NULL);
1254+
}
1255+
1256+
static void felix_port_disable(struct dsa_switch *ds, int port)
1257+
{
1258+
struct dsa_port *dp = dsa_to_port(ds, port);
1259+
struct ocelot *ocelot = ds->priv;
1260+
struct felix *felix = ocelot_to_felix(ocelot);
1261+
1262+
if (!dsa_port_is_user(dp))
1263+
return;
1264+
1265+
if (!dp->hsr_dev || felix->tag_proto == DSA_TAG_PROTO_OCELOT_8021Q)
1266+
return;
1267+
1268+
dsa_port_simple_hsr_leave(ds, port, dp->hsr_dev);
12501269
}
12511270

12521271
static void felix_port_qos_map_init(struct ocelot *ocelot, int port)
@@ -2232,6 +2251,52 @@ static void felix_get_mm_stats(struct dsa_switch *ds, int port,
22322251
ocelot_port_get_mm_stats(ocelot, port, stats);
22332252
}
22342253

2254+
/* Depending on port type, we may be able to support the offload later (with
2255+
* the "ocelot"/"seville" tagging protocols), or never.
2256+
* If we return 0, the dp->hsr_dev reference is kept for later; if we return
2257+
* -EOPNOTSUPP, it is cleared (which helps to not bother
2258+
* dsa_port_simple_hsr_leave() with an offload that didn't pass validation).
2259+
*/
2260+
static int felix_port_hsr_join(struct dsa_switch *ds, int port,
2261+
struct net_device *hsr,
2262+
struct netlink_ext_ack *extack)
2263+
{
2264+
struct ocelot *ocelot = ds->priv;
2265+
struct felix *felix = ocelot_to_felix(ocelot);
2266+
2267+
if (felix->tag_proto == DSA_TAG_PROTO_OCELOT_8021Q) {
2268+
int err;
2269+
2270+
err = dsa_port_simple_hsr_validate(ds, port, hsr, extack);
2271+
if (err)
2272+
return err;
2273+
2274+
NL_SET_ERR_MSG_MOD(extack,
2275+
"Offloading not supported with \"ocelot-8021q\"");
2276+
return 0;
2277+
}
2278+
2279+
if (!(dsa_to_port(ds, port)->user->flags & IFF_UP))
2280+
return 0;
2281+
2282+
return dsa_port_simple_hsr_join(ds, port, hsr, extack);
2283+
}
2284+
2285+
static int felix_port_hsr_leave(struct dsa_switch *ds, int port,
2286+
struct net_device *hsr)
2287+
{
2288+
struct ocelot *ocelot = ds->priv;
2289+
struct felix *felix = ocelot_to_felix(ocelot);
2290+
2291+
if (felix->tag_proto == DSA_TAG_PROTO_OCELOT_8021Q)
2292+
return 0;
2293+
2294+
if (!(dsa_to_port(ds, port)->user->flags & IFF_UP))
2295+
return 0;
2296+
2297+
return dsa_port_simple_hsr_leave(ds, port, hsr);
2298+
}
2299+
22352300
static const struct phylink_mac_ops felix_phylink_mac_ops = {
22362301
.mac_select_pcs = felix_phylink_mac_select_pcs,
22372302
.mac_config = felix_phylink_mac_config,
@@ -2262,6 +2327,7 @@ static const struct dsa_switch_ops felix_switch_ops = {
22622327
.get_ts_info = felix_get_ts_info,
22632328
.phylink_get_caps = felix_phylink_get_caps,
22642329
.port_enable = felix_port_enable,
2330+
.port_disable = felix_port_disable,
22652331
.port_fast_age = felix_port_fast_age,
22662332
.port_fdb_dump = felix_fdb_dump,
22672333
.port_fdb_add = felix_fdb_add,
@@ -2318,6 +2384,8 @@ static const struct dsa_switch_ops felix_switch_ops = {
23182384
.port_del_dscp_prio = felix_port_del_dscp_prio,
23192385
.port_set_host_flood = felix_port_set_host_flood,
23202386
.port_change_conduit = felix_port_change_conduit,
2387+
.port_hsr_join = felix_port_hsr_join,
2388+
.port_hsr_leave = felix_port_hsr_leave,
23212389
};
23222390

23232391
int felix_register_switch(struct device *dev, resource_size_t switch_base,

0 commit comments

Comments
 (0)