1 // SPDX-License-Identifier: GPL-2.0+
2
3 #include "lan966x_main.h"
4
5 #define VLANACCESS_CMD_IDLE 0
6 #define VLANACCESS_CMD_READ 1
7 #define VLANACCESS_CMD_WRITE 2
8 #define VLANACCESS_CMD_INIT 3
9
lan966x_vlan_get_status(struct lan966x * lan966x)10 static int lan966x_vlan_get_status(struct lan966x *lan966x)
11 {
12 return lan_rd(lan966x, ANA_VLANACCESS);
13 }
14
lan966x_vlan_wait_for_completion(struct lan966x * lan966x)15 static int lan966x_vlan_wait_for_completion(struct lan966x *lan966x)
16 {
17 u32 val;
18
19 return readx_poll_timeout(lan966x_vlan_get_status,
20 lan966x, val,
21 (val & ANA_VLANACCESS_VLAN_TBL_CMD) ==
22 VLANACCESS_CMD_IDLE,
23 TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US);
24 }
25
lan966x_vlan_set_mask(struct lan966x * lan966x,u16 vid)26 static void lan966x_vlan_set_mask(struct lan966x *lan966x, u16 vid)
27 {
28 u16 mask = lan966x->vlan_mask[vid];
29 bool cpu_dis;
30
31 cpu_dis = !(mask & BIT(CPU_PORT));
32
33 /* Set flags and the VID to configure */
34 lan_rmw(ANA_VLANTIDX_VLAN_PGID_CPU_DIS_SET(cpu_dis) |
35 ANA_VLANTIDX_V_INDEX_SET(vid),
36 ANA_VLANTIDX_VLAN_PGID_CPU_DIS |
37 ANA_VLANTIDX_V_INDEX,
38 lan966x, ANA_VLANTIDX);
39
40 /* Set the vlan port members mask */
41 lan_rmw(ANA_VLAN_PORT_MASK_VLAN_PORT_MASK_SET(mask),
42 ANA_VLAN_PORT_MASK_VLAN_PORT_MASK,
43 lan966x, ANA_VLAN_PORT_MASK);
44
45 /* Issue a write command */
46 lan_rmw(ANA_VLANACCESS_VLAN_TBL_CMD_SET(VLANACCESS_CMD_WRITE),
47 ANA_VLANACCESS_VLAN_TBL_CMD,
48 lan966x, ANA_VLANACCESS);
49
50 if (lan966x_vlan_wait_for_completion(lan966x))
51 dev_err(lan966x->dev, "Vlan set mask failed\n");
52 }
53
lan966x_vlan_port_add_vlan_mask(struct lan966x_port * port,u16 vid)54 static void lan966x_vlan_port_add_vlan_mask(struct lan966x_port *port, u16 vid)
55 {
56 struct lan966x *lan966x = port->lan966x;
57 u8 p = port->chip_port;
58
59 lan966x->vlan_mask[vid] |= BIT(p);
60 lan966x_vlan_set_mask(lan966x, vid);
61 }
62
lan966x_vlan_port_del_vlan_mask(struct lan966x_port * port,u16 vid)63 static void lan966x_vlan_port_del_vlan_mask(struct lan966x_port *port, u16 vid)
64 {
65 struct lan966x *lan966x = port->lan966x;
66 u8 p = port->chip_port;
67
68 lan966x->vlan_mask[vid] &= ~BIT(p);
69 lan966x_vlan_set_mask(lan966x, vid);
70 }
71
lan966x_vlan_port_any_vlan_mask(struct lan966x * lan966x,u16 vid)72 static bool lan966x_vlan_port_any_vlan_mask(struct lan966x *lan966x, u16 vid)
73 {
74 return !!(lan966x->vlan_mask[vid] & ~BIT(CPU_PORT));
75 }
76
lan966x_vlan_cpu_add_vlan_mask(struct lan966x * lan966x,u16 vid)77 static void lan966x_vlan_cpu_add_vlan_mask(struct lan966x *lan966x, u16 vid)
78 {
79 lan966x->vlan_mask[vid] |= BIT(CPU_PORT);
80 lan966x_vlan_set_mask(lan966x, vid);
81 }
82
lan966x_vlan_cpu_del_vlan_mask(struct lan966x * lan966x,u16 vid)83 static void lan966x_vlan_cpu_del_vlan_mask(struct lan966x *lan966x, u16 vid)
84 {
85 lan966x->vlan_mask[vid] &= ~BIT(CPU_PORT);
86 lan966x_vlan_set_mask(lan966x, vid);
87 }
88
lan966x_vlan_cpu_add_cpu_vlan_mask(struct lan966x * lan966x,u16 vid)89 static void lan966x_vlan_cpu_add_cpu_vlan_mask(struct lan966x *lan966x, u16 vid)
90 {
91 __set_bit(vid, lan966x->cpu_vlan_mask);
92 }
93
lan966x_vlan_cpu_del_cpu_vlan_mask(struct lan966x * lan966x,u16 vid)94 static void lan966x_vlan_cpu_del_cpu_vlan_mask(struct lan966x *lan966x, u16 vid)
95 {
96 __clear_bit(vid, lan966x->cpu_vlan_mask);
97 }
98
lan966x_vlan_cpu_member_cpu_vlan_mask(struct lan966x * lan966x,u16 vid)99 bool lan966x_vlan_cpu_member_cpu_vlan_mask(struct lan966x *lan966x, u16 vid)
100 {
101 return test_bit(vid, lan966x->cpu_vlan_mask);
102 }
103
lan966x_vlan_port_get_pvid(struct lan966x_port * port)104 static u16 lan966x_vlan_port_get_pvid(struct lan966x_port *port)
105 {
106 struct lan966x *lan966x = port->lan966x;
107
108 if (!(lan966x->bridge_mask & BIT(port->chip_port)))
109 return HOST_PVID;
110
111 return port->vlan_aware ? port->pvid : UNAWARE_PVID;
112 }
113
lan966x_vlan_port_set_vid(struct lan966x_port * port,u16 vid,bool pvid,bool untagged)114 int lan966x_vlan_port_set_vid(struct lan966x_port *port, u16 vid,
115 bool pvid, bool untagged)
116 {
117 struct lan966x *lan966x = port->lan966x;
118
119 /* Egress vlan classification */
120 if (untagged && port->vid != vid) {
121 if (port->vid) {
122 dev_err(lan966x->dev,
123 "Port already has a native VLAN: %d\n",
124 port->vid);
125 return -EBUSY;
126 }
127 port->vid = vid;
128 }
129
130 /* Default ingress vlan classification */
131 if (pvid)
132 port->pvid = vid;
133
134 return 0;
135 }
136
lan966x_vlan_port_remove_vid(struct lan966x_port * port,u16 vid)137 static void lan966x_vlan_port_remove_vid(struct lan966x_port *port, u16 vid)
138 {
139 if (port->pvid == vid)
140 port->pvid = 0;
141
142 if (port->vid == vid)
143 port->vid = 0;
144 }
145
lan966x_vlan_port_set_vlan_aware(struct lan966x_port * port,bool vlan_aware)146 void lan966x_vlan_port_set_vlan_aware(struct lan966x_port *port,
147 bool vlan_aware)
148 {
149 port->vlan_aware = vlan_aware;
150 }
151
152 /* When the interface is in host mode, the interface should not be vlan aware
153 * but it should insert all the tags that it gets from the network stack.
154 * The tags are not in the data of the frame but actually in the skb and the ifh
155 * is configured already to get this tag. So what we need to do is to update the
156 * rewriter to insert the vlan tag for all frames which have a vlan tag
157 * different than 0.
158 */
lan966x_vlan_port_rew_host(struct lan966x_port * port)159 void lan966x_vlan_port_rew_host(struct lan966x_port *port)
160 {
161 struct lan966x *lan966x = port->lan966x;
162 u32 val;
163
164 /* Tag all frames except when VID=0*/
165 val = REW_TAG_CFG_TAG_CFG_SET(2);
166
167 /* Update only some bits in the register */
168 lan_rmw(val,
169 REW_TAG_CFG_TAG_CFG,
170 lan966x, REW_TAG_CFG(port->chip_port));
171 }
172
lan966x_vlan_port_apply(struct lan966x_port * port)173 void lan966x_vlan_port_apply(struct lan966x_port *port)
174 {
175 struct lan966x *lan966x = port->lan966x;
176 u16 pvid;
177 u32 val;
178
179 pvid = lan966x_vlan_port_get_pvid(port);
180
181 /* Ingress clasification (ANA_PORT_VLAN_CFG) */
182 /* Default vlan to classify for untagged frames (may be zero) */
183 val = ANA_VLAN_CFG_VLAN_VID_SET(pvid);
184 if (port->vlan_aware)
185 val |= ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) |
186 ANA_VLAN_CFG_VLAN_POP_CNT_SET(1);
187
188 lan_rmw(val,
189 ANA_VLAN_CFG_VLAN_VID | ANA_VLAN_CFG_VLAN_AWARE_ENA |
190 ANA_VLAN_CFG_VLAN_POP_CNT,
191 lan966x, ANA_VLAN_CFG(port->chip_port));
192
193 lan_rmw(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(port->vlan_aware) |
194 DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_SET(port->vlan_aware),
195 DEV_MAC_TAGS_CFG_VLAN_AWR_ENA |
196 DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA,
197 lan966x, DEV_MAC_TAGS_CFG(port->chip_port));
198
199 /* Drop frames with multicast source address */
200 val = ANA_DROP_CFG_DROP_MC_SMAC_ENA_SET(1);
201 if (port->vlan_aware && !pvid)
202 /* If port is vlan-aware and tagged, drop untagged and priority
203 * tagged frames.
204 */
205 val |= ANA_DROP_CFG_DROP_UNTAGGED_ENA_SET(1) |
206 ANA_DROP_CFG_DROP_PRIO_S_TAGGED_ENA_SET(1) |
207 ANA_DROP_CFG_DROP_PRIO_C_TAGGED_ENA_SET(1);
208
209 lan_wr(val, lan966x, ANA_DROP_CFG(port->chip_port));
210
211 /* Egress configuration (REW_TAG_CFG): VLAN tag type to 8021Q */
212 val = REW_TAG_CFG_TAG_TPID_CFG_SET(0);
213 if (port->vlan_aware) {
214 if (port->vid)
215 /* Tag all frames except when VID == DEFAULT_VLAN */
216 val |= REW_TAG_CFG_TAG_CFG_SET(1);
217 else
218 val |= REW_TAG_CFG_TAG_CFG_SET(3);
219 }
220
221 /* Update only some bits in the register */
222 lan_rmw(val,
223 REW_TAG_CFG_TAG_TPID_CFG | REW_TAG_CFG_TAG_CFG,
224 lan966x, REW_TAG_CFG(port->chip_port));
225
226 /* Set default VLAN and tag type to 8021Q */
227 lan_rmw(REW_PORT_VLAN_CFG_PORT_TPID_SET(ETH_P_8021Q) |
228 REW_PORT_VLAN_CFG_PORT_VID_SET(port->vid),
229 REW_PORT_VLAN_CFG_PORT_TPID |
230 REW_PORT_VLAN_CFG_PORT_VID,
231 lan966x, REW_PORT_VLAN_CFG(port->chip_port));
232 }
233
lan966x_vlan_port_add_vlan(struct lan966x_port * port,u16 vid,bool pvid,bool untagged)234 void lan966x_vlan_port_add_vlan(struct lan966x_port *port,
235 u16 vid,
236 bool pvid,
237 bool untagged)
238 {
239 struct lan966x *lan966x = port->lan966x;
240
241 /* If the CPU(br) is already part of the vlan then add the fdb
242 * entries in MAC table to copy the frames to the CPU(br).
243 * If the CPU(br) is not part of the vlan then it would
244 * just drop the frames.
245 */
246 if (lan966x_vlan_cpu_member_cpu_vlan_mask(lan966x, vid)) {
247 lan966x_vlan_cpu_add_vlan_mask(lan966x, vid);
248 lan966x_fdb_write_entries(lan966x, vid);
249 lan966x_mdb_write_entries(lan966x, vid);
250 }
251
252 lan966x_vlan_port_set_vid(port, vid, pvid, untagged);
253 lan966x_vlan_port_add_vlan_mask(port, vid);
254 lan966x_vlan_port_apply(port);
255 }
256
lan966x_vlan_port_del_vlan(struct lan966x_port * port,u16 vid)257 void lan966x_vlan_port_del_vlan(struct lan966x_port *port, u16 vid)
258 {
259 struct lan966x *lan966x = port->lan966x;
260
261 lan966x_vlan_port_remove_vid(port, vid);
262 lan966x_vlan_port_del_vlan_mask(port, vid);
263 lan966x_vlan_port_apply(port);
264
265 /* In case there are no other ports in vlan then remove the CPU from
266 * that vlan but still keep it in the mask because it may be needed
267 * again then another port gets added in that vlan
268 */
269 if (!lan966x_vlan_port_any_vlan_mask(lan966x, vid)) {
270 lan966x_vlan_cpu_del_vlan_mask(lan966x, vid);
271 lan966x_fdb_erase_entries(lan966x, vid);
272 lan966x_mdb_erase_entries(lan966x, vid);
273 }
274 }
275
lan966x_vlan_cpu_add_vlan(struct lan966x * lan966x,u16 vid)276 void lan966x_vlan_cpu_add_vlan(struct lan966x *lan966x, u16 vid)
277 {
278 /* Add an entry in the MAC table for the CPU
279 * Add the CPU part of the vlan only if there is another port in that
280 * vlan otherwise all the broadcast frames in that vlan will go to CPU
281 * even if none of the ports are in the vlan and then the CPU will just
282 * need to discard these frames. It is required to store this
283 * information so when a front port is added then it would add also the
284 * CPU port.
285 */
286 if (lan966x_vlan_port_any_vlan_mask(lan966x, vid)) {
287 lan966x_vlan_cpu_add_vlan_mask(lan966x, vid);
288 lan966x_mdb_write_entries(lan966x, vid);
289 }
290
291 lan966x_vlan_cpu_add_cpu_vlan_mask(lan966x, vid);
292 lan966x_fdb_write_entries(lan966x, vid);
293 }
294
lan966x_vlan_cpu_del_vlan(struct lan966x * lan966x,u16 vid)295 void lan966x_vlan_cpu_del_vlan(struct lan966x *lan966x, u16 vid)
296 {
297 /* Remove the CPU part of the vlan */
298 lan966x_vlan_cpu_del_cpu_vlan_mask(lan966x, vid);
299 lan966x_vlan_cpu_del_vlan_mask(lan966x, vid);
300 lan966x_fdb_erase_entries(lan966x, vid);
301 lan966x_mdb_erase_entries(lan966x, vid);
302 }
303
lan966x_vlan_init(struct lan966x * lan966x)304 void lan966x_vlan_init(struct lan966x *lan966x)
305 {
306 u16 port, vid;
307
308 /* Clear VLAN table, by default all ports are members of all VLANS */
309 lan_rmw(ANA_VLANACCESS_VLAN_TBL_CMD_SET(VLANACCESS_CMD_INIT),
310 ANA_VLANACCESS_VLAN_TBL_CMD,
311 lan966x, ANA_VLANACCESS);
312 lan966x_vlan_wait_for_completion(lan966x);
313
314 for (vid = 1; vid < VLAN_N_VID; vid++) {
315 lan966x->vlan_mask[vid] = 0;
316 lan966x_vlan_set_mask(lan966x, vid);
317 }
318
319 /* Set all the ports + cpu to be part of HOST_PVID and UNAWARE_PVID */
320 lan966x->vlan_mask[HOST_PVID] =
321 GENMASK(lan966x->num_phys_ports - 1, 0) | BIT(CPU_PORT);
322 lan966x_vlan_set_mask(lan966x, HOST_PVID);
323
324 lan966x->vlan_mask[UNAWARE_PVID] =
325 GENMASK(lan966x->num_phys_ports - 1, 0) | BIT(CPU_PORT);
326 lan966x_vlan_set_mask(lan966x, UNAWARE_PVID);
327
328 lan966x_vlan_cpu_add_cpu_vlan_mask(lan966x, UNAWARE_PVID);
329
330 /* Configure the CPU port to be vlan aware */
331 lan_wr(ANA_VLAN_CFG_VLAN_VID_SET(0) |
332 ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) |
333 ANA_VLAN_CFG_VLAN_POP_CNT_SET(1),
334 lan966x, ANA_VLAN_CFG(CPU_PORT));
335
336 /* Set vlan ingress filter mask to all ports */
337 lan_wr(GENMASK(lan966x->num_phys_ports, 0),
338 lan966x, ANA_VLANMASK);
339
340 for (port = 0; port < lan966x->num_phys_ports; port++) {
341 lan_wr(0, lan966x, REW_PORT_VLAN_CFG(port));
342 lan_wr(0, lan966x, REW_TAG_CFG(port));
343 }
344 }
345