@@ -61,11 +61,46 @@ static int felix_cpu_port_for_conduit(struct dsa_switch *ds,
61
61
return cpu_dp -> index ;
62
62
}
63
63
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
+
64
98
/* Set up VCAP ES0 rules for pushing a tag_8021q VLAN towards the CPU such that
65
99
* the tagger can perform RX source port identification.
66
100
*/
67
101
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 )
69
104
{
70
105
struct ocelot_vcap_filter * outer_tagging_rule ;
71
106
struct ocelot * ocelot = ds -> priv ;
@@ -96,6 +131,14 @@ static int felix_tag_8021q_vlan_add_rx(struct dsa_switch *ds, int port,
96
131
outer_tagging_rule -> action .tag_a_tpid_sel = OCELOT_TAG_TPID_SEL_8021AD ;
97
132
outer_tagging_rule -> action .tag_a_vid_sel = 1 ;
98
133
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
+ */
99
142
100
143
err = ocelot_vcap_filter_add (ocelot , outer_tagging_rule , NULL );
101
144
if (err )
@@ -227,18 +270,20 @@ static int felix_tag_8021q_vlan_del_tx(struct dsa_switch *ds, int port, u16 vid)
227
270
static int felix_tag_8021q_vlan_add (struct dsa_switch * ds , int port , u16 vid ,
228
271
u16 flags )
229
272
{
273
+ struct dsa_port * dp = dsa_to_port (ds , port );
230
274
struct dsa_port * cpu_dp ;
231
275
int err ;
232
276
233
277
/* tag_8021q.c assumes we are implementing this via port VLAN
234
278
* membership, which we aren't. So we don't need to add any VCAP filter
235
279
* for the CPU port.
236
280
*/
237
- if (!dsa_is_user_port ( ds , port ))
281
+ if (!dsa_port_is_user ( dp ))
238
282
return 0 ;
239
283
240
284
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 ));
242
287
if (err )
243
288
return err ;
244
289
}
@@ -258,10 +303,11 @@ static int felix_tag_8021q_vlan_add(struct dsa_switch *ds, int port, u16 vid,
258
303
259
304
static int felix_tag_8021q_vlan_del (struct dsa_switch * ds , int port , u16 vid )
260
305
{
306
+ struct dsa_port * dp = dsa_to_port (ds , port );
261
307
struct dsa_port * cpu_dp ;
262
308
int err ;
263
309
264
- if (!dsa_is_user_port ( ds , port ))
310
+ if (!dsa_port_is_user ( dp ))
265
311
return 0 ;
266
312
267
313
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)
278
324
279
325
del_tx_failed :
280
326
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 ));
282
329
283
330
return err ;
284
331
}
285
332
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
+
286
362
static int felix_trap_get_cpu_port (struct dsa_switch * ds ,
287
363
const struct ocelot_vcap_filter * trap )
288
364
{
@@ -528,7 +604,19 @@ static int felix_tag_8021q_setup(struct dsa_switch *ds)
528
604
* so we need to be careful that there are no extra frames to be
529
605
* dequeued over MMIO, since we would never know to discard them.
530
606
*/
607
+ ocelot_lock_xtr_grp_bh (ocelot , 0 );
531
608
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;
532
620
533
621
return 0 ;
534
622
}
@@ -554,6 +642,8 @@ static void felix_tag_8021q_teardown(struct dsa_switch *ds)
554
642
ocelot_port_teardown_dsa_8021q_cpu (ocelot , dp -> index );
555
643
556
644
dsa_tag_8021q_unregister (ds );
645
+
646
+ ds -> untag_vlan_aware_bridge_pvid = false;
557
647
}
558
648
559
649
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,
1008
1098
struct netlink_ext_ack * extack )
1009
1099
{
1010
1100
struct ocelot * ocelot = ds -> priv ;
1101
+ bool using_tag_8021q ;
1102
+ struct felix * felix ;
1103
+ int err ;
1011
1104
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 ;
1013
1118
}
1014
1119
1015
1120
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)
1518
1623
int port = xmit_work -> dp -> index ;
1519
1624
int retries = 10 ;
1520
1625
1626
+ ocelot_lock_inj_grp (ocelot , 0 );
1627
+
1521
1628
do {
1522
1629
if (ocelot_can_inject (ocelot , 0 ))
1523
1630
break ;
@@ -1526,6 +1633,7 @@ static void felix_port_deferred_xmit(struct kthread_work *work)
1526
1633
} while (-- retries );
1527
1634
1528
1635
if (!retries ) {
1636
+ ocelot_unlock_inj_grp (ocelot , 0 );
1529
1637
dev_err (ocelot -> dev , "port %d failed to inject skb\n" ,
1530
1638
port );
1531
1639
ocelot_port_purge_txtstamp_skb (ocelot , port , skb );
@@ -1535,6 +1643,8 @@ static void felix_port_deferred_xmit(struct kthread_work *work)
1535
1643
1536
1644
ocelot_port_inject_frame (ocelot , port , 0 , rew_op , skb );
1537
1645
1646
+ ocelot_unlock_inj_grp (ocelot , 0 );
1647
+
1538
1648
consume_skb (skb );
1539
1649
kfree (xmit_work );
1540
1650
}
@@ -1694,6 +1804,8 @@ static bool felix_check_xtr_pkt(struct ocelot *ocelot)
1694
1804
if (!felix -> info -> quirk_no_xtr_irq )
1695
1805
return false;
1696
1806
1807
+ ocelot_lock_xtr_grp (ocelot , grp );
1808
+
1697
1809
while (ocelot_read (ocelot , QS_XTR_DATA_PRESENT ) & BIT (grp )) {
1698
1810
struct sk_buff * skb ;
1699
1811
unsigned int type ;
@@ -1730,6 +1842,8 @@ static bool felix_check_xtr_pkt(struct ocelot *ocelot)
1730
1842
ocelot_drain_cpu_queue (ocelot , 0 );
1731
1843
}
1732
1844
1845
+ ocelot_unlock_xtr_grp (ocelot , grp );
1846
+
1733
1847
return true;
1734
1848
}
1735
1849
0 commit comments