1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright 2019-2021 NXP |
3 | * |
4 | * This is an umbrella module for all network switches that are |
5 | * register-compatible with Ocelot and that perform I/O to their host CPU |
6 | * through an NPI (Node Processor Interface) Ethernet port. |
7 | */ |
8 | #include <uapi/linux/if_bridge.h> |
9 | #include <soc/mscc/ocelot_vcap.h> |
10 | #include <soc/mscc/ocelot_qsys.h> |
11 | #include <soc/mscc/ocelot_sys.h> |
12 | #include <soc/mscc/ocelot_dev.h> |
13 | #include <soc/mscc/ocelot_ana.h> |
14 | #include <soc/mscc/ocelot_ptp.h> |
15 | #include <soc/mscc/ocelot.h> |
16 | #include <linux/dsa/8021q.h> |
17 | #include <linux/dsa/ocelot.h> |
18 | #include <linux/platform_device.h> |
19 | #include <linux/ptp_classify.h> |
20 | #include <linux/module.h> |
21 | #include <linux/of_net.h> |
22 | #include <linux/pci.h> |
23 | #include <linux/of.h> |
24 | #include <net/pkt_sched.h> |
25 | #include <net/dsa.h> |
26 | #include "felix.h" |
27 | |
28 | /* Translate the DSA database API into the ocelot switch library API, |
29 | * which uses VID 0 for all ports that aren't part of a bridge, |
30 | * and expects the bridge_dev to be NULL in that case. |
31 | */ |
32 | static struct net_device *felix_classify_db(struct dsa_db db) |
33 | { |
34 | switch (db.type) { |
35 | case DSA_DB_PORT: |
36 | case DSA_DB_LAG: |
37 | return NULL; |
38 | case DSA_DB_BRIDGE: |
39 | return db.bridge.dev; |
40 | default: |
41 | return ERR_PTR(error: -EOPNOTSUPP); |
42 | } |
43 | } |
44 | |
45 | static int felix_cpu_port_for_conduit(struct dsa_switch *ds, |
46 | struct net_device *conduit) |
47 | { |
48 | struct ocelot *ocelot = ds->priv; |
49 | struct dsa_port *cpu_dp; |
50 | int lag; |
51 | |
52 | if (netif_is_lag_master(dev: conduit)) { |
53 | mutex_lock(&ocelot->fwd_domain_lock); |
54 | lag = ocelot_bond_get_id(ocelot, bond: conduit); |
55 | mutex_unlock(lock: &ocelot->fwd_domain_lock); |
56 | |
57 | return lag; |
58 | } |
59 | |
60 | cpu_dp = conduit->dsa_ptr; |
61 | return cpu_dp->index; |
62 | } |
63 | |
64 | /* Set up VCAP ES0 rules for pushing a tag_8021q VLAN towards the CPU such that |
65 | * the tagger can perform RX source port identification. |
66 | */ |
67 | static int felix_tag_8021q_vlan_add_rx(struct dsa_switch *ds, int port, |
68 | int upstream, u16 vid) |
69 | { |
70 | struct ocelot_vcap_filter *outer_tagging_rule; |
71 | struct ocelot *ocelot = ds->priv; |
72 | unsigned long cookie; |
73 | int key_length, err; |
74 | |
75 | key_length = ocelot->vcap[VCAP_ES0].keys[VCAP_ES0_IGR_PORT].length; |
76 | |
77 | outer_tagging_rule = kzalloc(size: sizeof(struct ocelot_vcap_filter), |
78 | GFP_KERNEL); |
79 | if (!outer_tagging_rule) |
80 | return -ENOMEM; |
81 | |
82 | cookie = OCELOT_VCAP_ES0_TAG_8021Q_RXVLAN(ocelot, port, upstream); |
83 | |
84 | outer_tagging_rule->key_type = OCELOT_VCAP_KEY_ANY; |
85 | outer_tagging_rule->prio = 1; |
86 | outer_tagging_rule->id.cookie = cookie; |
87 | outer_tagging_rule->id.tc_offload = false; |
88 | outer_tagging_rule->block_id = VCAP_ES0; |
89 | outer_tagging_rule->type = OCELOT_VCAP_FILTER_OFFLOAD; |
90 | outer_tagging_rule->lookup = 0; |
91 | outer_tagging_rule->ingress_port.value = port; |
92 | outer_tagging_rule->ingress_port.mask = GENMASK(key_length - 1, 0); |
93 | outer_tagging_rule->egress_port.value = upstream; |
94 | outer_tagging_rule->egress_port.mask = GENMASK(key_length - 1, 0); |
95 | outer_tagging_rule->action.push_outer_tag = OCELOT_ES0_TAG; |
96 | outer_tagging_rule->action.tag_a_tpid_sel = OCELOT_TAG_TPID_SEL_8021AD; |
97 | outer_tagging_rule->action.tag_a_vid_sel = 1; |
98 | outer_tagging_rule->action.vid_a_val = vid; |
99 | |
100 | err = ocelot_vcap_filter_add(ocelot, rule: outer_tagging_rule, NULL); |
101 | if (err) |
102 | kfree(objp: outer_tagging_rule); |
103 | |
104 | return err; |
105 | } |
106 | |
107 | static int felix_tag_8021q_vlan_del_rx(struct dsa_switch *ds, int port, |
108 | int upstream, u16 vid) |
109 | { |
110 | struct ocelot_vcap_filter *outer_tagging_rule; |
111 | struct ocelot_vcap_block *block_vcap_es0; |
112 | struct ocelot *ocelot = ds->priv; |
113 | unsigned long cookie; |
114 | |
115 | block_vcap_es0 = &ocelot->block[VCAP_ES0]; |
116 | cookie = OCELOT_VCAP_ES0_TAG_8021Q_RXVLAN(ocelot, port, upstream); |
117 | |
118 | outer_tagging_rule = ocelot_vcap_block_find_filter_by_id(block: block_vcap_es0, |
119 | cookie, tc_offload: false); |
120 | if (!outer_tagging_rule) |
121 | return -ENOENT; |
122 | |
123 | return ocelot_vcap_filter_del(ocelot, rule: outer_tagging_rule); |
124 | } |
125 | |
126 | /* Set up VCAP IS1 rules for stripping the tag_8021q VLAN on TX and VCAP IS2 |
127 | * rules for steering those tagged packets towards the correct destination port |
128 | */ |
129 | static int felix_tag_8021q_vlan_add_tx(struct dsa_switch *ds, int port, |
130 | u16 vid) |
131 | { |
132 | struct ocelot_vcap_filter *untagging_rule, *redirect_rule; |
133 | unsigned long cpu_ports = dsa_cpu_ports(ds); |
134 | struct ocelot *ocelot = ds->priv; |
135 | unsigned long cookie; |
136 | int err; |
137 | |
138 | untagging_rule = kzalloc(size: sizeof(struct ocelot_vcap_filter), GFP_KERNEL); |
139 | if (!untagging_rule) |
140 | return -ENOMEM; |
141 | |
142 | redirect_rule = kzalloc(size: sizeof(struct ocelot_vcap_filter), GFP_KERNEL); |
143 | if (!redirect_rule) { |
144 | kfree(objp: untagging_rule); |
145 | return -ENOMEM; |
146 | } |
147 | |
148 | cookie = OCELOT_VCAP_IS1_TAG_8021Q_TXVLAN(ocelot, port); |
149 | |
150 | untagging_rule->key_type = OCELOT_VCAP_KEY_ANY; |
151 | untagging_rule->ingress_port_mask = cpu_ports; |
152 | untagging_rule->vlan.vid.value = vid; |
153 | untagging_rule->vlan.vid.mask = VLAN_VID_MASK; |
154 | untagging_rule->prio = 1; |
155 | untagging_rule->id.cookie = cookie; |
156 | untagging_rule->id.tc_offload = false; |
157 | untagging_rule->block_id = VCAP_IS1; |
158 | untagging_rule->type = OCELOT_VCAP_FILTER_OFFLOAD; |
159 | untagging_rule->lookup = 0; |
160 | untagging_rule->action.vlan_pop_cnt_ena = true; |
161 | untagging_rule->action.vlan_pop_cnt = 1; |
162 | untagging_rule->action.pag_override_mask = 0xff; |
163 | untagging_rule->action.pag_val = port; |
164 | |
165 | err = ocelot_vcap_filter_add(ocelot, rule: untagging_rule, NULL); |
166 | if (err) { |
167 | kfree(objp: untagging_rule); |
168 | kfree(objp: redirect_rule); |
169 | return err; |
170 | } |
171 | |
172 | cookie = OCELOT_VCAP_IS2_TAG_8021Q_TXVLAN(ocelot, port); |
173 | |
174 | redirect_rule->key_type = OCELOT_VCAP_KEY_ANY; |
175 | redirect_rule->ingress_port_mask = cpu_ports; |
176 | redirect_rule->pag = port; |
177 | redirect_rule->prio = 1; |
178 | redirect_rule->id.cookie = cookie; |
179 | redirect_rule->id.tc_offload = false; |
180 | redirect_rule->block_id = VCAP_IS2; |
181 | redirect_rule->type = OCELOT_VCAP_FILTER_OFFLOAD; |
182 | redirect_rule->lookup = 0; |
183 | redirect_rule->action.mask_mode = OCELOT_MASK_MODE_REDIRECT; |
184 | redirect_rule->action.port_mask = BIT(port); |
185 | |
186 | err = ocelot_vcap_filter_add(ocelot, rule: redirect_rule, NULL); |
187 | if (err) { |
188 | ocelot_vcap_filter_del(ocelot, rule: untagging_rule); |
189 | kfree(objp: redirect_rule); |
190 | return err; |
191 | } |
192 | |
193 | return 0; |
194 | } |
195 | |
196 | static int felix_tag_8021q_vlan_del_tx(struct dsa_switch *ds, int port, u16 vid) |
197 | { |
198 | struct ocelot_vcap_filter *untagging_rule, *redirect_rule; |
199 | struct ocelot_vcap_block *block_vcap_is1; |
200 | struct ocelot_vcap_block *block_vcap_is2; |
201 | struct ocelot *ocelot = ds->priv; |
202 | unsigned long cookie; |
203 | int err; |
204 | |
205 | block_vcap_is1 = &ocelot->block[VCAP_IS1]; |
206 | block_vcap_is2 = &ocelot->block[VCAP_IS2]; |
207 | |
208 | cookie = OCELOT_VCAP_IS1_TAG_8021Q_TXVLAN(ocelot, port); |
209 | untagging_rule = ocelot_vcap_block_find_filter_by_id(block: block_vcap_is1, |
210 | cookie, tc_offload: false); |
211 | if (!untagging_rule) |
212 | return -ENOENT; |
213 | |
214 | err = ocelot_vcap_filter_del(ocelot, rule: untagging_rule); |
215 | if (err) |
216 | return err; |
217 | |
218 | cookie = OCELOT_VCAP_IS2_TAG_8021Q_TXVLAN(ocelot, port); |
219 | redirect_rule = ocelot_vcap_block_find_filter_by_id(block: block_vcap_is2, |
220 | cookie, tc_offload: false); |
221 | if (!redirect_rule) |
222 | return -ENOENT; |
223 | |
224 | return ocelot_vcap_filter_del(ocelot, rule: redirect_rule); |
225 | } |
226 | |
227 | static int felix_tag_8021q_vlan_add(struct dsa_switch *ds, int port, u16 vid, |
228 | u16 flags) |
229 | { |
230 | struct dsa_port *cpu_dp; |
231 | int err; |
232 | |
233 | /* tag_8021q.c assumes we are implementing this via port VLAN |
234 | * membership, which we aren't. So we don't need to add any VCAP filter |
235 | * for the CPU port. |
236 | */ |
237 | if (!dsa_is_user_port(ds, p: port)) |
238 | return 0; |
239 | |
240 | dsa_switch_for_each_cpu_port(cpu_dp, ds) { |
241 | err = felix_tag_8021q_vlan_add_rx(ds, port, upstream: cpu_dp->index, vid); |
242 | if (err) |
243 | return err; |
244 | } |
245 | |
246 | err = felix_tag_8021q_vlan_add_tx(ds, port, vid); |
247 | if (err) |
248 | goto add_tx_failed; |
249 | |
250 | return 0; |
251 | |
252 | add_tx_failed: |
253 | dsa_switch_for_each_cpu_port(cpu_dp, ds) |
254 | felix_tag_8021q_vlan_del_rx(ds, port, upstream: cpu_dp->index, vid); |
255 | |
256 | return err; |
257 | } |
258 | |
259 | static int felix_tag_8021q_vlan_del(struct dsa_switch *ds, int port, u16 vid) |
260 | { |
261 | struct dsa_port *cpu_dp; |
262 | int err; |
263 | |
264 | if (!dsa_is_user_port(ds, p: port)) |
265 | return 0; |
266 | |
267 | dsa_switch_for_each_cpu_port(cpu_dp, ds) { |
268 | err = felix_tag_8021q_vlan_del_rx(ds, port, upstream: cpu_dp->index, vid); |
269 | if (err) |
270 | return err; |
271 | } |
272 | |
273 | err = felix_tag_8021q_vlan_del_tx(ds, port, vid); |
274 | if (err) |
275 | goto del_tx_failed; |
276 | |
277 | return 0; |
278 | |
279 | del_tx_failed: |
280 | dsa_switch_for_each_cpu_port(cpu_dp, ds) |
281 | felix_tag_8021q_vlan_add_rx(ds, port, upstream: cpu_dp->index, vid); |
282 | |
283 | return err; |
284 | } |
285 | |
286 | static int felix_trap_get_cpu_port(struct dsa_switch *ds, |
287 | const struct ocelot_vcap_filter *trap) |
288 | { |
289 | struct dsa_port *dp; |
290 | int first_port; |
291 | |
292 | if (WARN_ON(!trap->ingress_port_mask)) |
293 | return -1; |
294 | |
295 | first_port = __ffs(trap->ingress_port_mask); |
296 | dp = dsa_to_port(ds, p: first_port); |
297 | |
298 | return dp->cpu_dp->index; |
299 | } |
300 | |
301 | /* On switches with no extraction IRQ wired, trapped packets need to be |
302 | * replicated over Ethernet as well, otherwise we'd get no notification of |
303 | * their arrival when using the ocelot-8021q tagging protocol. |
304 | */ |
305 | static int felix_update_trapping_destinations(struct dsa_switch *ds, |
306 | bool using_tag_8021q) |
307 | { |
308 | struct ocelot *ocelot = ds->priv; |
309 | struct felix *felix = ocelot_to_felix(ocelot); |
310 | struct ocelot_vcap_block *block_vcap_is2; |
311 | struct ocelot_vcap_filter *trap; |
312 | enum ocelot_mask_mode mask_mode; |
313 | unsigned long port_mask; |
314 | bool cpu_copy_ena; |
315 | int err; |
316 | |
317 | if (!felix->info->quirk_no_xtr_irq) |
318 | return 0; |
319 | |
320 | /* We are sure that "cpu" was found, otherwise |
321 | * dsa_tree_setup_default_cpu() would have failed earlier. |
322 | */ |
323 | block_vcap_is2 = &ocelot->block[VCAP_IS2]; |
324 | |
325 | /* Make sure all traps are set up for that destination */ |
326 | list_for_each_entry(trap, &block_vcap_is2->rules, list) { |
327 | if (!trap->is_trap) |
328 | continue; |
329 | |
330 | /* Figure out the current trapping destination */ |
331 | if (using_tag_8021q) { |
332 | /* Redirect to the tag_8021q CPU port. If timestamps |
333 | * are necessary, also copy trapped packets to the CPU |
334 | * port module. |
335 | */ |
336 | mask_mode = OCELOT_MASK_MODE_REDIRECT; |
337 | port_mask = BIT(felix_trap_get_cpu_port(ds, trap)); |
338 | cpu_copy_ena = !!trap->take_ts; |
339 | } else { |
340 | /* Trap packets only to the CPU port module, which is |
341 | * redirected to the NPI port (the DSA CPU port) |
342 | */ |
343 | mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; |
344 | port_mask = 0; |
345 | cpu_copy_ena = true; |
346 | } |
347 | |
348 | if (trap->action.mask_mode == mask_mode && |
349 | trap->action.port_mask == port_mask && |
350 | trap->action.cpu_copy_ena == cpu_copy_ena) |
351 | continue; |
352 | |
353 | trap->action.mask_mode = mask_mode; |
354 | trap->action.port_mask = port_mask; |
355 | trap->action.cpu_copy_ena = cpu_copy_ena; |
356 | |
357 | err = ocelot_vcap_filter_replace(ocelot, filter: trap); |
358 | if (err) |
359 | return err; |
360 | } |
361 | |
362 | return 0; |
363 | } |
364 | |
365 | /* The CPU port module is connected to the Node Processor Interface (NPI). This |
366 | * is the mode through which frames can be injected from and extracted to an |
367 | * external CPU, over Ethernet. In NXP SoCs, the "external CPU" is the ARM CPU |
368 | * running Linux, and this forms a DSA setup together with the enetc or fman |
369 | * DSA conduit. |
370 | */ |
371 | static void felix_npi_port_init(struct ocelot *ocelot, int port) |
372 | { |
373 | ocelot->npi = port; |
374 | |
375 | ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M | |
376 | QSYS_EXT_CPU_CFG_EXT_CPU_PORT(port), |
377 | QSYS_EXT_CPU_CFG); |
378 | |
379 | /* NPI port Injection/Extraction configuration */ |
380 | ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_XTR_HDR, |
381 | ocelot->npi_xtr_prefix); |
382 | ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_INJ_HDR, |
383 | ocelot->npi_inj_prefix); |
384 | |
385 | /* Disable transmission of pause frames */ |
386 | ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 0); |
387 | } |
388 | |
389 | static void felix_npi_port_deinit(struct ocelot *ocelot, int port) |
390 | { |
391 | /* Restore hardware defaults */ |
392 | int unused_port = ocelot->num_phys_ports + 2; |
393 | |
394 | ocelot->npi = -1; |
395 | |
396 | ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPU_PORT(unused_port), |
397 | QSYS_EXT_CPU_CFG); |
398 | |
399 | ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_XTR_HDR, |
400 | OCELOT_TAG_PREFIX_DISABLED); |
401 | ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_INJ_HDR, |
402 | OCELOT_TAG_PREFIX_DISABLED); |
403 | |
404 | /* Enable transmission of pause frames */ |
405 | ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 1); |
406 | } |
407 | |
408 | static int felix_tag_npi_setup(struct dsa_switch *ds) |
409 | { |
410 | struct dsa_port *dp, *first_cpu_dp = NULL; |
411 | struct ocelot *ocelot = ds->priv; |
412 | |
413 | dsa_switch_for_each_user_port(dp, ds) { |
414 | if (first_cpu_dp && dp->cpu_dp != first_cpu_dp) { |
415 | dev_err(ds->dev, "Multiple NPI ports not supported\n" ); |
416 | return -EINVAL; |
417 | } |
418 | |
419 | first_cpu_dp = dp->cpu_dp; |
420 | } |
421 | |
422 | if (!first_cpu_dp) |
423 | return -EINVAL; |
424 | |
425 | felix_npi_port_init(ocelot, port: first_cpu_dp->index); |
426 | |
427 | return 0; |
428 | } |
429 | |
430 | static void felix_tag_npi_teardown(struct dsa_switch *ds) |
431 | { |
432 | struct ocelot *ocelot = ds->priv; |
433 | |
434 | felix_npi_port_deinit(ocelot, port: ocelot->npi); |
435 | } |
436 | |
437 | static unsigned long felix_tag_npi_get_host_fwd_mask(struct dsa_switch *ds) |
438 | { |
439 | struct ocelot *ocelot = ds->priv; |
440 | |
441 | return BIT(ocelot->num_phys_ports); |
442 | } |
443 | |
444 | static int felix_tag_npi_change_conduit(struct dsa_switch *ds, int port, |
445 | struct net_device *conduit, |
446 | struct netlink_ext_ack *extack) |
447 | { |
448 | struct dsa_port *dp = dsa_to_port(ds, p: port), *other_dp; |
449 | struct ocelot *ocelot = ds->priv; |
450 | |
451 | if (netif_is_lag_master(dev: conduit)) { |
452 | NL_SET_ERR_MSG_MOD(extack, |
453 | "LAG DSA conduit only supported using ocelot-8021q" ); |
454 | return -EOPNOTSUPP; |
455 | } |
456 | |
457 | /* Changing the NPI port breaks user ports still assigned to the old |
458 | * one, so only allow it while they're down, and don't allow them to |
459 | * come back up until they're all changed to the new one. |
460 | */ |
461 | dsa_switch_for_each_user_port(other_dp, ds) { |
462 | struct net_device *user = other_dp->user; |
463 | |
464 | if (other_dp != dp && (user->flags & IFF_UP) && |
465 | dsa_port_to_conduit(dp: other_dp) != conduit) { |
466 | NL_SET_ERR_MSG_MOD(extack, |
467 | "Cannot change while old conduit still has users" ); |
468 | return -EOPNOTSUPP; |
469 | } |
470 | } |
471 | |
472 | felix_npi_port_deinit(ocelot, port: ocelot->npi); |
473 | felix_npi_port_init(ocelot, port: felix_cpu_port_for_conduit(ds, conduit)); |
474 | |
475 | return 0; |
476 | } |
477 | |
478 | /* Alternatively to using the NPI functionality, that same hardware MAC |
479 | * connected internally to the enetc or fman DSA conduit can be configured to |
480 | * use the software-defined tag_8021q frame format. As far as the hardware is |
481 | * concerned, it thinks it is a "dumb switch" - the queues of the CPU port |
482 | * module are now disconnected from it, but can still be accessed through |
483 | * register-based MMIO. |
484 | */ |
485 | static const struct felix_tag_proto_ops felix_tag_npi_proto_ops = { |
486 | .setup = felix_tag_npi_setup, |
487 | .teardown = felix_tag_npi_teardown, |
488 | .get_host_fwd_mask = felix_tag_npi_get_host_fwd_mask, |
489 | .change_conduit = felix_tag_npi_change_conduit, |
490 | }; |
491 | |
492 | static int felix_tag_8021q_setup(struct dsa_switch *ds) |
493 | { |
494 | struct ocelot *ocelot = ds->priv; |
495 | struct dsa_port *dp; |
496 | int err; |
497 | |
498 | err = dsa_tag_8021q_register(ds, htons(ETH_P_8021AD)); |
499 | if (err) |
500 | return err; |
501 | |
502 | dsa_switch_for_each_cpu_port(dp, ds) |
503 | ocelot_port_setup_dsa_8021q_cpu(ocelot, cpu: dp->index); |
504 | |
505 | dsa_switch_for_each_user_port(dp, ds) |
506 | ocelot_port_assign_dsa_8021q_cpu(ocelot, port: dp->index, |
507 | cpu: dp->cpu_dp->index); |
508 | |
509 | dsa_switch_for_each_available_port(dp, ds) |
510 | /* This overwrites ocelot_init(): |
511 | * Do not forward BPDU frames to the CPU port module, |
512 | * for 2 reasons: |
513 | * - When these packets are injected from the tag_8021q |
514 | * CPU port, we want them to go out, not loop back |
515 | * into the system. |
516 | * - STP traffic ingressing on a user port should go to |
517 | * the tag_8021q CPU port, not to the hardware CPU |
518 | * port module. |
519 | */ |
520 | ocelot_write_gix(ocelot, |
521 | ANA_PORT_CPU_FWD_BPDU_CFG_BPDU_REDIR_ENA(0), |
522 | ANA_PORT_CPU_FWD_BPDU_CFG, dp->index); |
523 | |
524 | /* The ownership of the CPU port module's queues might have just been |
525 | * transferred to the tag_8021q tagger from the NPI-based tagger. |
526 | * So there might still be all sorts of crap in the queues. On the |
527 | * other hand, the MMIO-based matching of PTP frames is very brittle, |
528 | * so we need to be careful that there are no extra frames to be |
529 | * dequeued over MMIO, since we would never know to discard them. |
530 | */ |
531 | ocelot_drain_cpu_queue(ocelot, grp: 0); |
532 | |
533 | return 0; |
534 | } |
535 | |
536 | static void felix_tag_8021q_teardown(struct dsa_switch *ds) |
537 | { |
538 | struct ocelot *ocelot = ds->priv; |
539 | struct dsa_port *dp; |
540 | |
541 | dsa_switch_for_each_available_port(dp, ds) |
542 | /* Restore the logic from ocelot_init: |
543 | * do not forward BPDU frames to the front ports. |
544 | */ |
545 | ocelot_write_gix(ocelot, |
546 | ANA_PORT_CPU_FWD_BPDU_CFG_BPDU_REDIR_ENA(0xffff), |
547 | ANA_PORT_CPU_FWD_BPDU_CFG, |
548 | dp->index); |
549 | |
550 | dsa_switch_for_each_user_port(dp, ds) |
551 | ocelot_port_unassign_dsa_8021q_cpu(ocelot, port: dp->index); |
552 | |
553 | dsa_switch_for_each_cpu_port(dp, ds) |
554 | ocelot_port_teardown_dsa_8021q_cpu(ocelot, cpu: dp->index); |
555 | |
556 | dsa_tag_8021q_unregister(ds); |
557 | } |
558 | |
559 | static unsigned long felix_tag_8021q_get_host_fwd_mask(struct dsa_switch *ds) |
560 | { |
561 | return dsa_cpu_ports(ds); |
562 | } |
563 | |
564 | static int felix_tag_8021q_change_conduit(struct dsa_switch *ds, int port, |
565 | struct net_device *conduit, |
566 | struct netlink_ext_ack *extack) |
567 | { |
568 | int cpu = felix_cpu_port_for_conduit(ds, conduit); |
569 | struct ocelot *ocelot = ds->priv; |
570 | |
571 | ocelot_port_unassign_dsa_8021q_cpu(ocelot, port); |
572 | ocelot_port_assign_dsa_8021q_cpu(ocelot, port, cpu); |
573 | |
574 | return felix_update_trapping_destinations(ds, using_tag_8021q: true); |
575 | } |
576 | |
577 | static const struct felix_tag_proto_ops felix_tag_8021q_proto_ops = { |
578 | .setup = felix_tag_8021q_setup, |
579 | .teardown = felix_tag_8021q_teardown, |
580 | .get_host_fwd_mask = felix_tag_8021q_get_host_fwd_mask, |
581 | .change_conduit = felix_tag_8021q_change_conduit, |
582 | }; |
583 | |
584 | static void felix_set_host_flood(struct dsa_switch *ds, unsigned long mask, |
585 | bool uc, bool mc, bool bc) |
586 | { |
587 | struct ocelot *ocelot = ds->priv; |
588 | unsigned long val; |
589 | |
590 | val = uc ? mask : 0; |
591 | ocelot_rmw_rix(ocelot, val, mask, ANA_PGID_PGID, PGID_UC); |
592 | |
593 | val = mc ? mask : 0; |
594 | ocelot_rmw_rix(ocelot, val, mask, ANA_PGID_PGID, PGID_MC); |
595 | ocelot_rmw_rix(ocelot, val, mask, ANA_PGID_PGID, PGID_MCIPV4); |
596 | ocelot_rmw_rix(ocelot, val, mask, ANA_PGID_PGID, PGID_MCIPV6); |
597 | |
598 | val = bc ? mask : 0; |
599 | ocelot_rmw_rix(ocelot, val, mask, ANA_PGID_PGID, PGID_BC); |
600 | } |
601 | |
602 | static void |
603 | felix_migrate_host_flood(struct dsa_switch *ds, |
604 | const struct felix_tag_proto_ops *proto_ops, |
605 | const struct felix_tag_proto_ops *old_proto_ops) |
606 | { |
607 | struct ocelot *ocelot = ds->priv; |
608 | struct felix *felix = ocelot_to_felix(ocelot); |
609 | unsigned long mask; |
610 | |
611 | if (old_proto_ops) { |
612 | mask = old_proto_ops->get_host_fwd_mask(ds); |
613 | felix_set_host_flood(ds, mask, uc: false, mc: false, bc: false); |
614 | } |
615 | |
616 | mask = proto_ops->get_host_fwd_mask(ds); |
617 | felix_set_host_flood(ds, mask, uc: !!felix->host_flood_uc_mask, |
618 | mc: !!felix->host_flood_mc_mask, bc: true); |
619 | } |
620 | |
621 | static int felix_migrate_mdbs(struct dsa_switch *ds, |
622 | const struct felix_tag_proto_ops *proto_ops, |
623 | const struct felix_tag_proto_ops *old_proto_ops) |
624 | { |
625 | struct ocelot *ocelot = ds->priv; |
626 | unsigned long from, to; |
627 | |
628 | if (!old_proto_ops) |
629 | return 0; |
630 | |
631 | from = old_proto_ops->get_host_fwd_mask(ds); |
632 | to = proto_ops->get_host_fwd_mask(ds); |
633 | |
634 | return ocelot_migrate_mdbs(ocelot, from_mask: from, to_mask: to); |
635 | } |
636 | |
637 | /* Configure the shared hardware resources for a transition between |
638 | * @old_proto_ops and @proto_ops. |
639 | * Manual migration is needed because as far as DSA is concerned, no change of |
640 | * the CPU port is taking place here, just of the tagging protocol. |
641 | */ |
642 | static int |
643 | felix_tag_proto_setup_shared(struct dsa_switch *ds, |
644 | const struct felix_tag_proto_ops *proto_ops, |
645 | const struct felix_tag_proto_ops *old_proto_ops) |
646 | { |
647 | bool using_tag_8021q = (proto_ops == &felix_tag_8021q_proto_ops); |
648 | int err; |
649 | |
650 | err = felix_migrate_mdbs(ds, proto_ops, old_proto_ops); |
651 | if (err) |
652 | return err; |
653 | |
654 | felix_update_trapping_destinations(ds, using_tag_8021q); |
655 | |
656 | felix_migrate_host_flood(ds, proto_ops, old_proto_ops); |
657 | |
658 | return 0; |
659 | } |
660 | |
661 | /* This always leaves the switch in a consistent state, because although the |
662 | * tag_8021q setup can fail, the NPI setup can't. So either the change is made, |
663 | * or the restoration is guaranteed to work. |
664 | */ |
665 | static int felix_change_tag_protocol(struct dsa_switch *ds, |
666 | enum dsa_tag_protocol proto) |
667 | { |
668 | const struct felix_tag_proto_ops *old_proto_ops, *proto_ops; |
669 | struct ocelot *ocelot = ds->priv; |
670 | struct felix *felix = ocelot_to_felix(ocelot); |
671 | int err; |
672 | |
673 | switch (proto) { |
674 | case DSA_TAG_PROTO_SEVILLE: |
675 | case DSA_TAG_PROTO_OCELOT: |
676 | proto_ops = &felix_tag_npi_proto_ops; |
677 | break; |
678 | case DSA_TAG_PROTO_OCELOT_8021Q: |
679 | proto_ops = &felix_tag_8021q_proto_ops; |
680 | break; |
681 | default: |
682 | return -EPROTONOSUPPORT; |
683 | } |
684 | |
685 | old_proto_ops = felix->tag_proto_ops; |
686 | |
687 | if (proto_ops == old_proto_ops) |
688 | return 0; |
689 | |
690 | err = proto_ops->setup(ds); |
691 | if (err) |
692 | goto setup_failed; |
693 | |
694 | err = felix_tag_proto_setup_shared(ds, proto_ops, old_proto_ops); |
695 | if (err) |
696 | goto setup_shared_failed; |
697 | |
698 | if (old_proto_ops) |
699 | old_proto_ops->teardown(ds); |
700 | |
701 | felix->tag_proto_ops = proto_ops; |
702 | felix->tag_proto = proto; |
703 | |
704 | return 0; |
705 | |
706 | setup_shared_failed: |
707 | proto_ops->teardown(ds); |
708 | setup_failed: |
709 | return err; |
710 | } |
711 | |
712 | static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds, |
713 | int port, |
714 | enum dsa_tag_protocol mp) |
715 | { |
716 | struct ocelot *ocelot = ds->priv; |
717 | struct felix *felix = ocelot_to_felix(ocelot); |
718 | |
719 | return felix->tag_proto; |
720 | } |
721 | |
722 | static void felix_port_set_host_flood(struct dsa_switch *ds, int port, |
723 | bool uc, bool mc) |
724 | { |
725 | struct ocelot *ocelot = ds->priv; |
726 | struct felix *felix = ocelot_to_felix(ocelot); |
727 | unsigned long mask; |
728 | |
729 | if (uc) |
730 | felix->host_flood_uc_mask |= BIT(port); |
731 | else |
732 | felix->host_flood_uc_mask &= ~BIT(port); |
733 | |
734 | if (mc) |
735 | felix->host_flood_mc_mask |= BIT(port); |
736 | else |
737 | felix->host_flood_mc_mask &= ~BIT(port); |
738 | |
739 | mask = felix->tag_proto_ops->get_host_fwd_mask(ds); |
740 | felix_set_host_flood(ds, mask, uc: !!felix->host_flood_uc_mask, |
741 | mc: !!felix->host_flood_mc_mask, bc: true); |
742 | } |
743 | |
744 | static int felix_port_change_conduit(struct dsa_switch *ds, int port, |
745 | struct net_device *conduit, |
746 | struct netlink_ext_ack *extack) |
747 | { |
748 | struct ocelot *ocelot = ds->priv; |
749 | struct felix *felix = ocelot_to_felix(ocelot); |
750 | |
751 | return felix->tag_proto_ops->change_conduit(ds, port, conduit, extack); |
752 | } |
753 | |
754 | static int felix_set_ageing_time(struct dsa_switch *ds, |
755 | unsigned int ageing_time) |
756 | { |
757 | struct ocelot *ocelot = ds->priv; |
758 | |
759 | ocelot_set_ageing_time(ocelot, msecs: ageing_time); |
760 | |
761 | return 0; |
762 | } |
763 | |
764 | static void felix_port_fast_age(struct dsa_switch *ds, int port) |
765 | { |
766 | struct ocelot *ocelot = ds->priv; |
767 | int err; |
768 | |
769 | err = ocelot_mact_flush(ocelot, port); |
770 | if (err) |
771 | dev_err(ds->dev, "Flushing MAC table on port %d returned %pe\n" , |
772 | port, ERR_PTR(err)); |
773 | } |
774 | |
775 | static int felix_fdb_dump(struct dsa_switch *ds, int port, |
776 | dsa_fdb_dump_cb_t *cb, void *data) |
777 | { |
778 | struct ocelot *ocelot = ds->priv; |
779 | |
780 | return ocelot_fdb_dump(ocelot, port, cb, data); |
781 | } |
782 | |
783 | static int felix_fdb_add(struct dsa_switch *ds, int port, |
784 | const unsigned char *addr, u16 vid, |
785 | struct dsa_db db) |
786 | { |
787 | struct net_device *bridge_dev = felix_classify_db(db); |
788 | struct dsa_port *dp = dsa_to_port(ds, p: port); |
789 | struct ocelot *ocelot = ds->priv; |
790 | |
791 | if (IS_ERR(ptr: bridge_dev)) |
792 | return PTR_ERR(ptr: bridge_dev); |
793 | |
794 | if (dsa_port_is_cpu(port: dp) && !bridge_dev && |
795 | dsa_fdb_present_in_other_db(ds, port, addr, vid, db)) |
796 | return 0; |
797 | |
798 | if (dsa_port_is_cpu(port: dp)) |
799 | port = PGID_CPU; |
800 | |
801 | return ocelot_fdb_add(ocelot, port, addr, vid, bridge: bridge_dev); |
802 | } |
803 | |
804 | static int felix_fdb_del(struct dsa_switch *ds, int port, |
805 | const unsigned char *addr, u16 vid, |
806 | struct dsa_db db) |
807 | { |
808 | struct net_device *bridge_dev = felix_classify_db(db); |
809 | struct dsa_port *dp = dsa_to_port(ds, p: port); |
810 | struct ocelot *ocelot = ds->priv; |
811 | |
812 | if (IS_ERR(ptr: bridge_dev)) |
813 | return PTR_ERR(ptr: bridge_dev); |
814 | |
815 | if (dsa_port_is_cpu(port: dp) && !bridge_dev && |
816 | dsa_fdb_present_in_other_db(ds, port, addr, vid, db)) |
817 | return 0; |
818 | |
819 | if (dsa_port_is_cpu(port: dp)) |
820 | port = PGID_CPU; |
821 | |
822 | return ocelot_fdb_del(ocelot, port, addr, vid, bridge: bridge_dev); |
823 | } |
824 | |
825 | static int felix_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag lag, |
826 | const unsigned char *addr, u16 vid, |
827 | struct dsa_db db) |
828 | { |
829 | struct net_device *bridge_dev = felix_classify_db(db); |
830 | struct ocelot *ocelot = ds->priv; |
831 | |
832 | if (IS_ERR(ptr: bridge_dev)) |
833 | return PTR_ERR(ptr: bridge_dev); |
834 | |
835 | return ocelot_lag_fdb_add(ocelot, bond: lag.dev, addr, vid, bridge: bridge_dev); |
836 | } |
837 | |
838 | static int felix_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag lag, |
839 | const unsigned char *addr, u16 vid, |
840 | struct dsa_db db) |
841 | { |
842 | struct net_device *bridge_dev = felix_classify_db(db); |
843 | struct ocelot *ocelot = ds->priv; |
844 | |
845 | if (IS_ERR(ptr: bridge_dev)) |
846 | return PTR_ERR(ptr: bridge_dev); |
847 | |
848 | return ocelot_lag_fdb_del(ocelot, bond: lag.dev, addr, vid, bridge: bridge_dev); |
849 | } |
850 | |
851 | static int felix_mdb_add(struct dsa_switch *ds, int port, |
852 | const struct switchdev_obj_port_mdb *mdb, |
853 | struct dsa_db db) |
854 | { |
855 | struct net_device *bridge_dev = felix_classify_db(db); |
856 | struct ocelot *ocelot = ds->priv; |
857 | |
858 | if (IS_ERR(ptr: bridge_dev)) |
859 | return PTR_ERR(ptr: bridge_dev); |
860 | |
861 | if (dsa_is_cpu_port(ds, p: port) && !bridge_dev && |
862 | dsa_mdb_present_in_other_db(ds, port, mdb, db)) |
863 | return 0; |
864 | |
865 | if (port == ocelot->npi) |
866 | port = ocelot->num_phys_ports; |
867 | |
868 | return ocelot_port_mdb_add(ocelot, port, mdb, bridge: bridge_dev); |
869 | } |
870 | |
871 | static int felix_mdb_del(struct dsa_switch *ds, int port, |
872 | const struct switchdev_obj_port_mdb *mdb, |
873 | struct dsa_db db) |
874 | { |
875 | struct net_device *bridge_dev = felix_classify_db(db); |
876 | struct ocelot *ocelot = ds->priv; |
877 | |
878 | if (IS_ERR(ptr: bridge_dev)) |
879 | return PTR_ERR(ptr: bridge_dev); |
880 | |
881 | if (dsa_is_cpu_port(ds, p: port) && !bridge_dev && |
882 | dsa_mdb_present_in_other_db(ds, port, mdb, db)) |
883 | return 0; |
884 | |
885 | if (port == ocelot->npi) |
886 | port = ocelot->num_phys_ports; |
887 | |
888 | return ocelot_port_mdb_del(ocelot, port, mdb, bridge: bridge_dev); |
889 | } |
890 | |
891 | static void felix_bridge_stp_state_set(struct dsa_switch *ds, int port, |
892 | u8 state) |
893 | { |
894 | struct ocelot *ocelot = ds->priv; |
895 | |
896 | return ocelot_bridge_stp_state_set(ocelot, port, state); |
897 | } |
898 | |
899 | static int felix_pre_bridge_flags(struct dsa_switch *ds, int port, |
900 | struct switchdev_brport_flags val, |
901 | struct netlink_ext_ack *extack) |
902 | { |
903 | struct ocelot *ocelot = ds->priv; |
904 | |
905 | return ocelot_port_pre_bridge_flags(ocelot, port, val); |
906 | } |
907 | |
908 | static int felix_bridge_flags(struct dsa_switch *ds, int port, |
909 | struct switchdev_brport_flags val, |
910 | struct netlink_ext_ack *extack) |
911 | { |
912 | struct ocelot *ocelot = ds->priv; |
913 | |
914 | if (port == ocelot->npi) |
915 | port = ocelot->num_phys_ports; |
916 | |
917 | ocelot_port_bridge_flags(ocelot, port, val); |
918 | |
919 | return 0; |
920 | } |
921 | |
922 | static int felix_bridge_join(struct dsa_switch *ds, int port, |
923 | struct dsa_bridge bridge, bool *tx_fwd_offload, |
924 | struct netlink_ext_ack *extack) |
925 | { |
926 | struct ocelot *ocelot = ds->priv; |
927 | |
928 | return ocelot_port_bridge_join(ocelot, port, bridge: bridge.dev, bridge_num: bridge.num, |
929 | extack); |
930 | } |
931 | |
932 | static void felix_bridge_leave(struct dsa_switch *ds, int port, |
933 | struct dsa_bridge bridge) |
934 | { |
935 | struct ocelot *ocelot = ds->priv; |
936 | |
937 | ocelot_port_bridge_leave(ocelot, port, bridge: bridge.dev); |
938 | } |
939 | |
940 | static int felix_lag_join(struct dsa_switch *ds, int port, |
941 | struct dsa_lag lag, |
942 | struct netdev_lag_upper_info *info, |
943 | struct netlink_ext_ack *extack) |
944 | { |
945 | struct ocelot *ocelot = ds->priv; |
946 | int err; |
947 | |
948 | err = ocelot_port_lag_join(ocelot, port, bond: lag.dev, info, extack); |
949 | if (err) |
950 | return err; |
951 | |
952 | /* Update the logical LAG port that serves as tag_8021q CPU port */ |
953 | if (!dsa_is_cpu_port(ds, p: port)) |
954 | return 0; |
955 | |
956 | return felix_port_change_conduit(ds, port, conduit: lag.dev, extack); |
957 | } |
958 | |
959 | static int felix_lag_leave(struct dsa_switch *ds, int port, |
960 | struct dsa_lag lag) |
961 | { |
962 | struct ocelot *ocelot = ds->priv; |
963 | |
964 | ocelot_port_lag_leave(ocelot, port, bond: lag.dev); |
965 | |
966 | /* Update the logical LAG port that serves as tag_8021q CPU port */ |
967 | if (!dsa_is_cpu_port(ds, p: port)) |
968 | return 0; |
969 | |
970 | return felix_port_change_conduit(ds, port, conduit: lag.dev, NULL); |
971 | } |
972 | |
973 | static int felix_lag_change(struct dsa_switch *ds, int port) |
974 | { |
975 | struct dsa_port *dp = dsa_to_port(ds, p: port); |
976 | struct ocelot *ocelot = ds->priv; |
977 | |
978 | ocelot_port_lag_change(ocelot, port, lag_tx_active: dp->lag_tx_enabled); |
979 | |
980 | return 0; |
981 | } |
982 | |
983 | static int felix_vlan_prepare(struct dsa_switch *ds, int port, |
984 | const struct switchdev_obj_port_vlan *vlan, |
985 | struct netlink_ext_ack *extack) |
986 | { |
987 | struct ocelot *ocelot = ds->priv; |
988 | u16 flags = vlan->flags; |
989 | |
990 | /* Ocelot switches copy frames as-is to the CPU, so the flags: |
991 | * egress-untagged or not, pvid or not, make no difference. This |
992 | * behavior is already better than what DSA just tries to approximate |
993 | * when it installs the VLAN with the same flags on the CPU port. |
994 | * Just accept any configuration, and don't let ocelot deny installing |
995 | * multiple native VLANs on the NPI port, because the switch doesn't |
996 | * look at the port tag settings towards the NPI interface anyway. |
997 | */ |
998 | if (port == ocelot->npi) |
999 | return 0; |
1000 | |
1001 | return ocelot_vlan_prepare(ocelot, port, vid: vlan->vid, |
1002 | pvid: flags & BRIDGE_VLAN_INFO_PVID, |
1003 | untagged: flags & BRIDGE_VLAN_INFO_UNTAGGED, |
1004 | extack); |
1005 | } |
1006 | |
1007 | static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, |
1008 | struct netlink_ext_ack *extack) |
1009 | { |
1010 | struct ocelot *ocelot = ds->priv; |
1011 | |
1012 | return ocelot_port_vlan_filtering(ocelot, port, enabled, extack); |
1013 | } |
1014 | |
1015 | static int felix_vlan_add(struct dsa_switch *ds, int port, |
1016 | const struct switchdev_obj_port_vlan *vlan, |
1017 | struct netlink_ext_ack *extack) |
1018 | { |
1019 | struct ocelot *ocelot = ds->priv; |
1020 | u16 flags = vlan->flags; |
1021 | int err; |
1022 | |
1023 | err = felix_vlan_prepare(ds, port, vlan, extack); |
1024 | if (err) |
1025 | return err; |
1026 | |
1027 | return ocelot_vlan_add(ocelot, port, vid: vlan->vid, |
1028 | pvid: flags & BRIDGE_VLAN_INFO_PVID, |
1029 | untagged: flags & BRIDGE_VLAN_INFO_UNTAGGED); |
1030 | } |
1031 | |
1032 | static int felix_vlan_del(struct dsa_switch *ds, int port, |
1033 | const struct switchdev_obj_port_vlan *vlan) |
1034 | { |
1035 | struct ocelot *ocelot = ds->priv; |
1036 | |
1037 | return ocelot_vlan_del(ocelot, port, vid: vlan->vid); |
1038 | } |
1039 | |
1040 | static void felix_phylink_get_caps(struct dsa_switch *ds, int port, |
1041 | struct phylink_config *config) |
1042 | { |
1043 | struct ocelot *ocelot = ds->priv; |
1044 | |
1045 | config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | |
1046 | MAC_10 | MAC_100 | MAC_1000FD | |
1047 | MAC_2500FD; |
1048 | |
1049 | __set_bit(ocelot->ports[port]->phy_mode, |
1050 | config->supported_interfaces); |
1051 | } |
1052 | |
1053 | static void felix_phylink_mac_config(struct dsa_switch *ds, int port, |
1054 | unsigned int mode, |
1055 | const struct phylink_link_state *state) |
1056 | { |
1057 | struct ocelot *ocelot = ds->priv; |
1058 | struct felix *felix = ocelot_to_felix(ocelot); |
1059 | |
1060 | if (felix->info->phylink_mac_config) |
1061 | felix->info->phylink_mac_config(ocelot, port, mode, state); |
1062 | } |
1063 | |
1064 | static struct phylink_pcs *felix_phylink_mac_select_pcs(struct dsa_switch *ds, |
1065 | int port, |
1066 | phy_interface_t iface) |
1067 | { |
1068 | struct ocelot *ocelot = ds->priv; |
1069 | struct felix *felix = ocelot_to_felix(ocelot); |
1070 | struct phylink_pcs *pcs = NULL; |
1071 | |
1072 | if (felix->pcs && felix->pcs[port]) |
1073 | pcs = felix->pcs[port]; |
1074 | |
1075 | return pcs; |
1076 | } |
1077 | |
1078 | static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port, |
1079 | unsigned int link_an_mode, |
1080 | phy_interface_t interface) |
1081 | { |
1082 | struct ocelot *ocelot = ds->priv; |
1083 | struct felix *felix; |
1084 | |
1085 | felix = ocelot_to_felix(ocelot); |
1086 | |
1087 | ocelot_phylink_mac_link_down(ocelot, port, link_an_mode, interface, |
1088 | quirks: felix->info->quirks); |
1089 | } |
1090 | |
1091 | static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port, |
1092 | unsigned int link_an_mode, |
1093 | phy_interface_t interface, |
1094 | struct phy_device *phydev, |
1095 | int speed, int duplex, |
1096 | bool tx_pause, bool rx_pause) |
1097 | { |
1098 | struct ocelot *ocelot = ds->priv; |
1099 | struct felix *felix = ocelot_to_felix(ocelot); |
1100 | |
1101 | ocelot_phylink_mac_link_up(ocelot, port, phydev, link_an_mode, |
1102 | interface, speed, duplex, tx_pause, rx_pause, |
1103 | quirks: felix->info->quirks); |
1104 | |
1105 | if (felix->info->port_sched_speed_set) |
1106 | felix->info->port_sched_speed_set(ocelot, port, speed); |
1107 | } |
1108 | |
1109 | static int felix_port_enable(struct dsa_switch *ds, int port, |
1110 | struct phy_device *phydev) |
1111 | { |
1112 | struct dsa_port *dp = dsa_to_port(ds, p: port); |
1113 | struct ocelot *ocelot = ds->priv; |
1114 | |
1115 | if (!dsa_port_is_user(dp)) |
1116 | return 0; |
1117 | |
1118 | if (ocelot->npi >= 0) { |
1119 | struct net_device *conduit = dsa_port_to_conduit(dp); |
1120 | |
1121 | if (felix_cpu_port_for_conduit(ds, conduit) != ocelot->npi) { |
1122 | dev_err(ds->dev, "Multiple conduits are not allowed\n" ); |
1123 | return -EINVAL; |
1124 | } |
1125 | } |
1126 | |
1127 | return 0; |
1128 | } |
1129 | |
1130 | static void felix_port_qos_map_init(struct ocelot *ocelot, int port) |
1131 | { |
1132 | int i; |
1133 | |
1134 | ocelot_rmw_gix(ocelot, |
1135 | ANA_PORT_QOS_CFG_QOS_PCP_ENA, |
1136 | ANA_PORT_QOS_CFG_QOS_PCP_ENA, |
1137 | ANA_PORT_QOS_CFG, |
1138 | port); |
1139 | |
1140 | for (i = 0; i < OCELOT_NUM_TC * 2; i++) { |
1141 | ocelot_rmw_ix(ocelot, |
1142 | (ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL & i) | |
1143 | ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL(i), |
1144 | ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL | |
1145 | ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL_M, |
1146 | ANA_PORT_PCP_DEI_MAP, |
1147 | port, i); |
1148 | } |
1149 | } |
1150 | |
1151 | static void felix_get_stats64(struct dsa_switch *ds, int port, |
1152 | struct rtnl_link_stats64 *stats) |
1153 | { |
1154 | struct ocelot *ocelot = ds->priv; |
1155 | |
1156 | ocelot_port_get_stats64(ocelot, port, stats); |
1157 | } |
1158 | |
1159 | static void felix_get_pause_stats(struct dsa_switch *ds, int port, |
1160 | struct ethtool_pause_stats *pause_stats) |
1161 | { |
1162 | struct ocelot *ocelot = ds->priv; |
1163 | |
1164 | ocelot_port_get_pause_stats(ocelot, port, pause_stats); |
1165 | } |
1166 | |
1167 | static void felix_get_rmon_stats(struct dsa_switch *ds, int port, |
1168 | struct ethtool_rmon_stats *rmon_stats, |
1169 | const struct ethtool_rmon_hist_range **ranges) |
1170 | { |
1171 | struct ocelot *ocelot = ds->priv; |
1172 | |
1173 | ocelot_port_get_rmon_stats(ocelot, port, rmon_stats, ranges); |
1174 | } |
1175 | |
1176 | static void felix_get_eth_ctrl_stats(struct dsa_switch *ds, int port, |
1177 | struct ethtool_eth_ctrl_stats *ctrl_stats) |
1178 | { |
1179 | struct ocelot *ocelot = ds->priv; |
1180 | |
1181 | ocelot_port_get_eth_ctrl_stats(ocelot, port, ctrl_stats); |
1182 | } |
1183 | |
1184 | static void felix_get_eth_mac_stats(struct dsa_switch *ds, int port, |
1185 | struct ethtool_eth_mac_stats *mac_stats) |
1186 | { |
1187 | struct ocelot *ocelot = ds->priv; |
1188 | |
1189 | ocelot_port_get_eth_mac_stats(ocelot, port, mac_stats); |
1190 | } |
1191 | |
1192 | static void felix_get_eth_phy_stats(struct dsa_switch *ds, int port, |
1193 | struct ethtool_eth_phy_stats *phy_stats) |
1194 | { |
1195 | struct ocelot *ocelot = ds->priv; |
1196 | |
1197 | ocelot_port_get_eth_phy_stats(ocelot, port, phy_stats); |
1198 | } |
1199 | |
1200 | static void felix_get_strings(struct dsa_switch *ds, int port, |
1201 | u32 stringset, u8 *data) |
1202 | { |
1203 | struct ocelot *ocelot = ds->priv; |
1204 | |
1205 | return ocelot_get_strings(ocelot, port, sset: stringset, data); |
1206 | } |
1207 | |
1208 | static void felix_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data) |
1209 | { |
1210 | struct ocelot *ocelot = ds->priv; |
1211 | |
1212 | ocelot_get_ethtool_stats(ocelot, port, data); |
1213 | } |
1214 | |
1215 | static int felix_get_sset_count(struct dsa_switch *ds, int port, int sset) |
1216 | { |
1217 | struct ocelot *ocelot = ds->priv; |
1218 | |
1219 | return ocelot_get_sset_count(ocelot, port, sset); |
1220 | } |
1221 | |
1222 | static int felix_get_ts_info(struct dsa_switch *ds, int port, |
1223 | struct ethtool_ts_info *info) |
1224 | { |
1225 | struct ocelot *ocelot = ds->priv; |
1226 | |
1227 | return ocelot_get_ts_info(ocelot, port, info); |
1228 | } |
1229 | |
1230 | static const u32 felix_phy_match_table[PHY_INTERFACE_MODE_MAX] = { |
1231 | [PHY_INTERFACE_MODE_INTERNAL] = OCELOT_PORT_MODE_INTERNAL, |
1232 | [PHY_INTERFACE_MODE_SGMII] = OCELOT_PORT_MODE_SGMII, |
1233 | [PHY_INTERFACE_MODE_QSGMII] = OCELOT_PORT_MODE_QSGMII, |
1234 | [PHY_INTERFACE_MODE_USXGMII] = OCELOT_PORT_MODE_USXGMII, |
1235 | [PHY_INTERFACE_MODE_1000BASEX] = OCELOT_PORT_MODE_1000BASEX, |
1236 | [PHY_INTERFACE_MODE_2500BASEX] = OCELOT_PORT_MODE_2500BASEX, |
1237 | }; |
1238 | |
1239 | static int felix_validate_phy_mode(struct felix *felix, int port, |
1240 | phy_interface_t phy_mode) |
1241 | { |
1242 | u32 modes = felix->info->port_modes[port]; |
1243 | |
1244 | if (felix_phy_match_table[phy_mode] & modes) |
1245 | return 0; |
1246 | return -EOPNOTSUPP; |
1247 | } |
1248 | |
1249 | static int felix_parse_ports_node(struct felix *felix, |
1250 | struct device_node *ports_node, |
1251 | phy_interface_t *port_phy_modes) |
1252 | { |
1253 | struct device *dev = felix->ocelot.dev; |
1254 | struct device_node *child; |
1255 | |
1256 | for_each_available_child_of_node(ports_node, child) { |
1257 | phy_interface_t phy_mode; |
1258 | u32 port; |
1259 | int err; |
1260 | |
1261 | /* Get switch port number from DT */ |
1262 | if (of_property_read_u32(np: child, propname: "reg" , out_value: &port) < 0) { |
1263 | dev_err(dev, "Port number not defined in device tree " |
1264 | "(property \"reg\")\n" ); |
1265 | of_node_put(node: child); |
1266 | return -ENODEV; |
1267 | } |
1268 | |
1269 | /* Get PHY mode from DT */ |
1270 | err = of_get_phy_mode(np: child, interface: &phy_mode); |
1271 | if (err) { |
1272 | dev_err(dev, "Failed to read phy-mode or " |
1273 | "phy-interface-type property for port %d\n" , |
1274 | port); |
1275 | of_node_put(node: child); |
1276 | return -ENODEV; |
1277 | } |
1278 | |
1279 | err = felix_validate_phy_mode(felix, port, phy_mode); |
1280 | if (err < 0) { |
1281 | dev_info(dev, "Unsupported PHY mode %s on port %d\n" , |
1282 | phy_modes(phy_mode), port); |
1283 | |
1284 | /* Leave port_phy_modes[port] = 0, which is also |
1285 | * PHY_INTERFACE_MODE_NA. This will perform a |
1286 | * best-effort to bring up as many ports as possible. |
1287 | */ |
1288 | continue; |
1289 | } |
1290 | |
1291 | port_phy_modes[port] = phy_mode; |
1292 | } |
1293 | |
1294 | return 0; |
1295 | } |
1296 | |
1297 | static int felix_parse_dt(struct felix *felix, phy_interface_t *port_phy_modes) |
1298 | { |
1299 | struct device *dev = felix->ocelot.dev; |
1300 | struct device_node *switch_node; |
1301 | struct device_node *ports_node; |
1302 | int err; |
1303 | |
1304 | switch_node = dev->of_node; |
1305 | |
1306 | ports_node = of_get_child_by_name(node: switch_node, name: "ports" ); |
1307 | if (!ports_node) |
1308 | ports_node = of_get_child_by_name(node: switch_node, name: "ethernet-ports" ); |
1309 | if (!ports_node) { |
1310 | dev_err(dev, "Incorrect bindings: absent \"ports\" or \"ethernet-ports\" node\n" ); |
1311 | return -ENODEV; |
1312 | } |
1313 | |
1314 | err = felix_parse_ports_node(felix, ports_node, port_phy_modes); |
1315 | of_node_put(node: ports_node); |
1316 | |
1317 | return err; |
1318 | } |
1319 | |
1320 | static struct regmap *felix_request_regmap_by_name(struct felix *felix, |
1321 | const char *resource_name) |
1322 | { |
1323 | struct ocelot *ocelot = &felix->ocelot; |
1324 | struct resource res; |
1325 | int i; |
1326 | |
1327 | /* In an MFD configuration, regmaps are registered directly to the |
1328 | * parent device before the child devices are probed, so there is no |
1329 | * need to initialize a new one. |
1330 | */ |
1331 | if (!felix->info->resources) |
1332 | return dev_get_regmap(dev: ocelot->dev->parent, name: resource_name); |
1333 | |
1334 | for (i = 0; i < felix->info->num_resources; i++) { |
1335 | if (strcmp(resource_name, felix->info->resources[i].name)) |
1336 | continue; |
1337 | |
1338 | memcpy(&res, &felix->info->resources[i], sizeof(res)); |
1339 | res.start += felix->switch_base; |
1340 | res.end += felix->switch_base; |
1341 | |
1342 | return ocelot_regmap_init(ocelot, res: &res); |
1343 | } |
1344 | |
1345 | return ERR_PTR(error: -ENOENT); |
1346 | } |
1347 | |
1348 | static struct regmap *felix_request_regmap(struct felix *felix, |
1349 | enum ocelot_target target) |
1350 | { |
1351 | const char *resource_name = felix->info->resource_names[target]; |
1352 | |
1353 | /* If the driver didn't provide a resource name for the target, |
1354 | * the resource is optional. |
1355 | */ |
1356 | if (!resource_name) |
1357 | return NULL; |
1358 | |
1359 | return felix_request_regmap_by_name(felix, resource_name); |
1360 | } |
1361 | |
1362 | static struct regmap *felix_request_port_regmap(struct felix *felix, int port) |
1363 | { |
1364 | char resource_name[32]; |
1365 | |
1366 | sprintf(buf: resource_name, fmt: "port%d" , port); |
1367 | |
1368 | return felix_request_regmap_by_name(felix, resource_name); |
1369 | } |
1370 | |
1371 | static int felix_init_structs(struct felix *felix, int num_phys_ports) |
1372 | { |
1373 | struct ocelot *ocelot = &felix->ocelot; |
1374 | phy_interface_t *port_phy_modes; |
1375 | struct regmap *target; |
1376 | int port, i, err; |
1377 | |
1378 | ocelot->num_phys_ports = num_phys_ports; |
1379 | ocelot->ports = devm_kcalloc(dev: ocelot->dev, n: num_phys_ports, |
1380 | size: sizeof(struct ocelot_port *), GFP_KERNEL); |
1381 | if (!ocelot->ports) |
1382 | return -ENOMEM; |
1383 | |
1384 | ocelot->map = felix->info->map; |
1385 | ocelot->num_mact_rows = felix->info->num_mact_rows; |
1386 | ocelot->vcap = felix->info->vcap; |
1387 | ocelot->vcap_pol.base = felix->info->vcap_pol_base; |
1388 | ocelot->vcap_pol.max = felix->info->vcap_pol_max; |
1389 | ocelot->vcap_pol.base2 = felix->info->vcap_pol_base2; |
1390 | ocelot->vcap_pol.max2 = felix->info->vcap_pol_max2; |
1391 | ocelot->ops = felix->info->ops; |
1392 | ocelot->npi_inj_prefix = OCELOT_TAG_PREFIX_SHORT; |
1393 | ocelot->npi_xtr_prefix = OCELOT_TAG_PREFIX_SHORT; |
1394 | ocelot->devlink = felix->ds->devlink; |
1395 | |
1396 | port_phy_modes = kcalloc(n: num_phys_ports, size: sizeof(phy_interface_t), |
1397 | GFP_KERNEL); |
1398 | if (!port_phy_modes) |
1399 | return -ENOMEM; |
1400 | |
1401 | err = felix_parse_dt(felix, port_phy_modes); |
1402 | if (err) { |
1403 | kfree(objp: port_phy_modes); |
1404 | return err; |
1405 | } |
1406 | |
1407 | for (i = 0; i < TARGET_MAX; i++) { |
1408 | target = felix_request_regmap(felix, target: i); |
1409 | if (IS_ERR(ptr: target)) { |
1410 | dev_err(ocelot->dev, |
1411 | "Failed to map device memory space: %pe\n" , |
1412 | target); |
1413 | kfree(objp: port_phy_modes); |
1414 | return PTR_ERR(ptr: target); |
1415 | } |
1416 | |
1417 | ocelot->targets[i] = target; |
1418 | } |
1419 | |
1420 | err = ocelot_regfields_init(ocelot, regfields: felix->info->regfields); |
1421 | if (err) { |
1422 | dev_err(ocelot->dev, "failed to init reg fields map\n" ); |
1423 | kfree(objp: port_phy_modes); |
1424 | return err; |
1425 | } |
1426 | |
1427 | for (port = 0; port < num_phys_ports; port++) { |
1428 | struct ocelot_port *ocelot_port; |
1429 | |
1430 | ocelot_port = devm_kzalloc(dev: ocelot->dev, |
1431 | size: sizeof(struct ocelot_port), |
1432 | GFP_KERNEL); |
1433 | if (!ocelot_port) { |
1434 | dev_err(ocelot->dev, |
1435 | "failed to allocate port memory\n" ); |
1436 | kfree(objp: port_phy_modes); |
1437 | return -ENOMEM; |
1438 | } |
1439 | |
1440 | target = felix_request_port_regmap(felix, port); |
1441 | if (IS_ERR(ptr: target)) { |
1442 | dev_err(ocelot->dev, |
1443 | "Failed to map memory space for port %d: %pe\n" , |
1444 | port, target); |
1445 | kfree(objp: port_phy_modes); |
1446 | return PTR_ERR(ptr: target); |
1447 | } |
1448 | |
1449 | ocelot_port->phy_mode = port_phy_modes[port]; |
1450 | ocelot_port->ocelot = ocelot; |
1451 | ocelot_port->target = target; |
1452 | ocelot_port->index = port; |
1453 | ocelot->ports[port] = ocelot_port; |
1454 | } |
1455 | |
1456 | kfree(objp: port_phy_modes); |
1457 | |
1458 | if (felix->info->mdio_bus_alloc) { |
1459 | err = felix->info->mdio_bus_alloc(ocelot); |
1460 | if (err < 0) |
1461 | return err; |
1462 | } |
1463 | |
1464 | return 0; |
1465 | } |
1466 | |
1467 | static void ocelot_port_purge_txtstamp_skb(struct ocelot *ocelot, int port, |
1468 | struct sk_buff *skb) |
1469 | { |
1470 | struct ocelot_port *ocelot_port = ocelot->ports[port]; |
1471 | struct sk_buff *clone = OCELOT_SKB_CB(skb)->clone; |
1472 | struct sk_buff *skb_match = NULL, *skb_tmp; |
1473 | unsigned long flags; |
1474 | |
1475 | if (!clone) |
1476 | return; |
1477 | |
1478 | spin_lock_irqsave(&ocelot_port->tx_skbs.lock, flags); |
1479 | |
1480 | skb_queue_walk_safe(&ocelot_port->tx_skbs, skb, skb_tmp) { |
1481 | if (skb != clone) |
1482 | continue; |
1483 | __skb_unlink(skb, list: &ocelot_port->tx_skbs); |
1484 | skb_match = skb; |
1485 | break; |
1486 | } |
1487 | |
1488 | spin_unlock_irqrestore(lock: &ocelot_port->tx_skbs.lock, flags); |
1489 | |
1490 | WARN_ONCE(!skb_match, |
1491 | "Could not find skb clone in TX timestamping list\n" ); |
1492 | } |
1493 | |
1494 | #define work_to_xmit_work(w) \ |
1495 | container_of((w), struct felix_deferred_xmit_work, work) |
1496 | |
1497 | static void felix_port_deferred_xmit(struct kthread_work *work) |
1498 | { |
1499 | struct felix_deferred_xmit_work *xmit_work = work_to_xmit_work(work); |
1500 | struct dsa_switch *ds = xmit_work->dp->ds; |
1501 | struct sk_buff *skb = xmit_work->skb; |
1502 | u32 rew_op = ocelot_ptp_rew_op(skb); |
1503 | struct ocelot *ocelot = ds->priv; |
1504 | int port = xmit_work->dp->index; |
1505 | int retries = 10; |
1506 | |
1507 | do { |
1508 | if (ocelot_can_inject(ocelot, grp: 0)) |
1509 | break; |
1510 | |
1511 | cpu_relax(); |
1512 | } while (--retries); |
1513 | |
1514 | if (!retries) { |
1515 | dev_err(ocelot->dev, "port %d failed to inject skb\n" , |
1516 | port); |
1517 | ocelot_port_purge_txtstamp_skb(ocelot, port, skb); |
1518 | kfree_skb(skb); |
1519 | return; |
1520 | } |
1521 | |
1522 | ocelot_port_inject_frame(ocelot, port, grp: 0, rew_op, skb); |
1523 | |
1524 | consume_skb(skb); |
1525 | kfree(objp: xmit_work); |
1526 | } |
1527 | |
1528 | static int felix_connect_tag_protocol(struct dsa_switch *ds, |
1529 | enum dsa_tag_protocol proto) |
1530 | { |
1531 | struct ocelot_8021q_tagger_data *tagger_data; |
1532 | |
1533 | switch (proto) { |
1534 | case DSA_TAG_PROTO_OCELOT_8021Q: |
1535 | tagger_data = ocelot_8021q_tagger_data(ds); |
1536 | tagger_data->xmit_work_fn = felix_port_deferred_xmit; |
1537 | return 0; |
1538 | case DSA_TAG_PROTO_OCELOT: |
1539 | case DSA_TAG_PROTO_SEVILLE: |
1540 | return 0; |
1541 | default: |
1542 | return -EPROTONOSUPPORT; |
1543 | } |
1544 | } |
1545 | |
1546 | static int felix_setup(struct dsa_switch *ds) |
1547 | { |
1548 | struct ocelot *ocelot = ds->priv; |
1549 | struct felix *felix = ocelot_to_felix(ocelot); |
1550 | struct dsa_port *dp; |
1551 | int err; |
1552 | |
1553 | err = felix_init_structs(felix, num_phys_ports: ds->num_ports); |
1554 | if (err) |
1555 | return err; |
1556 | |
1557 | if (ocelot->targets[HSIO]) |
1558 | ocelot_pll5_init(ocelot); |
1559 | |
1560 | err = ocelot_init(ocelot); |
1561 | if (err) |
1562 | goto out_mdiobus_free; |
1563 | |
1564 | if (ocelot->ptp) { |
1565 | err = ocelot_init_timestamp(ocelot, info: felix->info->ptp_caps); |
1566 | if (err) { |
1567 | dev_err(ocelot->dev, |
1568 | "Timestamp initialization failed\n" ); |
1569 | ocelot->ptp = 0; |
1570 | } |
1571 | } |
1572 | |
1573 | dsa_switch_for_each_available_port(dp, ds) { |
1574 | ocelot_init_port(ocelot, port: dp->index); |
1575 | |
1576 | if (felix->info->configure_serdes) |
1577 | felix->info->configure_serdes(ocelot, dp->index, |
1578 | dp->dn); |
1579 | |
1580 | /* Set the default QoS Classification based on PCP and DEI |
1581 | * bits of vlan tag. |
1582 | */ |
1583 | felix_port_qos_map_init(ocelot, port: dp->index); |
1584 | } |
1585 | |
1586 | err = ocelot_devlink_sb_register(ocelot); |
1587 | if (err) |
1588 | goto out_deinit_ports; |
1589 | |
1590 | /* The initial tag protocol is NPI which won't fail during initial |
1591 | * setup, there's no real point in checking for errors. |
1592 | */ |
1593 | felix_change_tag_protocol(ds, proto: felix->tag_proto); |
1594 | |
1595 | ds->mtu_enforcement_ingress = true; |
1596 | ds->assisted_learning_on_cpu_port = true; |
1597 | ds->fdb_isolation = true; |
1598 | ds->max_num_bridges = ds->num_ports; |
1599 | |
1600 | return 0; |
1601 | |
1602 | out_deinit_ports: |
1603 | dsa_switch_for_each_available_port(dp, ds) |
1604 | ocelot_deinit_port(ocelot, port: dp->index); |
1605 | |
1606 | ocelot_deinit_timestamp(ocelot); |
1607 | ocelot_deinit(ocelot); |
1608 | |
1609 | out_mdiobus_free: |
1610 | if (felix->info->mdio_bus_free) |
1611 | felix->info->mdio_bus_free(ocelot); |
1612 | |
1613 | return err; |
1614 | } |
1615 | |
1616 | static void felix_teardown(struct dsa_switch *ds) |
1617 | { |
1618 | struct ocelot *ocelot = ds->priv; |
1619 | struct felix *felix = ocelot_to_felix(ocelot); |
1620 | struct dsa_port *dp; |
1621 | |
1622 | rtnl_lock(); |
1623 | if (felix->tag_proto_ops) |
1624 | felix->tag_proto_ops->teardown(ds); |
1625 | rtnl_unlock(); |
1626 | |
1627 | dsa_switch_for_each_available_port(dp, ds) |
1628 | ocelot_deinit_port(ocelot, port: dp->index); |
1629 | |
1630 | ocelot_devlink_sb_unregister(ocelot); |
1631 | ocelot_deinit_timestamp(ocelot); |
1632 | ocelot_deinit(ocelot); |
1633 | |
1634 | if (felix->info->mdio_bus_free) |
1635 | felix->info->mdio_bus_free(ocelot); |
1636 | } |
1637 | |
1638 | static int felix_hwtstamp_get(struct dsa_switch *ds, int port, |
1639 | struct ifreq *ifr) |
1640 | { |
1641 | struct ocelot *ocelot = ds->priv; |
1642 | |
1643 | return ocelot_hwstamp_get(ocelot, port, ifr); |
1644 | } |
1645 | |
1646 | static int felix_hwtstamp_set(struct dsa_switch *ds, int port, |
1647 | struct ifreq *ifr) |
1648 | { |
1649 | struct ocelot *ocelot = ds->priv; |
1650 | struct felix *felix = ocelot_to_felix(ocelot); |
1651 | bool using_tag_8021q; |
1652 | int err; |
1653 | |
1654 | err = ocelot_hwstamp_set(ocelot, port, ifr); |
1655 | if (err) |
1656 | return err; |
1657 | |
1658 | using_tag_8021q = felix->tag_proto == DSA_TAG_PROTO_OCELOT_8021Q; |
1659 | |
1660 | return felix_update_trapping_destinations(ds, using_tag_8021q); |
1661 | } |
1662 | |
1663 | static bool felix_check_xtr_pkt(struct ocelot *ocelot) |
1664 | { |
1665 | struct felix *felix = ocelot_to_felix(ocelot); |
1666 | int err = 0, grp = 0; |
1667 | |
1668 | if (felix->tag_proto != DSA_TAG_PROTO_OCELOT_8021Q) |
1669 | return false; |
1670 | |
1671 | if (!felix->info->quirk_no_xtr_irq) |
1672 | return false; |
1673 | |
1674 | while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) { |
1675 | struct sk_buff *skb; |
1676 | unsigned int type; |
1677 | |
1678 | err = ocelot_xtr_poll_frame(ocelot, grp, skb: &skb); |
1679 | if (err) |
1680 | goto out; |
1681 | |
1682 | /* We trap to the CPU port module all PTP frames, but |
1683 | * felix_rxtstamp() only gets called for event frames. |
1684 | * So we need to avoid sending duplicate general |
1685 | * message frames by running a second BPF classifier |
1686 | * here and dropping those. |
1687 | */ |
1688 | __skb_push(skb, ETH_HLEN); |
1689 | |
1690 | type = ptp_classify_raw(skb); |
1691 | |
1692 | __skb_pull(skb, ETH_HLEN); |
1693 | |
1694 | if (type == PTP_CLASS_NONE) { |
1695 | kfree_skb(skb); |
1696 | continue; |
1697 | } |
1698 | |
1699 | netif_rx(skb); |
1700 | } |
1701 | |
1702 | out: |
1703 | if (err < 0) { |
1704 | dev_err_ratelimited(ocelot->dev, |
1705 | "Error during packet extraction: %pe\n" , |
1706 | ERR_PTR(err)); |
1707 | ocelot_drain_cpu_queue(ocelot, grp: 0); |
1708 | } |
1709 | |
1710 | return true; |
1711 | } |
1712 | |
1713 | static bool felix_rxtstamp(struct dsa_switch *ds, int port, |
1714 | struct sk_buff *skb, unsigned int type) |
1715 | { |
1716 | u32 tstamp_lo = OCELOT_SKB_CB(skb)->tstamp_lo; |
1717 | struct skb_shared_hwtstamps *shhwtstamps; |
1718 | struct ocelot *ocelot = ds->priv; |
1719 | struct timespec64 ts; |
1720 | u32 tstamp_hi; |
1721 | u64 tstamp; |
1722 | |
1723 | switch (type & PTP_CLASS_PMASK) { |
1724 | case PTP_CLASS_L2: |
1725 | if (!(ocelot->ports[port]->trap_proto & OCELOT_PROTO_PTP_L2)) |
1726 | return false; |
1727 | break; |
1728 | case PTP_CLASS_IPV4: |
1729 | case PTP_CLASS_IPV6: |
1730 | if (!(ocelot->ports[port]->trap_proto & OCELOT_PROTO_PTP_L4)) |
1731 | return false; |
1732 | break; |
1733 | } |
1734 | |
1735 | /* If the "no XTR IRQ" workaround is in use, tell DSA to defer this skb |
1736 | * for RX timestamping. Then free it, and poll for its copy through |
1737 | * MMIO in the CPU port module, and inject that into the stack from |
1738 | * ocelot_xtr_poll(). |
1739 | */ |
1740 | if (felix_check_xtr_pkt(ocelot)) { |
1741 | kfree_skb(skb); |
1742 | return true; |
1743 | } |
1744 | |
1745 | ocelot_ptp_gettime64(ptp: &ocelot->ptp_info, ts: &ts); |
1746 | tstamp = ktime_set(secs: ts.tv_sec, nsecs: ts.tv_nsec); |
1747 | |
1748 | tstamp_hi = tstamp >> 32; |
1749 | if ((tstamp & 0xffffffff) < tstamp_lo) |
1750 | tstamp_hi--; |
1751 | |
1752 | tstamp = ((u64)tstamp_hi << 32) | tstamp_lo; |
1753 | |
1754 | shhwtstamps = skb_hwtstamps(skb); |
1755 | memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); |
1756 | shhwtstamps->hwtstamp = tstamp; |
1757 | return false; |
1758 | } |
1759 | |
1760 | static void felix_txtstamp(struct dsa_switch *ds, int port, |
1761 | struct sk_buff *skb) |
1762 | { |
1763 | struct ocelot *ocelot = ds->priv; |
1764 | struct sk_buff *clone = NULL; |
1765 | |
1766 | if (!ocelot->ptp) |
1767 | return; |
1768 | |
1769 | if (ocelot_port_txtstamp_request(ocelot, port, skb, clone: &clone)) { |
1770 | dev_err_ratelimited(ds->dev, |
1771 | "port %d delivering skb without TX timestamp\n" , |
1772 | port); |
1773 | return; |
1774 | } |
1775 | |
1776 | if (clone) |
1777 | OCELOT_SKB_CB(skb)->clone = clone; |
1778 | } |
1779 | |
1780 | static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu) |
1781 | { |
1782 | struct ocelot *ocelot = ds->priv; |
1783 | struct ocelot_port *ocelot_port = ocelot->ports[port]; |
1784 | |
1785 | ocelot_port_set_maxlen(ocelot, port, sdu: new_mtu); |
1786 | |
1787 | mutex_lock(&ocelot->fwd_domain_lock); |
1788 | |
1789 | if (ocelot_port->taprio && ocelot->ops->tas_guard_bands_update) |
1790 | ocelot->ops->tas_guard_bands_update(ocelot, port); |
1791 | |
1792 | mutex_unlock(lock: &ocelot->fwd_domain_lock); |
1793 | |
1794 | return 0; |
1795 | } |
1796 | |
1797 | static int felix_get_max_mtu(struct dsa_switch *ds, int port) |
1798 | { |
1799 | struct ocelot *ocelot = ds->priv; |
1800 | |
1801 | return ocelot_get_max_mtu(ocelot, port); |
1802 | } |
1803 | |
1804 | static int felix_cls_flower_add(struct dsa_switch *ds, int port, |
1805 | struct flow_cls_offload *cls, bool ingress) |
1806 | { |
1807 | struct ocelot *ocelot = ds->priv; |
1808 | struct felix *felix = ocelot_to_felix(ocelot); |
1809 | bool using_tag_8021q; |
1810 | int err; |
1811 | |
1812 | err = ocelot_cls_flower_replace(ocelot, port, f: cls, ingress); |
1813 | if (err) |
1814 | return err; |
1815 | |
1816 | using_tag_8021q = felix->tag_proto == DSA_TAG_PROTO_OCELOT_8021Q; |
1817 | |
1818 | return felix_update_trapping_destinations(ds, using_tag_8021q); |
1819 | } |
1820 | |
1821 | static int felix_cls_flower_del(struct dsa_switch *ds, int port, |
1822 | struct flow_cls_offload *cls, bool ingress) |
1823 | { |
1824 | struct ocelot *ocelot = ds->priv; |
1825 | |
1826 | return ocelot_cls_flower_destroy(ocelot, port, f: cls, ingress); |
1827 | } |
1828 | |
1829 | static int felix_cls_flower_stats(struct dsa_switch *ds, int port, |
1830 | struct flow_cls_offload *cls, bool ingress) |
1831 | { |
1832 | struct ocelot *ocelot = ds->priv; |
1833 | |
1834 | return ocelot_cls_flower_stats(ocelot, port, f: cls, ingress); |
1835 | } |
1836 | |
1837 | static int felix_port_policer_add(struct dsa_switch *ds, int port, |
1838 | struct dsa_mall_policer_tc_entry *policer) |
1839 | { |
1840 | struct ocelot *ocelot = ds->priv; |
1841 | struct ocelot_policer pol = { |
1842 | .rate = div_u64(dividend: policer->rate_bytes_per_sec, divisor: 1000) * 8, |
1843 | .burst = policer->burst, |
1844 | }; |
1845 | |
1846 | return ocelot_port_policer_add(ocelot, port, pol: &pol); |
1847 | } |
1848 | |
1849 | static void felix_port_policer_del(struct dsa_switch *ds, int port) |
1850 | { |
1851 | struct ocelot *ocelot = ds->priv; |
1852 | |
1853 | ocelot_port_policer_del(ocelot, port); |
1854 | } |
1855 | |
1856 | static int felix_port_mirror_add(struct dsa_switch *ds, int port, |
1857 | struct dsa_mall_mirror_tc_entry *mirror, |
1858 | bool ingress, struct netlink_ext_ack *extack) |
1859 | { |
1860 | struct ocelot *ocelot = ds->priv; |
1861 | |
1862 | return ocelot_port_mirror_add(ocelot, from: port, to: mirror->to_local_port, |
1863 | ingress, extack); |
1864 | } |
1865 | |
1866 | static void felix_port_mirror_del(struct dsa_switch *ds, int port, |
1867 | struct dsa_mall_mirror_tc_entry *mirror) |
1868 | { |
1869 | struct ocelot *ocelot = ds->priv; |
1870 | |
1871 | ocelot_port_mirror_del(ocelot, from: port, ingress: mirror->ingress); |
1872 | } |
1873 | |
1874 | static int felix_port_setup_tc(struct dsa_switch *ds, int port, |
1875 | enum tc_setup_type type, |
1876 | void *type_data) |
1877 | { |
1878 | struct ocelot *ocelot = ds->priv; |
1879 | struct felix *felix = ocelot_to_felix(ocelot); |
1880 | |
1881 | if (felix->info->port_setup_tc) |
1882 | return felix->info->port_setup_tc(ds, port, type, type_data); |
1883 | else |
1884 | return -EOPNOTSUPP; |
1885 | } |
1886 | |
1887 | static int felix_sb_pool_get(struct dsa_switch *ds, unsigned int sb_index, |
1888 | u16 pool_index, |
1889 | struct devlink_sb_pool_info *pool_info) |
1890 | { |
1891 | struct ocelot *ocelot = ds->priv; |
1892 | |
1893 | return ocelot_sb_pool_get(ocelot, sb_index, pool_index, pool_info); |
1894 | } |
1895 | |
1896 | static int felix_sb_pool_set(struct dsa_switch *ds, unsigned int sb_index, |
1897 | u16 pool_index, u32 size, |
1898 | enum devlink_sb_threshold_type threshold_type, |
1899 | struct netlink_ext_ack *extack) |
1900 | { |
1901 | struct ocelot *ocelot = ds->priv; |
1902 | |
1903 | return ocelot_sb_pool_set(ocelot, sb_index, pool_index, size, |
1904 | threshold_type, extack); |
1905 | } |
1906 | |
1907 | static int felix_sb_port_pool_get(struct dsa_switch *ds, int port, |
1908 | unsigned int sb_index, u16 pool_index, |
1909 | u32 *p_threshold) |
1910 | { |
1911 | struct ocelot *ocelot = ds->priv; |
1912 | |
1913 | return ocelot_sb_port_pool_get(ocelot, port, sb_index, pool_index, |
1914 | p_threshold); |
1915 | } |
1916 | |
1917 | static int felix_sb_port_pool_set(struct dsa_switch *ds, int port, |
1918 | unsigned int sb_index, u16 pool_index, |
1919 | u32 threshold, struct netlink_ext_ack *extack) |
1920 | { |
1921 | struct ocelot *ocelot = ds->priv; |
1922 | |
1923 | return ocelot_sb_port_pool_set(ocelot, port, sb_index, pool_index, |
1924 | threshold, extack); |
1925 | } |
1926 | |
1927 | static int felix_sb_tc_pool_bind_get(struct dsa_switch *ds, int port, |
1928 | unsigned int sb_index, u16 tc_index, |
1929 | enum devlink_sb_pool_type pool_type, |
1930 | u16 *p_pool_index, u32 *p_threshold) |
1931 | { |
1932 | struct ocelot *ocelot = ds->priv; |
1933 | |
1934 | return ocelot_sb_tc_pool_bind_get(ocelot, port, sb_index, tc_index, |
1935 | pool_type, p_pool_index, |
1936 | p_threshold); |
1937 | } |
1938 | |
1939 | static int felix_sb_tc_pool_bind_set(struct dsa_switch *ds, int port, |
1940 | unsigned int sb_index, u16 tc_index, |
1941 | enum devlink_sb_pool_type pool_type, |
1942 | u16 pool_index, u32 threshold, |
1943 | struct netlink_ext_ack *extack) |
1944 | { |
1945 | struct ocelot *ocelot = ds->priv; |
1946 | |
1947 | return ocelot_sb_tc_pool_bind_set(ocelot, port, sb_index, tc_index, |
1948 | pool_type, pool_index, threshold, |
1949 | extack); |
1950 | } |
1951 | |
1952 | static int felix_sb_occ_snapshot(struct dsa_switch *ds, |
1953 | unsigned int sb_index) |
1954 | { |
1955 | struct ocelot *ocelot = ds->priv; |
1956 | |
1957 | return ocelot_sb_occ_snapshot(ocelot, sb_index); |
1958 | } |
1959 | |
1960 | static int felix_sb_occ_max_clear(struct dsa_switch *ds, |
1961 | unsigned int sb_index) |
1962 | { |
1963 | struct ocelot *ocelot = ds->priv; |
1964 | |
1965 | return ocelot_sb_occ_max_clear(ocelot, sb_index); |
1966 | } |
1967 | |
1968 | static int felix_sb_occ_port_pool_get(struct dsa_switch *ds, int port, |
1969 | unsigned int sb_index, u16 pool_index, |
1970 | u32 *p_cur, u32 *p_max) |
1971 | { |
1972 | struct ocelot *ocelot = ds->priv; |
1973 | |
1974 | return ocelot_sb_occ_port_pool_get(ocelot, port, sb_index, pool_index, |
1975 | p_cur, p_max); |
1976 | } |
1977 | |
1978 | static int felix_sb_occ_tc_port_bind_get(struct dsa_switch *ds, int port, |
1979 | unsigned int sb_index, u16 tc_index, |
1980 | enum devlink_sb_pool_type pool_type, |
1981 | u32 *p_cur, u32 *p_max) |
1982 | { |
1983 | struct ocelot *ocelot = ds->priv; |
1984 | |
1985 | return ocelot_sb_occ_tc_port_bind_get(ocelot, port, sb_index, tc_index, |
1986 | pool_type, p_cur, p_max); |
1987 | } |
1988 | |
1989 | static int felix_mrp_add(struct dsa_switch *ds, int port, |
1990 | const struct switchdev_obj_mrp *mrp) |
1991 | { |
1992 | struct ocelot *ocelot = ds->priv; |
1993 | |
1994 | return ocelot_mrp_add(ocelot, port, mrp); |
1995 | } |
1996 | |
1997 | static int felix_mrp_del(struct dsa_switch *ds, int port, |
1998 | const struct switchdev_obj_mrp *mrp) |
1999 | { |
2000 | struct ocelot *ocelot = ds->priv; |
2001 | |
2002 | return ocelot_mrp_add(ocelot, port, mrp); |
2003 | } |
2004 | |
2005 | static int |
2006 | felix_mrp_add_ring_role(struct dsa_switch *ds, int port, |
2007 | const struct switchdev_obj_ring_role_mrp *mrp) |
2008 | { |
2009 | struct ocelot *ocelot = ds->priv; |
2010 | |
2011 | return ocelot_mrp_add_ring_role(ocelot, port, mrp); |
2012 | } |
2013 | |
2014 | static int |
2015 | felix_mrp_del_ring_role(struct dsa_switch *ds, int port, |
2016 | const struct switchdev_obj_ring_role_mrp *mrp) |
2017 | { |
2018 | struct ocelot *ocelot = ds->priv; |
2019 | |
2020 | return ocelot_mrp_del_ring_role(ocelot, port, mrp); |
2021 | } |
2022 | |
2023 | static int felix_port_get_default_prio(struct dsa_switch *ds, int port) |
2024 | { |
2025 | struct ocelot *ocelot = ds->priv; |
2026 | |
2027 | return ocelot_port_get_default_prio(ocelot, port); |
2028 | } |
2029 | |
2030 | static int felix_port_set_default_prio(struct dsa_switch *ds, int port, |
2031 | u8 prio) |
2032 | { |
2033 | struct ocelot *ocelot = ds->priv; |
2034 | |
2035 | return ocelot_port_set_default_prio(ocelot, port, prio); |
2036 | } |
2037 | |
2038 | static int felix_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp) |
2039 | { |
2040 | struct ocelot *ocelot = ds->priv; |
2041 | |
2042 | return ocelot_port_get_dscp_prio(ocelot, port, dscp); |
2043 | } |
2044 | |
2045 | static int felix_port_add_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, |
2046 | u8 prio) |
2047 | { |
2048 | struct ocelot *ocelot = ds->priv; |
2049 | |
2050 | return ocelot_port_add_dscp_prio(ocelot, port, dscp, prio); |
2051 | } |
2052 | |
2053 | static int felix_port_del_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, |
2054 | u8 prio) |
2055 | { |
2056 | struct ocelot *ocelot = ds->priv; |
2057 | |
2058 | return ocelot_port_del_dscp_prio(ocelot, port, dscp, prio); |
2059 | } |
2060 | |
2061 | static int felix_get_mm(struct dsa_switch *ds, int port, |
2062 | struct ethtool_mm_state *state) |
2063 | { |
2064 | struct ocelot *ocelot = ds->priv; |
2065 | |
2066 | return ocelot_port_get_mm(ocelot, port, state); |
2067 | } |
2068 | |
2069 | static int felix_set_mm(struct dsa_switch *ds, int port, |
2070 | struct ethtool_mm_cfg *cfg, |
2071 | struct netlink_ext_ack *extack) |
2072 | { |
2073 | struct ocelot *ocelot = ds->priv; |
2074 | |
2075 | return ocelot_port_set_mm(ocelot, port, cfg, extack); |
2076 | } |
2077 | |
2078 | static void felix_get_mm_stats(struct dsa_switch *ds, int port, |
2079 | struct ethtool_mm_stats *stats) |
2080 | { |
2081 | struct ocelot *ocelot = ds->priv; |
2082 | |
2083 | ocelot_port_get_mm_stats(ocelot, port, stats); |
2084 | } |
2085 | |
2086 | const struct dsa_switch_ops felix_switch_ops = { |
2087 | .get_tag_protocol = felix_get_tag_protocol, |
2088 | .change_tag_protocol = felix_change_tag_protocol, |
2089 | .connect_tag_protocol = felix_connect_tag_protocol, |
2090 | .setup = felix_setup, |
2091 | .teardown = felix_teardown, |
2092 | .set_ageing_time = felix_set_ageing_time, |
2093 | .get_mm = felix_get_mm, |
2094 | .set_mm = felix_set_mm, |
2095 | .get_mm_stats = felix_get_mm_stats, |
2096 | .get_stats64 = felix_get_stats64, |
2097 | .get_pause_stats = felix_get_pause_stats, |
2098 | .get_rmon_stats = felix_get_rmon_stats, |
2099 | .get_eth_ctrl_stats = felix_get_eth_ctrl_stats, |
2100 | .get_eth_mac_stats = felix_get_eth_mac_stats, |
2101 | .get_eth_phy_stats = felix_get_eth_phy_stats, |
2102 | .get_strings = felix_get_strings, |
2103 | .get_ethtool_stats = felix_get_ethtool_stats, |
2104 | .get_sset_count = felix_get_sset_count, |
2105 | .get_ts_info = felix_get_ts_info, |
2106 | .phylink_get_caps = felix_phylink_get_caps, |
2107 | .phylink_mac_config = felix_phylink_mac_config, |
2108 | .phylink_mac_select_pcs = felix_phylink_mac_select_pcs, |
2109 | .phylink_mac_link_down = felix_phylink_mac_link_down, |
2110 | .phylink_mac_link_up = felix_phylink_mac_link_up, |
2111 | .port_enable = felix_port_enable, |
2112 | .port_fast_age = felix_port_fast_age, |
2113 | .port_fdb_dump = felix_fdb_dump, |
2114 | .port_fdb_add = felix_fdb_add, |
2115 | .port_fdb_del = felix_fdb_del, |
2116 | .lag_fdb_add = felix_lag_fdb_add, |
2117 | .lag_fdb_del = felix_lag_fdb_del, |
2118 | .port_mdb_add = felix_mdb_add, |
2119 | .port_mdb_del = felix_mdb_del, |
2120 | .port_pre_bridge_flags = felix_pre_bridge_flags, |
2121 | .port_bridge_flags = felix_bridge_flags, |
2122 | .port_bridge_join = felix_bridge_join, |
2123 | .port_bridge_leave = felix_bridge_leave, |
2124 | .port_lag_join = felix_lag_join, |
2125 | .port_lag_leave = felix_lag_leave, |
2126 | .port_lag_change = felix_lag_change, |
2127 | .port_stp_state_set = felix_bridge_stp_state_set, |
2128 | .port_vlan_filtering = felix_vlan_filtering, |
2129 | .port_vlan_add = felix_vlan_add, |
2130 | .port_vlan_del = felix_vlan_del, |
2131 | .port_hwtstamp_get = felix_hwtstamp_get, |
2132 | .port_hwtstamp_set = felix_hwtstamp_set, |
2133 | .port_rxtstamp = felix_rxtstamp, |
2134 | .port_txtstamp = felix_txtstamp, |
2135 | .port_change_mtu = felix_change_mtu, |
2136 | .port_max_mtu = felix_get_max_mtu, |
2137 | .port_policer_add = felix_port_policer_add, |
2138 | .port_policer_del = felix_port_policer_del, |
2139 | .port_mirror_add = felix_port_mirror_add, |
2140 | .port_mirror_del = felix_port_mirror_del, |
2141 | .cls_flower_add = felix_cls_flower_add, |
2142 | .cls_flower_del = felix_cls_flower_del, |
2143 | .cls_flower_stats = felix_cls_flower_stats, |
2144 | .port_setup_tc = felix_port_setup_tc, |
2145 | .devlink_sb_pool_get = felix_sb_pool_get, |
2146 | .devlink_sb_pool_set = felix_sb_pool_set, |
2147 | .devlink_sb_port_pool_get = felix_sb_port_pool_get, |
2148 | .devlink_sb_port_pool_set = felix_sb_port_pool_set, |
2149 | .devlink_sb_tc_pool_bind_get = felix_sb_tc_pool_bind_get, |
2150 | .devlink_sb_tc_pool_bind_set = felix_sb_tc_pool_bind_set, |
2151 | .devlink_sb_occ_snapshot = felix_sb_occ_snapshot, |
2152 | .devlink_sb_occ_max_clear = felix_sb_occ_max_clear, |
2153 | .devlink_sb_occ_port_pool_get = felix_sb_occ_port_pool_get, |
2154 | .devlink_sb_occ_tc_port_bind_get= felix_sb_occ_tc_port_bind_get, |
2155 | .port_mrp_add = felix_mrp_add, |
2156 | .port_mrp_del = felix_mrp_del, |
2157 | .port_mrp_add_ring_role = felix_mrp_add_ring_role, |
2158 | .port_mrp_del_ring_role = felix_mrp_del_ring_role, |
2159 | .tag_8021q_vlan_add = felix_tag_8021q_vlan_add, |
2160 | .tag_8021q_vlan_del = felix_tag_8021q_vlan_del, |
2161 | .port_get_default_prio = felix_port_get_default_prio, |
2162 | .port_set_default_prio = felix_port_set_default_prio, |
2163 | .port_get_dscp_prio = felix_port_get_dscp_prio, |
2164 | .port_add_dscp_prio = felix_port_add_dscp_prio, |
2165 | .port_del_dscp_prio = felix_port_del_dscp_prio, |
2166 | .port_set_host_flood = felix_port_set_host_flood, |
2167 | .port_change_conduit = felix_port_change_conduit, |
2168 | }; |
2169 | EXPORT_SYMBOL_GPL(felix_switch_ops); |
2170 | |
2171 | struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port) |
2172 | { |
2173 | struct felix *felix = ocelot_to_felix(ocelot); |
2174 | struct dsa_switch *ds = felix->ds; |
2175 | |
2176 | if (!dsa_is_user_port(ds, p: port)) |
2177 | return NULL; |
2178 | |
2179 | return dsa_to_port(ds, p: port)->user; |
2180 | } |
2181 | EXPORT_SYMBOL_GPL(felix_port_to_netdev); |
2182 | |
2183 | int felix_netdev_to_port(struct net_device *dev) |
2184 | { |
2185 | struct dsa_port *dp; |
2186 | |
2187 | dp = dsa_port_from_netdev(netdev: dev); |
2188 | if (IS_ERR(ptr: dp)) |
2189 | return -EINVAL; |
2190 | |
2191 | return dp->index; |
2192 | } |
2193 | EXPORT_SYMBOL_GPL(felix_netdev_to_port); |
2194 | |
2195 | MODULE_DESCRIPTION("Felix DSA library" ); |
2196 | MODULE_LICENSE("GPL" ); |
2197 | |