Skip to content

Commit 3d93a14

Browse files
committed
Merge branch 'vln-ocelot-fixes'
Vladimir Oltean says: ==================== VLAN fixes for Ocelot driver This is a collection of patches I've gathered over the past several months. Patches 1-6/14 are supporting patches for selftests. Patch 9/14 fixes PTP TX from a VLAN upper of a VLAN-aware bridge port when using the "ocelot-8021q" tagging protocol. Patch 7/14 is its supporting selftest. Patch 10/14 fixes the QoS class used by PTP in the same case as above. It is hard to quantify - there is no selftest. Patch 11/14 fixes potential data corruption during PTP TX in the same case as above. Again, there is no selftest. Patch 13/14 fixes RX in the same case as above - 8021q upper of a VLAN-aware bridge port, with the "ocelot-8021q" tagging protocol. Patch 12/14 is a supporting patch for this in the DSA core, and 7/14 is also its selftest. Patch 14/14 ensures that VLAN-aware bridges offloaded to Ocelot only react to the ETH_P_8021Q TPID, and treat absolutely everything else as VLAN-untagged, including ETH_P_8021AD. Patch 8/14 is the supporting selftest. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents b153b3c + 36dd114 commit 3d93a14

File tree

15 files changed

+1036
-173
lines changed

15 files changed

+1036
-173
lines changed

drivers/net/dsa/ocelot/felix.c

Lines changed: 120 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,46 @@ static int felix_cpu_port_for_conduit(struct dsa_switch *ds,
6161
return cpu_dp->index;
6262
}
6363

