@@ -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 */
67101static 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)
227270static 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
259304static 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
279325del_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+
286362static 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
559649static 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
10151120static 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