64+
/**
65+
* felix_update_tag_8021q_rx_rule - Update VCAP ES0 tag_8021q rule after
66+
* vlan_filtering change
67+
* @outer_tagging_rule: Pointer to VCAP filter on which the update is performed
68+
* @vlan_filtering: Current bridge VLAN filtering setting
69+
*
70+
* Source port identification for tag_8021q is done using VCAP ES0 rules on the
71+
* CPU port(s). The ES0 tag B (inner tag from the packet) can be configured as
72+
* either:
73+
* - push_inner_tag=0: the inner tag is never pushed into the frame
74+
* (and we lose info about the classified VLAN). This is
75+
* good when the classified VLAN is a discardable quantity
76+
* for the software RX path: it is either set to
77+
* OCELOT_STANDALONE_PVID, or to
78+
* ocelot_vlan_unaware_pvid(bridge).
79+
* - push_inner_tag=1: the inner tag is always pushed. This is good when the
80+
* classified VLAN is not a discardable quantity (the port
81+
* is under a VLAN-aware bridge, and software needs to
82+
* continue processing the packet in the same VLAN as the
83+
* hardware).
84+
* The point is that what is good for a VLAN-unaware port is not good for a
85+
* VLAN-aware port, and vice versa. Thus, the RX tagging rules must be kept in
86+
* sync with the VLAN filtering state of the port.
87+
*/
88+
static void
89+
felix_update_tag_8021q_rx_rule(struct ocelot_vcap_filter *outer_tagging_rule,
90+
bool vlan_filtering)
91+
{
92+
if (vlan_filtering)
93+
outer_tagging_rule->action.push_inner_tag = OCELOT_ES0_TAG;
94+
else
95+
outer_tagging_rule->action.push_inner_tag = OCELOT_NO_ES0_TAG;
96+
}
97+
6498
/* Set up VCAP ES0 rules for pushing a tag_8021q VLAN towards the CPU such that
6599
* the tagger can perform RX source port identification.
66100
*/
67101
static int felix_tag_8021q_vlan_add_rx(struct dsa_switch *ds, int port,
68-
int upstream, u16 vid)
102+
int upstream, u16 vid,
103+
bool vlan_filtering)
69104
{
70105
struct ocelot_vcap_filter *outer_tagging_rule;
71106
struct ocelot *ocelot = ds->priv;
@@ -96,6 +131,14 @@ static int felix_tag_8021q_vlan_add_rx(struct dsa_switch *ds, int port,
96131
outer_tagging_rule->action.tag_a_tpid_sel = OCELOT_TAG_TPID_SEL_8021AD;
97132
outer_tagging_rule->action.tag_a_vid_sel = 1;
98133
outer_tagging_rule->action.vid_a_val = vid;
134+
felix_update_tag_8021q_rx_rule(outer_tagging_rule, vlan_filtering);
135+
outer_tagging_rule->action.tag_b_tpid_sel = OCELOT_TAG_TPID_SEL_8021Q;
136+
/* Leave TAG_B_VID_SEL at 0 (Classified VID + VID_B_VAL). Since we also
137+
* leave VID_B_VAL at 0, this makes ES0 tag B (the inner tag) equal to
138+
* the classified VID, which we need to see in the DSA tagger's receive
139+
* path. Note: the inner tag is only visible in the packet when pushed
140+
* (push_inner_tag == OCELOT_ES0_TAG).
141+
*/
99142

100143
err = ocelot_vcap_filter_add(ocelot, outer_tagging_rule, NULL);
101144
if (err)
@@ -227,18 +270,20 @@ static int felix_tag_8021q_vlan_del_tx(struct dsa_switch *ds, int port, u16 vid)
227270
static int felix_tag_8021q_vlan_add(struct dsa_switch *ds, int port, u16 vid,
228271
u16 flags)
229272
{
273+
struct dsa_port *dp = dsa_to_port(ds, port);
230274
struct dsa_port *cpu_dp;
231275
int err;
232276

233277
/* tag_8021q.c assumes we are implementing this via port VLAN
234278
* membership, which we aren't. So we don't need to add any VCAP filter
235279
* for the CPU port.
236280
*/
237-
if (!dsa_is_user_port(ds, port))
281+
if (!dsa_port_is_user(dp))
238282
return 0;
239283

240284
dsa_switch_for_each_cpu_port(cpu_dp, ds) {
241-
err = felix_tag_8021q_vlan_add_rx(ds, port, cpu_dp->index, vid);
285+
err = felix_tag_8021q_vlan_add_rx(ds, port, cpu_dp->index, vid,
286+
dsa_port_is_vlan_filtering(dp));
242287
if (err)
243288
return err;
244289
}
@@ -258,10 +303,11 @@ static int felix_tag_8021q_vlan_add(struct dsa_switch *ds, int port, u16 vid,
258303

259304
static int felix_tag_8021q_vlan_del(struct dsa_switch *ds, int port, u16 vid)
260305
{
306+
struct dsa_port *dp = dsa_to_port(ds, port);
261307
struct dsa_port *cpu_dp;
262308
int err;
263309

264-
if (!dsa_is_user_port(ds, port))
310+
if (!dsa_port_is_user(dp))
265311
return 0;
266312

267313
dsa_switch_for_each_cpu_port(cpu_dp, ds) {
@@ -278,11 +324,41 @@ static int felix_tag_8021q_vlan_del(struct dsa_switch *ds, int port, u16 vid)
278324

279325
del_tx_failed:
280326
dsa_switch_for_each_cpu_port(cpu_dp, ds)
281-
felix_tag_8021q_vlan_add_rx(ds, port, cpu_dp->index, vid);
327+
felix_tag_8021q_vlan_add_rx(ds, port, cpu_dp->index, vid,
328+
dsa_port_is_vlan_filtering(dp));
282329

283330
return err;
284331
}
285332

333+
static int felix_update_tag_8021q_rx_rules(struct dsa_switch *ds, int port,
334+
bool vlan_filtering)
335+
{
336+
struct ocelot_vcap_filter *outer_tagging_rule;
337+
struct ocelot_vcap_block *block_vcap_es0;
338+
struct ocelot *ocelot = ds->priv;
339+
struct dsa_port *cpu_dp;
340+
unsigned long cookie;
341+
int err;
342+
343+
block_vcap_es0 = &ocelot->block[VCAP_ES0];
344+
345+
dsa_switch_for_each_cpu_port(cpu_dp, ds) {
346+
cookie = OCELOT_VCAP_ES0_TAG_8021Q_RXVLAN(ocelot, port,
347+
cpu_dp->index);
348+
349+
outer_tagging_rule = ocelot_vcap_block_find_filter_by_id(block_vcap_es0,
350+
cookie, false);
351+
352+
felix_update_tag_8021q_rx_rule(outer_tagging_rule, vlan_filtering);
353+
354+
err = ocelot_vcap_filter_replace(ocelot, outer_tagging_rule);
355+
if (err)
356+
return err;
357+
}
358+
359+
return 0;
360+
}
361+
286362
static int felix_trap_get_cpu_port(struct dsa_switch *ds,
287363
const struct ocelot_vcap_filter *trap)
288364
{
@@ -528,7 +604,19 @@ static int felix_tag_8021q_setup(struct dsa_switch *ds)
528604
* so we need to be careful that there are no extra frames to be
529605
* dequeued over MMIO, since we would never know to discard them.
530606
*/
607+
ocelot_lock_xtr_grp_bh(ocelot, 0);
531608
ocelot_drain_cpu_queue(ocelot, 0);
609+
ocelot_unlock_xtr_grp_bh(ocelot, 0);
610+
611+
/* Problem: when using push_inner_tag=1 for ES0 tag B, we lose info
612+
* about whether the received packets were VLAN-tagged on the wire,
613+
* since they are always tagged on egress towards the CPU port.
614+
*
615+
* Since using push_inner_tag=1 is unavoidable for VLAN-aware bridges,
616+
* we must work around the fallout by untagging in software to make
617+
* untagged reception work more or less as expected.
618+
*/
619+
ds->untag_vlan_aware_bridge_pvid = true;
532620

533621
return 0;
534622
}
@@ -554,6 +642,8 @@ static void felix_tag_8021q_teardown(struct dsa_switch *ds)
554642
ocelot_port_teardown_dsa_8021q_cpu(ocelot, dp->index);
555643

556644
dsa_tag_8021q_unregister(ds);
645+
646+
ds->untag_vlan_aware_bridge_pvid = false;
557647
}
558648

559649
static unsigned long felix_tag_8021q_get_host_fwd_mask(struct dsa_switch *ds)
@@ -1008,8 +1098,23 @@ static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
10081098
struct netlink_ext_ack *extack)
10091099
{
10101100
struct ocelot *ocelot = ds->priv;
1101+
bool using_tag_8021q;
1102+
struct felix *felix;
1103+
int err;
10111104

1012-
return ocelot_port_vlan_filtering(ocelot, port, enabled, extack);
1105+
err = ocelot_port_vlan_filtering(ocelot, port, enabled, extack);
1106+
if (err)
1107+
return err;
1108+
1109+
felix = ocelot_to_felix(ocelot);
1110+
using_tag_8021q = felix->tag_proto == DSA_TAG_PROTO_OCELOT_8021Q;
1111+
if (using_tag_8021q) {
1112+
err = felix_update_tag_8021q_rx_rules(ds, port, enabled);
1113+
if (err)
1114+
return err;
1115+
}
1116+
1117+
return 0;
10131118
}
10141119

10151120
static int felix_vlan_add(struct dsa_switch *ds, int port,
@@ -1518,6 +1623,8 @@ static void felix_port_deferred_xmit(struct kthread_work *work)
15181623
int port = xmit_work->dp->index;
15191624
int retries = 10;
15201625

1626+
ocelot_lock_inj_grp(ocelot, 0);
1627+
15211628
do {
15221629
if (ocelot_can_inject(ocelot, 0))
15231630
break;
@@ -1526,6 +1633,7 @@ static void felix_port_deferred_xmit(struct kthread_work *work)
15261633
} while (--retries);
15271634

15281635
if (!retries) {
1636+
ocelot_unlock_inj_grp(ocelot, 0);
15291637
dev_err(ocelot->dev, "port %d failed to inject skb\n",
15301638
port);
15311639
ocelot_port_purge_txtstamp_skb(ocelot, port, skb);
@@ -1535,6 +1643,8 @@ static void felix_port_deferred_xmit(struct kthread_work *work)
15351643

15361644
ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb);
15371645

1646+
ocelot_unlock_inj_grp(ocelot, 0);
1647+
15381648
consume_skb(skb);
15391649
kfree(xmit_work);
15401650
}
@@ -1694,6 +1804,8 @@ static bool felix_check_xtr_pkt(struct ocelot *ocelot)
16941804
if (!felix->info->quirk_no_xtr_irq)
16951805
return false;
16961806

1807+
ocelot_lock_xtr_grp(ocelot, grp);
1808+
16971809
while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) {
16981810
struct sk_buff *skb;
16991811
unsigned int type;
@@ -1730,6 +1842,8 @@ static bool felix_check_xtr_pkt(struct ocelot *ocelot)
17301842
ocelot_drain_cpu_queue(ocelot, 0);
17311843
}
17321844

1845+
ocelot_unlock_xtr_grp(ocelot, grp);
1846+
17331847
return true;
17341848
}
17351849

0 commit comments

Comments
 (0)