1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
3
4 #include <linux/etherdevice.h>
5 #include <linux/if_bridge.h>
6 #include <linux/ethtool.h>
7 #include <linux/list.h>
8
9 #include "prestera.h"
10 #include "prestera_hw.h"
11 #include "prestera_acl.h"
12 #include "prestera_counter.h"
13
14 #define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
15
16 #define PRESTERA_MIN_MTU 64
17
18 enum prestera_cmd_type_t {
19 PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1,
20 PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2,
21
22 PRESTERA_CMD_TYPE_PORT_ATTR_SET = 0x100,
23 PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101,
24 PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110,
25
26 PRESTERA_CMD_TYPE_VLAN_CREATE = 0x200,
27 PRESTERA_CMD_TYPE_VLAN_DELETE = 0x201,
28 PRESTERA_CMD_TYPE_VLAN_PORT_SET = 0x202,
29 PRESTERA_CMD_TYPE_VLAN_PVID_SET = 0x203,
30
31 PRESTERA_CMD_TYPE_FDB_ADD = 0x300,
32 PRESTERA_CMD_TYPE_FDB_DELETE = 0x301,
33 PRESTERA_CMD_TYPE_FDB_FLUSH_PORT = 0x310,
34 PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN = 0x311,
35 PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN = 0x312,
36
37 PRESTERA_CMD_TYPE_BRIDGE_CREATE = 0x400,
38 PRESTERA_CMD_TYPE_BRIDGE_DELETE = 0x401,
39 PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD = 0x402,
40 PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE = 0x403,
41
42 PRESTERA_CMD_TYPE_COUNTER_GET = 0x510,
43 PRESTERA_CMD_TYPE_COUNTER_ABORT = 0x511,
44 PRESTERA_CMD_TYPE_COUNTER_TRIGGER = 0x512,
45 PRESTERA_CMD_TYPE_COUNTER_BLOCK_GET = 0x513,
46 PRESTERA_CMD_TYPE_COUNTER_BLOCK_RELEASE = 0x514,
47 PRESTERA_CMD_TYPE_COUNTER_CLEAR = 0x515,
48
49 PRESTERA_CMD_TYPE_VTCAM_CREATE = 0x540,
50 PRESTERA_CMD_TYPE_VTCAM_DESTROY = 0x541,
51 PRESTERA_CMD_TYPE_VTCAM_RULE_ADD = 0x550,
52 PRESTERA_CMD_TYPE_VTCAM_RULE_DELETE = 0x551,
53 PRESTERA_CMD_TYPE_VTCAM_IFACE_BIND = 0x560,
54 PRESTERA_CMD_TYPE_VTCAM_IFACE_UNBIND = 0x561,
55
56 PRESTERA_CMD_TYPE_ROUTER_RIF_CREATE = 0x600,
57 PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE = 0x601,
58 PRESTERA_CMD_TYPE_ROUTER_LPM_ADD = 0x610,
59 PRESTERA_CMD_TYPE_ROUTER_LPM_DELETE = 0x611,
60 PRESTERA_CMD_TYPE_ROUTER_VR_CREATE = 0x630,
61 PRESTERA_CMD_TYPE_ROUTER_VR_DELETE = 0x631,
62
63 PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
64
65 PRESTERA_CMD_TYPE_LAG_MEMBER_ADD = 0x900,
66 PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE = 0x901,
67 PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE = 0x902,
68 PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE = 0x903,
69
70 PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
71
72 PRESTERA_CMD_TYPE_SPAN_GET = 0x1100,
73 PRESTERA_CMD_TYPE_SPAN_BIND = 0x1101,
74 PRESTERA_CMD_TYPE_SPAN_UNBIND = 0x1102,
75 PRESTERA_CMD_TYPE_SPAN_RELEASE = 0x1103,
76
77 PRESTERA_CMD_TYPE_POLICER_CREATE = 0x1500,
78 PRESTERA_CMD_TYPE_POLICER_RELEASE = 0x1501,
79 PRESTERA_CMD_TYPE_POLICER_SET = 0x1502,
80
81 PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET = 0x2000,
82
83 PRESTERA_CMD_TYPE_ACK = 0x10000,
84 PRESTERA_CMD_TYPE_MAX
85 };
86
87 enum {
88 PRESTERA_CMD_PORT_ATTR_ADMIN_STATE = 1,
89 PRESTERA_CMD_PORT_ATTR_MTU = 3,
90 PRESTERA_CMD_PORT_ATTR_MAC = 4,
91 PRESTERA_CMD_PORT_ATTR_SPEED = 5,
92 PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6,
93 PRESTERA_CMD_PORT_ATTR_LEARNING = 7,
94 PRESTERA_CMD_PORT_ATTR_FLOOD = 8,
95 PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9,
96 PRESTERA_CMD_PORT_ATTR_PHY_MODE = 12,
97 PRESTERA_CMD_PORT_ATTR_TYPE = 13,
98 PRESTERA_CMD_PORT_ATTR_STATS = 17,
99 PRESTERA_CMD_PORT_ATTR_MAC_AUTONEG_RESTART = 18,
100 PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART = 19,
101 PRESTERA_CMD_PORT_ATTR_MAC_MODE = 22,
102 };
103
104 enum {
105 PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
106 PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
107 };
108
109 enum {
110 PRESTERA_CMD_ACK_OK,
111 PRESTERA_CMD_ACK_FAILED,
112
113 PRESTERA_CMD_ACK_MAX
114 };
115
116 enum {
117 PRESTERA_PORT_TP_NA,
118 PRESTERA_PORT_TP_MDI,
119 PRESTERA_PORT_TP_MDIX,
120 PRESTERA_PORT_TP_AUTO,
121 };
122
123 enum {
124 PRESTERA_PORT_FLOOD_TYPE_UC = 0,
125 PRESTERA_PORT_FLOOD_TYPE_MC = 1,
126 };
127
128 enum {
129 PRESTERA_PORT_GOOD_OCTETS_RCV_CNT,
130 PRESTERA_PORT_BAD_OCTETS_RCV_CNT,
131 PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT,
132 PRESTERA_PORT_BRDC_PKTS_RCV_CNT,
133 PRESTERA_PORT_MC_PKTS_RCV_CNT,
134 PRESTERA_PORT_PKTS_64L_CNT,
135 PRESTERA_PORT_PKTS_65TO127L_CNT,
136 PRESTERA_PORT_PKTS_128TO255L_CNT,
137 PRESTERA_PORT_PKTS_256TO511L_CNT,
138 PRESTERA_PORT_PKTS_512TO1023L_CNT,
139 PRESTERA_PORT_PKTS_1024TOMAXL_CNT,
140 PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT,
141 PRESTERA_PORT_MC_PKTS_SENT_CNT,
142 PRESTERA_PORT_BRDC_PKTS_SENT_CNT,
143 PRESTERA_PORT_FC_SENT_CNT,
144 PRESTERA_PORT_GOOD_FC_RCV_CNT,
145 PRESTERA_PORT_DROP_EVENTS_CNT,
146 PRESTERA_PORT_UNDERSIZE_PKTS_CNT,
147 PRESTERA_PORT_FRAGMENTS_PKTS_CNT,
148 PRESTERA_PORT_OVERSIZE_PKTS_CNT,
149 PRESTERA_PORT_JABBER_PKTS_CNT,
150 PRESTERA_PORT_MAC_RCV_ERROR_CNT,
151 PRESTERA_PORT_BAD_CRC_CNT,
152 PRESTERA_PORT_COLLISIONS_CNT,
153 PRESTERA_PORT_LATE_COLLISIONS_CNT,
154 PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT,
155 PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT,
156 PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT,
157 PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT,
158 PRESTERA_PORT_GOOD_OCTETS_SENT_CNT,
159
160 PRESTERA_PORT_CNT_MAX
161 };
162
163 enum {
164 PRESTERA_FC_NONE,
165 PRESTERA_FC_SYMMETRIC,
166 PRESTERA_FC_ASYMMETRIC,
167 PRESTERA_FC_SYMM_ASYMM,
168 };
169
170 enum {
171 PRESTERA_POLICER_MODE_SR_TCM
172 };
173
174 enum {
175 PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT = 0,
176 PRESTERA_HW_FDB_ENTRY_TYPE_LAG = 1,
177 PRESTERA_HW_FDB_ENTRY_TYPE_MAX = 2,
178 };
179
180 struct prestera_fw_event_handler {
181 struct list_head list;
182 struct rcu_head rcu;
183 enum prestera_event_type type;
184 prestera_event_cb_t func;
185 void *arg;
186 };
187
188 struct prestera_msg_cmd {
189 __le32 type;
190 };
191
192 struct prestera_msg_ret {
193 struct prestera_msg_cmd cmd;
194 __le32 status;
195 };
196
197 struct prestera_msg_common_req {
198 struct prestera_msg_cmd cmd;
199 };
200
201 struct prestera_msg_common_resp {
202 struct prestera_msg_ret ret;
203 };
204
205 struct prestera_msg_switch_attr_req {
206 struct prestera_msg_cmd cmd;
207 __le32 attr;
208 union {
209 __le32 ageing_timeout_ms;
210 struct {
211 u8 mac[ETH_ALEN];
212 u8 __pad[2];
213 };
214 } param;
215 };
216
217 struct prestera_msg_switch_init_resp {
218 struct prestera_msg_ret ret;
219 __le32 port_count;
220 __le32 mtu_max;
221 __le32 size_tbl_router_nexthop;
222 u8 switch_id;
223 u8 lag_max;
224 u8 lag_member_max;
225 };
226
227 struct prestera_msg_event_port_param {
228 union {
229 struct {
230 __le32 mode;
231 __le32 speed;
232 u8 oper;
233 u8 duplex;
234 u8 fc;
235 u8 fec;
236 } mac;
237 struct {
238 __le64 lmode_bmap;
239 u8 mdix;
240 u8 fc;
241 u8 __pad[2];
242 } __packed phy; /* make sure always 12 bytes size */
243 };
244 };
245
246 struct prestera_msg_port_cap_param {
247 __le64 link_mode;
248 u8 type;
249 u8 fec;
250 u8 fc;
251 u8 transceiver;
252 };
253
254 struct prestera_msg_port_flood_param {
255 u8 type;
256 u8 enable;
257 u8 __pad[2];
258 };
259
260 union prestera_msg_port_param {
261 __le32 mtu;
262 __le32 speed;
263 __le32 link_mode;
264 u8 admin_state;
265 u8 oper_state;
266 u8 mac[ETH_ALEN];
267 u8 accept_frm_type;
268 u8 learning;
269 u8 flood;
270 u8 type;
271 u8 duplex;
272 u8 fec;
273 u8 fc;
274 union {
275 struct {
276 u8 admin;
277 u8 fc;
278 u8 ap_enable;
279 u8 __reserved[5];
280 union {
281 struct {
282 __le32 mode;
283 __le32 speed;
284 u8 inband;
285 u8 duplex;
286 u8 fec;
287 u8 fec_supp;
288 } reg_mode;
289 struct {
290 __le32 mode;
291 __le32 speed;
292 u8 fec;
293 u8 fec_supp;
294 u8 __pad[2];
295 } ap_modes[PRESTERA_AP_PORT_MAX];
296 };
297 } mac;
298 struct {
299 __le64 modes;
300 __le32 mode;
301 u8 admin;
302 u8 adv_enable;
303 u8 mdix;
304 u8 __pad;
305 } phy;
306 } link;
307
308 struct prestera_msg_port_cap_param cap;
309 struct prestera_msg_port_flood_param flood_ext;
310 struct prestera_msg_event_port_param link_evt;
311 };
312
313 struct prestera_msg_port_attr_req {
314 struct prestera_msg_cmd cmd;
315 __le32 attr;
316 __le32 port;
317 __le32 dev;
318 union prestera_msg_port_param param;
319 };
320
321 struct prestera_msg_port_attr_resp {
322 struct prestera_msg_ret ret;
323 union prestera_msg_port_param param;
324 };
325
326 struct prestera_msg_port_stats_resp {
327 struct prestera_msg_ret ret;
328 __le64 stats[PRESTERA_PORT_CNT_MAX];
329 };
330
331 struct prestera_msg_port_info_req {
332 struct prestera_msg_cmd cmd;
333 __le32 port;
334 };
335
336 struct prestera_msg_port_info_resp {
337 struct prestera_msg_ret ret;
338 __le32 hw_id;
339 __le32 dev_id;
340 __le16 fp_id;
341 u8 pad[2];
342 };
343
344 struct prestera_msg_vlan_req {
345 struct prestera_msg_cmd cmd;
346 __le32 port;
347 __le32 dev;
348 __le16 vid;
349 u8 is_member;
350 u8 is_tagged;
351 };
352
353 struct prestera_msg_fdb_req {
354 struct prestera_msg_cmd cmd;
355 __le32 flush_mode;
356 union {
357 struct {
358 __le32 port;
359 __le32 dev;
360 };
361 __le16 lag_id;
362 } dest;
363 __le16 vid;
364 u8 dest_type;
365 u8 dynamic;
366 u8 mac[ETH_ALEN];
367 u8 __pad[2];
368 };
369
370 struct prestera_msg_bridge_req {
371 struct prestera_msg_cmd cmd;
372 __le32 port;
373 __le32 dev;
374 __le16 bridge;
375 u8 pad[2];
376 };
377
378 struct prestera_msg_bridge_resp {
379 struct prestera_msg_ret ret;
380 __le16 bridge;
381 u8 pad[2];
382 };
383
384 struct prestera_msg_vtcam_create_req {
385 struct prestera_msg_cmd cmd;
386 __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
387 u8 direction;
388 u8 lookup;
389 u8 pad[2];
390 };
391
392 struct prestera_msg_vtcam_destroy_req {
393 struct prestera_msg_cmd cmd;
394 __le32 vtcam_id;
395 };
396
397 struct prestera_msg_vtcam_rule_add_req {
398 struct prestera_msg_cmd cmd;
399 __le32 key[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
400 __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
401 __le32 vtcam_id;
402 __le32 prio;
403 __le32 n_act;
404 };
405
406 struct prestera_msg_vtcam_rule_del_req {
407 struct prestera_msg_cmd cmd;
408 __le32 vtcam_id;
409 __le32 id;
410 };
411
412 struct prestera_msg_vtcam_bind_req {
413 struct prestera_msg_cmd cmd;
414 union {
415 struct {
416 __le32 hw_id;
417 __le32 dev_id;
418 } port;
419 __le32 index;
420 };
421 __le32 vtcam_id;
422 __le16 pcl_id;
423 __le16 type;
424 };
425
426 struct prestera_msg_vtcam_resp {
427 struct prestera_msg_ret ret;
428 __le32 vtcam_id;
429 __le32 rule_id;
430 };
431
432 struct prestera_msg_acl_action {
433 __le32 id;
434 __le32 __reserved;
435 union {
436 struct {
437 __le32 index;
438 } jump;
439 struct {
440 __le32 id;
441 } police;
442 struct {
443 __le32 id;
444 } count;
445 __le32 reserved[6];
446 };
447 };
448
449 struct prestera_msg_counter_req {
450 struct prestera_msg_cmd cmd;
451 __le32 client;
452 __le32 block_id;
453 __le32 num_counters;
454 };
455
456 struct prestera_msg_counter_stats {
457 __le64 packets;
458 __le64 bytes;
459 };
460
461 struct prestera_msg_counter_resp {
462 struct prestera_msg_ret ret;
463 __le32 block_id;
464 __le32 offset;
465 __le32 num_counters;
466 __le32 done;
467 struct prestera_msg_counter_stats stats[];
468 };
469
470 struct prestera_msg_span_req {
471 struct prestera_msg_cmd cmd;
472 __le32 port;
473 __le32 dev;
474 u8 id;
475 u8 pad[3];
476 };
477
478 struct prestera_msg_span_resp {
479 struct prestera_msg_ret ret;
480 u8 id;
481 u8 pad[3];
482 };
483
484 struct prestera_msg_stp_req {
485 struct prestera_msg_cmd cmd;
486 __le32 port;
487 __le32 dev;
488 __le16 vid;
489 u8 state;
490 u8 __pad;
491 };
492
493 struct prestera_msg_rxtx_req {
494 struct prestera_msg_cmd cmd;
495 u8 use_sdma;
496 u8 pad[3];
497 };
498
499 struct prestera_msg_rxtx_resp {
500 struct prestera_msg_ret ret;
501 __le32 map_addr;
502 };
503
504 struct prestera_msg_iface {
505 union {
506 struct {
507 __le32 dev;
508 __le32 port;
509 };
510 __le16 lag_id;
511 };
512 __le16 vr_id;
513 __le16 vid;
514 u8 type;
515 u8 __pad[3];
516 };
517
518 struct prestera_msg_ip_addr {
519 union {
520 __be32 ipv4;
521 __be32 ipv6[4];
522 } u;
523 u8 v; /* e.g. PRESTERA_IPV4 */
524 u8 __pad[3];
525 };
526
527 struct prestera_msg_rif_req {
528 struct prestera_msg_cmd cmd;
529 struct prestera_msg_iface iif;
530 __le32 mtu;
531 __le16 rif_id;
532 __le16 __reserved;
533 u8 mac[ETH_ALEN];
534 u8 __pad[2];
535 };
536
537 struct prestera_msg_rif_resp {
538 struct prestera_msg_ret ret;
539 __le16 rif_id;
540 u8 __pad[2];
541 };
542
543 struct prestera_msg_lpm_req {
544 struct prestera_msg_cmd cmd;
545 struct prestera_msg_ip_addr dst;
546 __le32 grp_id;
547 __le32 dst_len;
548 __le16 vr_id;
549 u8 __pad[2];
550 };
551
552 struct prestera_msg_vr_req {
553 struct prestera_msg_cmd cmd;
554 __le16 vr_id;
555 u8 __pad[2];
556 };
557
558 struct prestera_msg_vr_resp {
559 struct prestera_msg_ret ret;
560 __le16 vr_id;
561 u8 __pad[2];
562 };
563
564 struct prestera_msg_lag_req {
565 struct prestera_msg_cmd cmd;
566 __le32 port;
567 __le32 dev;
568 __le16 lag_id;
569 u8 pad[2];
570 };
571
572 struct prestera_msg_cpu_code_counter_req {
573 struct prestera_msg_cmd cmd;
574 u8 counter_type;
575 u8 code;
576 u8 pad[2];
577 };
578
579 struct mvsw_msg_cpu_code_counter_ret {
580 struct prestera_msg_ret ret;
581 __le64 packet_count;
582 };
583
584 struct prestera_msg_policer_req {
585 struct prestera_msg_cmd cmd;
586 __le32 id;
587 union {
588 struct {
589 __le64 cir;
590 __le32 cbs;
591 } __packed sr_tcm; /* make sure always 12 bytes size */
592 __le32 reserved[6];
593 };
594 u8 mode;
595 u8 type;
596 u8 pad[2];
597 };
598
599 struct prestera_msg_policer_resp {
600 struct prestera_msg_ret ret;
601 __le32 id;
602 };
603
604 struct prestera_msg_event {
605 __le16 type;
606 __le16 id;
607 };
608
609 struct prestera_msg_event_port {
610 struct prestera_msg_event id;
611 __le32 port_id;
612 struct prestera_msg_event_port_param param;
613 };
614
615 union prestera_msg_event_fdb_param {
616 u8 mac[ETH_ALEN];
617 };
618
619 struct prestera_msg_event_fdb {
620 struct prestera_msg_event id;
621 __le32 vid;
622 union {
623 __le32 port_id;
624 __le16 lag_id;
625 } dest;
626 union prestera_msg_event_fdb_param param;
627 u8 dest_type;
628 };
629
prestera_hw_build_tests(void)630 static void prestera_hw_build_tests(void)
631 {
632 /* check requests */
633 BUILD_BUG_ON(sizeof(struct prestera_msg_common_req) != 4);
634 BUILD_BUG_ON(sizeof(struct prestera_msg_switch_attr_req) != 16);
635 BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_req) != 144);
636 BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_req) != 8);
637 BUILD_BUG_ON(sizeof(struct prestera_msg_vlan_req) != 16);
638 BUILD_BUG_ON(sizeof(struct prestera_msg_fdb_req) != 28);
639 BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_req) != 16);
640 BUILD_BUG_ON(sizeof(struct prestera_msg_span_req) != 16);
641 BUILD_BUG_ON(sizeof(struct prestera_msg_stp_req) != 16);
642 BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_req) != 8);
643 BUILD_BUG_ON(sizeof(struct prestera_msg_lag_req) != 16);
644 BUILD_BUG_ON(sizeof(struct prestera_msg_cpu_code_counter_req) != 8);
645 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_create_req) != 84);
646 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_destroy_req) != 8);
647 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_rule_add_req) != 168);
648 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_rule_del_req) != 12);
649 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_bind_req) != 20);
650 BUILD_BUG_ON(sizeof(struct prestera_msg_acl_action) != 32);
651 BUILD_BUG_ON(sizeof(struct prestera_msg_counter_req) != 16);
652 BUILD_BUG_ON(sizeof(struct prestera_msg_counter_stats) != 16);
653 BUILD_BUG_ON(sizeof(struct prestera_msg_rif_req) != 36);
654 BUILD_BUG_ON(sizeof(struct prestera_msg_vr_req) != 8);
655 BUILD_BUG_ON(sizeof(struct prestera_msg_lpm_req) != 36);
656 BUILD_BUG_ON(sizeof(struct prestera_msg_policer_req) != 36);
657
658 /* structure that are part of req/resp fw messages */
659 BUILD_BUG_ON(sizeof(struct prestera_msg_iface) != 16);
660 BUILD_BUG_ON(sizeof(struct prestera_msg_ip_addr) != 20);
661
662 /* check responses */
663 BUILD_BUG_ON(sizeof(struct prestera_msg_common_resp) != 8);
664 BUILD_BUG_ON(sizeof(struct prestera_msg_switch_init_resp) != 24);
665 BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_resp) != 136);
666 BUILD_BUG_ON(sizeof(struct prestera_msg_port_stats_resp) != 248);
667 BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_resp) != 20);
668 BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_resp) != 12);
669 BUILD_BUG_ON(sizeof(struct prestera_msg_span_resp) != 12);
670 BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_resp) != 12);
671 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_resp) != 16);
672 BUILD_BUG_ON(sizeof(struct prestera_msg_counter_resp) != 24);
673 BUILD_BUG_ON(sizeof(struct prestera_msg_rif_resp) != 12);
674 BUILD_BUG_ON(sizeof(struct prestera_msg_vr_resp) != 12);
675 BUILD_BUG_ON(sizeof(struct prestera_msg_policer_resp) != 12);
676
677 /* check events */
678 BUILD_BUG_ON(sizeof(struct prestera_msg_event_port) != 20);
679 BUILD_BUG_ON(sizeof(struct prestera_msg_event_fdb) != 20);
680 }
681
682 static u8 prestera_hw_mdix_to_eth(u8 mode);
683 static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause);
684
__prestera_cmd_ret(struct prestera_switch * sw,enum prestera_cmd_type_t type,struct prestera_msg_cmd * cmd,size_t clen,struct prestera_msg_ret * ret,size_t rlen,int waitms)685 static int __prestera_cmd_ret(struct prestera_switch *sw,
686 enum prestera_cmd_type_t type,
687 struct prestera_msg_cmd *cmd, size_t clen,
688 struct prestera_msg_ret *ret, size_t rlen,
689 int waitms)
690 {
691 struct prestera_device *dev = sw->dev;
692 int err;
693
694 cmd->type = __cpu_to_le32(type);
695
696 err = dev->send_req(dev, 0, cmd, clen, ret, rlen, waitms);
697 if (err)
698 return err;
699
700 if (ret->cmd.type != __cpu_to_le32(PRESTERA_CMD_TYPE_ACK))
701 return -EBADE;
702 if (ret->status != __cpu_to_le32(PRESTERA_CMD_ACK_OK))
703 return -EINVAL;
704
705 return 0;
706 }
707
prestera_cmd_ret(struct prestera_switch * sw,enum prestera_cmd_type_t type,struct prestera_msg_cmd * cmd,size_t clen,struct prestera_msg_ret * ret,size_t rlen)708 static int prestera_cmd_ret(struct prestera_switch *sw,
709 enum prestera_cmd_type_t type,
710 struct prestera_msg_cmd *cmd, size_t clen,
711 struct prestera_msg_ret *ret, size_t rlen)
712 {
713 return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0);
714 }
715
prestera_cmd_ret_wait(struct prestera_switch * sw,enum prestera_cmd_type_t type,struct prestera_msg_cmd * cmd,size_t clen,struct prestera_msg_ret * ret,size_t rlen,int waitms)716 static int prestera_cmd_ret_wait(struct prestera_switch *sw,
717 enum prestera_cmd_type_t type,
718 struct prestera_msg_cmd *cmd, size_t clen,
719 struct prestera_msg_ret *ret, size_t rlen,
720 int waitms)
721 {
722 return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms);
723 }
724
prestera_cmd(struct prestera_switch * sw,enum prestera_cmd_type_t type,struct prestera_msg_cmd * cmd,size_t clen)725 static int prestera_cmd(struct prestera_switch *sw,
726 enum prestera_cmd_type_t type,
727 struct prestera_msg_cmd *cmd, size_t clen)
728 {
729 struct prestera_msg_common_resp resp;
730
731 return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp));
732 }
733
prestera_fw_parse_port_evt(void * msg,struct prestera_event * evt)734 static int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt)
735 {
736 struct prestera_msg_event_port *hw_evt;
737
738 hw_evt = (struct prestera_msg_event_port *)msg;
739
740 evt->port_evt.port_id = __le32_to_cpu(hw_evt->port_id);
741
742 if (evt->id == PRESTERA_PORT_EVENT_MAC_STATE_CHANGED) {
743 evt->port_evt.data.mac.oper = hw_evt->param.mac.oper;
744 evt->port_evt.data.mac.mode =
745 __le32_to_cpu(hw_evt->param.mac.mode);
746 evt->port_evt.data.mac.speed =
747 __le32_to_cpu(hw_evt->param.mac.speed);
748 evt->port_evt.data.mac.duplex = hw_evt->param.mac.duplex;
749 evt->port_evt.data.mac.fc = hw_evt->param.mac.fc;
750 evt->port_evt.data.mac.fec = hw_evt->param.mac.fec;
751 } else {
752 return -EINVAL;
753 }
754
755 return 0;
756 }
757
prestera_fw_parse_fdb_evt(void * msg,struct prestera_event * evt)758 static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt)
759 {
760 struct prestera_msg_event_fdb *hw_evt = msg;
761
762 switch (hw_evt->dest_type) {
763 case PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT:
764 evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_REG_PORT;
765 evt->fdb_evt.dest.port_id = __le32_to_cpu(hw_evt->dest.port_id);
766 break;
767 case PRESTERA_HW_FDB_ENTRY_TYPE_LAG:
768 evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_LAG;
769 evt->fdb_evt.dest.lag_id = __le16_to_cpu(hw_evt->dest.lag_id);
770 break;
771 default:
772 return -EINVAL;
773 }
774
775 evt->fdb_evt.vid = __le32_to_cpu(hw_evt->vid);
776
777 ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac);
778
779 return 0;
780 }
781
782 static struct prestera_fw_evt_parser {
783 int (*func)(void *msg, struct prestera_event *evt);
784 } fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = {
785 [PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt },
786 [PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt },
787 };
788
789 static struct prestera_fw_event_handler *
__find_event_handler(const struct prestera_switch * sw,enum prestera_event_type type)790 __find_event_handler(const struct prestera_switch *sw,
791 enum prestera_event_type type)
792 {
793 struct prestera_fw_event_handler *eh;
794
795 list_for_each_entry_rcu(eh, &sw->event_handlers, list) {
796 if (eh->type == type)
797 return eh;
798 }
799
800 return NULL;
801 }
802
prestera_find_event_handler(const struct prestera_switch * sw,enum prestera_event_type type,struct prestera_fw_event_handler * eh)803 static int prestera_find_event_handler(const struct prestera_switch *sw,
804 enum prestera_event_type type,
805 struct prestera_fw_event_handler *eh)
806 {
807 struct prestera_fw_event_handler *tmp;
808 int err = 0;
809
810 rcu_read_lock();
811 tmp = __find_event_handler(sw, type);
812 if (tmp)
813 *eh = *tmp;
814 else
815 err = -ENOENT;
816 rcu_read_unlock();
817
818 return err;
819 }
820
prestera_evt_recv(struct prestera_device * dev,void * buf,size_t size)821 static int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size)
822 {
823 struct prestera_switch *sw = dev->priv;
824 struct prestera_msg_event *msg = buf;
825 struct prestera_fw_event_handler eh;
826 struct prestera_event evt;
827 u16 msg_type;
828 int err;
829
830 msg_type = __le16_to_cpu(msg->type);
831 if (msg_type >= PRESTERA_EVENT_TYPE_MAX)
832 return -EINVAL;
833 if (!fw_event_parsers[msg_type].func)
834 return -ENOENT;
835
836 err = prestera_find_event_handler(sw, msg_type, &eh);
837 if (err)
838 return err;
839
840 evt.id = __le16_to_cpu(msg->id);
841
842 err = fw_event_parsers[msg_type].func(buf, &evt);
843 if (err)
844 return err;
845
846 eh.func(sw, &evt, eh.arg);
847
848 return 0;
849 }
850
prestera_pkt_recv(struct prestera_device * dev)851 static void prestera_pkt_recv(struct prestera_device *dev)
852 {
853 struct prestera_switch *sw = dev->priv;
854 struct prestera_fw_event_handler eh;
855 struct prestera_event ev;
856 int err;
857
858 ev.id = PRESTERA_RXTX_EVENT_RCV_PKT;
859
860 err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh);
861 if (err)
862 return;
863
864 eh.func(sw, &ev, eh.arg);
865 }
866
prestera_hw_mdix_to_eth(u8 mode)867 static u8 prestera_hw_mdix_to_eth(u8 mode)
868 {
869 switch (mode) {
870 case PRESTERA_PORT_TP_MDI:
871 return ETH_TP_MDI;
872 case PRESTERA_PORT_TP_MDIX:
873 return ETH_TP_MDI_X;
874 case PRESTERA_PORT_TP_AUTO:
875 return ETH_TP_MDI_AUTO;
876 default:
877 return ETH_TP_MDI_INVALID;
878 }
879 }
880
prestera_hw_mdix_from_eth(u8 mode)881 static u8 prestera_hw_mdix_from_eth(u8 mode)
882 {
883 switch (mode) {
884 case ETH_TP_MDI:
885 return PRESTERA_PORT_TP_MDI;
886 case ETH_TP_MDI_X:
887 return PRESTERA_PORT_TP_MDIX;
888 case ETH_TP_MDI_AUTO:
889 return PRESTERA_PORT_TP_AUTO;
890 default:
891 return PRESTERA_PORT_TP_NA;
892 }
893 }
894
prestera_hw_port_info_get(const struct prestera_port * port,u32 * dev_id,u32 * hw_id,u16 * fp_id)895 int prestera_hw_port_info_get(const struct prestera_port *port,
896 u32 *dev_id, u32 *hw_id, u16 *fp_id)
897 {
898 struct prestera_msg_port_info_req req = {
899 .port = __cpu_to_le32(port->id),
900 };
901 struct prestera_msg_port_info_resp resp;
902 int err;
903
904 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET,
905 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
906 if (err)
907 return err;
908
909 *dev_id = __le32_to_cpu(resp.dev_id);
910 *hw_id = __le32_to_cpu(resp.hw_id);
911 *fp_id = __le16_to_cpu(resp.fp_id);
912
913 return 0;
914 }
915
prestera_hw_switch_mac_set(struct prestera_switch * sw,const char * mac)916 int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac)
917 {
918 struct prestera_msg_switch_attr_req req = {
919 .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_MAC),
920 };
921
922 ether_addr_copy(req.param.mac, mac);
923
924 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
925 &req.cmd, sizeof(req));
926 }
927
prestera_hw_switch_init(struct prestera_switch * sw)928 int prestera_hw_switch_init(struct prestera_switch *sw)
929 {
930 struct prestera_msg_switch_init_resp resp;
931 struct prestera_msg_common_req req;
932 int err;
933
934 INIT_LIST_HEAD(&sw->event_handlers);
935
936 prestera_hw_build_tests();
937
938 err = prestera_cmd_ret_wait(sw, PRESTERA_CMD_TYPE_SWITCH_INIT,
939 &req.cmd, sizeof(req),
940 &resp.ret, sizeof(resp),
941 PRESTERA_SWITCH_INIT_TIMEOUT_MS);
942 if (err)
943 return err;
944
945 sw->dev->recv_msg = prestera_evt_recv;
946 sw->dev->recv_pkt = prestera_pkt_recv;
947 sw->port_count = __le32_to_cpu(resp.port_count);
948 sw->mtu_min = PRESTERA_MIN_MTU;
949 sw->mtu_max = __le32_to_cpu(resp.mtu_max);
950 sw->id = resp.switch_id;
951 sw->lag_member_max = resp.lag_member_max;
952 sw->lag_max = resp.lag_max;
953
954 return 0;
955 }
956
prestera_hw_switch_fini(struct prestera_switch * sw)957 void prestera_hw_switch_fini(struct prestera_switch *sw)
958 {
959 WARN_ON(!list_empty(&sw->event_handlers));
960 }
961
prestera_hw_switch_ageing_set(struct prestera_switch * sw,u32 ageing_ms)962 int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms)
963 {
964 struct prestera_msg_switch_attr_req req = {
965 .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_AGEING),
966 .param = {
967 .ageing_timeout_ms = __cpu_to_le32(ageing_ms),
968 },
969 };
970
971 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
972 &req.cmd, sizeof(req));
973 }
974
prestera_hw_port_mac_mode_get(const struct prestera_port * port,u32 * mode,u32 * speed,u8 * duplex,u8 * fec)975 int prestera_hw_port_mac_mode_get(const struct prestera_port *port,
976 u32 *mode, u32 *speed, u8 *duplex, u8 *fec)
977 {
978 struct prestera_msg_port_attr_resp resp;
979 struct prestera_msg_port_attr_req req = {
980 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
981 .port = __cpu_to_le32(port->hw_id),
982 .dev = __cpu_to_le32(port->dev_id)
983 };
984 int err;
985
986 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
987 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
988 if (err)
989 return err;
990
991 if (mode)
992 *mode = __le32_to_cpu(resp.param.link_evt.mac.mode);
993
994 if (speed)
995 *speed = __le32_to_cpu(resp.param.link_evt.mac.speed);
996
997 if (duplex)
998 *duplex = resp.param.link_evt.mac.duplex;
999
1000 if (fec)
1001 *fec = resp.param.link_evt.mac.fec;
1002
1003 return err;
1004 }
1005
prestera_hw_port_mac_mode_set(const struct prestera_port * port,bool admin,u32 mode,u8 inband,u32 speed,u8 duplex,u8 fec)1006 int prestera_hw_port_mac_mode_set(const struct prestera_port *port,
1007 bool admin, u32 mode, u8 inband,
1008 u32 speed, u8 duplex, u8 fec)
1009 {
1010 struct prestera_msg_port_attr_req req = {
1011 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
1012 .port = __cpu_to_le32(port->hw_id),
1013 .dev = __cpu_to_le32(port->dev_id),
1014 .param = {
1015 .link = {
1016 .mac = {
1017 .admin = admin,
1018 .reg_mode.mode = __cpu_to_le32(mode),
1019 .reg_mode.inband = inband,
1020 .reg_mode.speed = __cpu_to_le32(speed),
1021 .reg_mode.duplex = duplex,
1022 .reg_mode.fec = fec
1023 }
1024 }
1025 }
1026 };
1027
1028 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1029 &req.cmd, sizeof(req));
1030 }
1031
prestera_hw_port_phy_mode_get(const struct prestera_port * port,u8 * mdix,u64 * lmode_bmap,bool * fc_pause,bool * fc_asym)1032 int prestera_hw_port_phy_mode_get(const struct prestera_port *port,
1033 u8 *mdix, u64 *lmode_bmap,
1034 bool *fc_pause, bool *fc_asym)
1035 {
1036 struct prestera_msg_port_attr_resp resp;
1037 struct prestera_msg_port_attr_req req = {
1038 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_MODE),
1039 .port = __cpu_to_le32(port->hw_id),
1040 .dev = __cpu_to_le32(port->dev_id)
1041 };
1042 int err;
1043
1044 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1045 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1046 if (err)
1047 return err;
1048
1049 if (mdix)
1050 *mdix = prestera_hw_mdix_to_eth(resp.param.link_evt.phy.mdix);
1051
1052 if (lmode_bmap)
1053 *lmode_bmap = __le64_to_cpu(resp.param.link_evt.phy.lmode_bmap);
1054
1055 if (fc_pause && fc_asym)
1056 prestera_hw_remote_fc_to_eth(resp.param.link_evt.phy.fc,
1057 fc_pause, fc_asym);
1058
1059 return err;
1060 }
1061
prestera_hw_port_phy_mode_set(const struct prestera_port * port,bool admin,bool adv,u32 mode,u64 modes,u8 mdix)1062 int prestera_hw_port_phy_mode_set(const struct prestera_port *port,
1063 bool admin, bool adv, u32 mode, u64 modes,
1064 u8 mdix)
1065 {
1066 struct prestera_msg_port_attr_req req = {
1067 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_MODE),
1068 .port = __cpu_to_le32(port->hw_id),
1069 .dev = __cpu_to_le32(port->dev_id),
1070 .param = {
1071 .link = {
1072 .phy = {
1073 .admin = admin,
1074 .adv_enable = adv ? 1 : 0,
1075 .mode = __cpu_to_le32(mode),
1076 .modes = __cpu_to_le64(modes),
1077 }
1078 }
1079 }
1080 };
1081
1082 req.param.link.phy.mdix = prestera_hw_mdix_from_eth(mdix);
1083
1084 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1085 &req.cmd, sizeof(req));
1086 }
1087
prestera_hw_port_mtu_set(const struct prestera_port * port,u32 mtu)1088 int prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu)
1089 {
1090 struct prestera_msg_port_attr_req req = {
1091 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MTU),
1092 .port = __cpu_to_le32(port->hw_id),
1093 .dev = __cpu_to_le32(port->dev_id),
1094 .param = {
1095 .mtu = __cpu_to_le32(mtu),
1096 }
1097 };
1098
1099 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1100 &req.cmd, sizeof(req));
1101 }
1102
prestera_hw_port_mac_set(const struct prestera_port * port,const char * mac)1103 int prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac)
1104 {
1105 struct prestera_msg_port_attr_req req = {
1106 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC),
1107 .port = __cpu_to_le32(port->hw_id),
1108 .dev = __cpu_to_le32(port->dev_id),
1109 };
1110
1111 ether_addr_copy(req.param.mac, mac);
1112
1113 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1114 &req.cmd, sizeof(req));
1115 }
1116
prestera_hw_port_accept_frm_type(struct prestera_port * port,enum prestera_accept_frm_type type)1117 int prestera_hw_port_accept_frm_type(struct prestera_port *port,
1118 enum prestera_accept_frm_type type)
1119 {
1120 struct prestera_msg_port_attr_req req = {
1121 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE),
1122 .port = __cpu_to_le32(port->hw_id),
1123 .dev = __cpu_to_le32(port->dev_id),
1124 .param = {
1125 .accept_frm_type = type,
1126 }
1127 };
1128
1129 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1130 &req.cmd, sizeof(req));
1131 }
1132
prestera_hw_port_cap_get(const struct prestera_port * port,struct prestera_port_caps * caps)1133 int prestera_hw_port_cap_get(const struct prestera_port *port,
1134 struct prestera_port_caps *caps)
1135 {
1136 struct prestera_msg_port_attr_req req = {
1137 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_CAPABILITY),
1138 .port = __cpu_to_le32(port->hw_id),
1139 .dev = __cpu_to_le32(port->dev_id),
1140 };
1141 struct prestera_msg_port_attr_resp resp;
1142 int err;
1143
1144 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1145 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1146 if (err)
1147 return err;
1148
1149 caps->supp_link_modes = __le64_to_cpu(resp.param.cap.link_mode);
1150 caps->transceiver = resp.param.cap.transceiver;
1151 caps->supp_fec = resp.param.cap.fec;
1152 caps->type = resp.param.cap.type;
1153
1154 return err;
1155 }
1156
prestera_hw_remote_fc_to_eth(u8 fc,bool * pause,bool * asym_pause)1157 static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause)
1158 {
1159 switch (fc) {
1160 case PRESTERA_FC_SYMMETRIC:
1161 *pause = true;
1162 *asym_pause = false;
1163 break;
1164 case PRESTERA_FC_ASYMMETRIC:
1165 *pause = false;
1166 *asym_pause = true;
1167 break;
1168 case PRESTERA_FC_SYMM_ASYMM:
1169 *pause = true;
1170 *asym_pause = true;
1171 break;
1172 default:
1173 *pause = false;
1174 *asym_pause = false;
1175 }
1176 }
1177
prestera_hw_vtcam_create(struct prestera_switch * sw,u8 lookup,const u32 * keymask,u32 * vtcam_id,enum prestera_hw_vtcam_direction_t dir)1178 int prestera_hw_vtcam_create(struct prestera_switch *sw,
1179 u8 lookup, const u32 *keymask, u32 *vtcam_id,
1180 enum prestera_hw_vtcam_direction_t dir)
1181 {
1182 int err;
1183 struct prestera_msg_vtcam_resp resp;
1184 struct prestera_msg_vtcam_create_req req = {
1185 .lookup = lookup,
1186 .direction = dir,
1187 };
1188
1189 if (keymask)
1190 memcpy(req.keymask, keymask, sizeof(req.keymask));
1191 else
1192 memset(req.keymask, 0, sizeof(req.keymask));
1193
1194 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_CREATE,
1195 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1196 if (err)
1197 return err;
1198
1199 *vtcam_id = __le32_to_cpu(resp.vtcam_id);
1200 return 0;
1201 }
1202
prestera_hw_vtcam_destroy(struct prestera_switch * sw,u32 vtcam_id)1203 int prestera_hw_vtcam_destroy(struct prestera_switch *sw, u32 vtcam_id)
1204 {
1205 struct prestera_msg_vtcam_destroy_req req = {
1206 .vtcam_id = __cpu_to_le32(vtcam_id),
1207 };
1208
1209 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_DESTROY,
1210 &req.cmd, sizeof(req));
1211 }
1212
1213 static int
prestera_acl_rule_add_put_action(struct prestera_msg_acl_action * action,struct prestera_acl_hw_action_info * info)1214 prestera_acl_rule_add_put_action(struct prestera_msg_acl_action *action,
1215 struct prestera_acl_hw_action_info *info)
1216 {
1217 action->id = __cpu_to_le32(info->id);
1218
1219 switch (info->id) {
1220 case PRESTERA_ACL_RULE_ACTION_ACCEPT:
1221 case PRESTERA_ACL_RULE_ACTION_DROP:
1222 case PRESTERA_ACL_RULE_ACTION_TRAP:
1223 /* just rule action id, no specific data */
1224 break;
1225 case PRESTERA_ACL_RULE_ACTION_JUMP:
1226 action->jump.index = __cpu_to_le32(info->jump.index);
1227 break;
1228 case PRESTERA_ACL_RULE_ACTION_POLICE:
1229 action->police.id = __cpu_to_le32(info->police.id);
1230 break;
1231 case PRESTERA_ACL_RULE_ACTION_COUNT:
1232 action->count.id = __cpu_to_le32(info->count.id);
1233 break;
1234 default:
1235 return -EINVAL;
1236 }
1237
1238 return 0;
1239 }
1240
prestera_hw_vtcam_rule_add(struct prestera_switch * sw,u32 vtcam_id,u32 prio,void * key,void * keymask,struct prestera_acl_hw_action_info * act,u8 n_act,u32 * rule_id)1241 int prestera_hw_vtcam_rule_add(struct prestera_switch *sw,
1242 u32 vtcam_id, u32 prio, void *key, void *keymask,
1243 struct prestera_acl_hw_action_info *act,
1244 u8 n_act, u32 *rule_id)
1245 {
1246 struct prestera_msg_acl_action *actions_msg;
1247 struct prestera_msg_vtcam_rule_add_req *req;
1248 struct prestera_msg_vtcam_resp resp;
1249 void *buff;
1250 u32 size;
1251 int err;
1252 u8 i;
1253
1254 size = sizeof(*req) + sizeof(*actions_msg) * n_act;
1255
1256 buff = kzalloc(size, GFP_KERNEL);
1257 if (!buff)
1258 return -ENOMEM;
1259
1260 req = buff;
1261 req->n_act = __cpu_to_le32(n_act);
1262 actions_msg = buff + sizeof(*req);
1263
1264 /* put acl matches into the message */
1265 memcpy(req->key, key, sizeof(req->key));
1266 memcpy(req->keymask, keymask, sizeof(req->keymask));
1267
1268 /* put acl actions into the message */
1269 for (i = 0; i < n_act; i++) {
1270 err = prestera_acl_rule_add_put_action(&actions_msg[i],
1271 &act[i]);
1272 if (err)
1273 goto free_buff;
1274 }
1275
1276 req->vtcam_id = __cpu_to_le32(vtcam_id);
1277 req->prio = __cpu_to_le32(prio);
1278
1279 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_ADD,
1280 &req->cmd, size, &resp.ret, sizeof(resp));
1281 if (err)
1282 goto free_buff;
1283
1284 *rule_id = __le32_to_cpu(resp.rule_id);
1285 free_buff:
1286 kfree(buff);
1287 return err;
1288 }
1289
prestera_hw_vtcam_rule_del(struct prestera_switch * sw,u32 vtcam_id,u32 rule_id)1290 int prestera_hw_vtcam_rule_del(struct prestera_switch *sw,
1291 u32 vtcam_id, u32 rule_id)
1292 {
1293 struct prestera_msg_vtcam_rule_del_req req = {
1294 .vtcam_id = __cpu_to_le32(vtcam_id),
1295 .id = __cpu_to_le32(rule_id)
1296 };
1297
1298 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_DELETE,
1299 &req.cmd, sizeof(req));
1300 }
1301
prestera_hw_vtcam_iface_bind(struct prestera_switch * sw,struct prestera_acl_iface * iface,u32 vtcam_id,u16 pcl_id)1302 int prestera_hw_vtcam_iface_bind(struct prestera_switch *sw,
1303 struct prestera_acl_iface *iface,
1304 u32 vtcam_id, u16 pcl_id)
1305 {
1306 struct prestera_msg_vtcam_bind_req req = {
1307 .vtcam_id = __cpu_to_le32(vtcam_id),
1308 .type = __cpu_to_le16(iface->type),
1309 .pcl_id = __cpu_to_le16(pcl_id)
1310 };
1311
1312 if (iface->type == PRESTERA_ACL_IFACE_TYPE_PORT) {
1313 req.port.dev_id = __cpu_to_le32(iface->port->dev_id);
1314 req.port.hw_id = __cpu_to_le32(iface->port->hw_id);
1315 } else {
1316 req.index = __cpu_to_le32(iface->index);
1317 }
1318
1319 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_BIND,
1320 &req.cmd, sizeof(req));
1321 }
1322
prestera_hw_vtcam_iface_unbind(struct prestera_switch * sw,struct prestera_acl_iface * iface,u32 vtcam_id)1323 int prestera_hw_vtcam_iface_unbind(struct prestera_switch *sw,
1324 struct prestera_acl_iface *iface,
1325 u32 vtcam_id)
1326 {
1327 struct prestera_msg_vtcam_bind_req req = {
1328 .vtcam_id = __cpu_to_le32(vtcam_id),
1329 .type = __cpu_to_le16(iface->type)
1330 };
1331
1332 if (iface->type == PRESTERA_ACL_IFACE_TYPE_PORT) {
1333 req.port.dev_id = __cpu_to_le32(iface->port->dev_id);
1334 req.port.hw_id = __cpu_to_le32(iface->port->hw_id);
1335 } else {
1336 req.index = __cpu_to_le32(iface->index);
1337 }
1338
1339 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_UNBIND,
1340 &req.cmd, sizeof(req));
1341 }
1342
prestera_hw_span_get(const struct prestera_port * port,u8 * span_id)1343 int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id)
1344 {
1345 struct prestera_msg_span_resp resp;
1346 struct prestera_msg_span_req req = {
1347 .port = __cpu_to_le32(port->hw_id),
1348 .dev = __cpu_to_le32(port->dev_id),
1349 };
1350 int err;
1351
1352 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_SPAN_GET,
1353 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1354 if (err)
1355 return err;
1356
1357 *span_id = resp.id;
1358
1359 return 0;
1360 }
1361
prestera_hw_span_bind(const struct prestera_port * port,u8 span_id)1362 int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id)
1363 {
1364 struct prestera_msg_span_req req = {
1365 .port = __cpu_to_le32(port->hw_id),
1366 .dev = __cpu_to_le32(port->dev_id),
1367 .id = span_id,
1368 };
1369
1370 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_BIND,
1371 &req.cmd, sizeof(req));
1372 }
1373
prestera_hw_span_unbind(const struct prestera_port * port)1374 int prestera_hw_span_unbind(const struct prestera_port *port)
1375 {
1376 struct prestera_msg_span_req req = {
1377 .port = __cpu_to_le32(port->hw_id),
1378 .dev = __cpu_to_le32(port->dev_id),
1379 };
1380
1381 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_UNBIND,
1382 &req.cmd, sizeof(req));
1383 }
1384
prestera_hw_span_release(struct prestera_switch * sw,u8 span_id)1385 int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id)
1386 {
1387 struct prestera_msg_span_req req = {
1388 .id = span_id
1389 };
1390
1391 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SPAN_RELEASE,
1392 &req.cmd, sizeof(req));
1393 }
1394
prestera_hw_port_type_get(const struct prestera_port * port,u8 * type)1395 int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
1396 {
1397 struct prestera_msg_port_attr_req req = {
1398 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_TYPE),
1399 .port = __cpu_to_le32(port->hw_id),
1400 .dev = __cpu_to_le32(port->dev_id),
1401 };
1402 struct prestera_msg_port_attr_resp resp;
1403 int err;
1404
1405 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1406 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1407 if (err)
1408 return err;
1409
1410 *type = resp.param.type;
1411
1412 return 0;
1413 }
1414
prestera_hw_port_speed_get(const struct prestera_port * port,u32 * speed)1415 int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed)
1416 {
1417 struct prestera_msg_port_attr_req req = {
1418 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_SPEED),
1419 .port = __cpu_to_le32(port->hw_id),
1420 .dev = __cpu_to_le32(port->dev_id),
1421 };
1422 struct prestera_msg_port_attr_resp resp;
1423 int err;
1424
1425 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1426 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1427 if (err)
1428 return err;
1429
1430 *speed = __le32_to_cpu(resp.param.speed);
1431
1432 return 0;
1433 }
1434
prestera_hw_port_autoneg_restart(struct prestera_port * port)1435 int prestera_hw_port_autoneg_restart(struct prestera_port *port)
1436 {
1437 struct prestera_msg_port_attr_req req = {
1438 .attr =
1439 __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART),
1440 .port = __cpu_to_le32(port->hw_id),
1441 .dev = __cpu_to_le32(port->dev_id),
1442 };
1443
1444 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1445 &req.cmd, sizeof(req));
1446 }
1447
prestera_hw_port_stats_get(const struct prestera_port * port,struct prestera_port_stats * st)1448 int prestera_hw_port_stats_get(const struct prestera_port *port,
1449 struct prestera_port_stats *st)
1450 {
1451 struct prestera_msg_port_attr_req req = {
1452 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_STATS),
1453 .port = __cpu_to_le32(port->hw_id),
1454 .dev = __cpu_to_le32(port->dev_id),
1455 };
1456 struct prestera_msg_port_stats_resp resp;
1457 __le64 *hw = resp.stats;
1458 int err;
1459
1460 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1461 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1462 if (err)
1463 return err;
1464
1465 st->good_octets_received =
1466 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_RCV_CNT]);
1467 st->bad_octets_received =
1468 __le64_to_cpu(hw[PRESTERA_PORT_BAD_OCTETS_RCV_CNT]);
1469 st->mac_trans_error =
1470 __le64_to_cpu(hw[PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT]);
1471 st->broadcast_frames_received =
1472 __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_RCV_CNT]);
1473 st->multicast_frames_received =
1474 __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_RCV_CNT]);
1475 st->frames_64_octets = __le64_to_cpu(hw[PRESTERA_PORT_PKTS_64L_CNT]);
1476 st->frames_65_to_127_octets =
1477 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_65TO127L_CNT]);
1478 st->frames_128_to_255_octets =
1479 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_128TO255L_CNT]);
1480 st->frames_256_to_511_octets =
1481 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_256TO511L_CNT]);
1482 st->frames_512_to_1023_octets =
1483 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_512TO1023L_CNT]);
1484 st->frames_1024_to_max_octets =
1485 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_1024TOMAXL_CNT]);
1486 st->excessive_collision =
1487 __le64_to_cpu(hw[PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT]);
1488 st->multicast_frames_sent =
1489 __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_SENT_CNT]);
1490 st->broadcast_frames_sent =
1491 __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_SENT_CNT]);
1492 st->fc_sent = __le64_to_cpu(hw[PRESTERA_PORT_FC_SENT_CNT]);
1493 st->fc_received = __le64_to_cpu(hw[PRESTERA_PORT_GOOD_FC_RCV_CNT]);
1494 st->buffer_overrun = __le64_to_cpu(hw[PRESTERA_PORT_DROP_EVENTS_CNT]);
1495 st->undersize = __le64_to_cpu(hw[PRESTERA_PORT_UNDERSIZE_PKTS_CNT]);
1496 st->fragments = __le64_to_cpu(hw[PRESTERA_PORT_FRAGMENTS_PKTS_CNT]);
1497 st->oversize = __le64_to_cpu(hw[PRESTERA_PORT_OVERSIZE_PKTS_CNT]);
1498 st->jabber = __le64_to_cpu(hw[PRESTERA_PORT_JABBER_PKTS_CNT]);
1499 st->rx_error_frame_received =
1500 __le64_to_cpu(hw[PRESTERA_PORT_MAC_RCV_ERROR_CNT]);
1501 st->bad_crc = __le64_to_cpu(hw[PRESTERA_PORT_BAD_CRC_CNT]);
1502 st->collisions = __le64_to_cpu(hw[PRESTERA_PORT_COLLISIONS_CNT]);
1503 st->late_collision =
1504 __le64_to_cpu(hw[PRESTERA_PORT_LATE_COLLISIONS_CNT]);
1505 st->unicast_frames_received =
1506 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT]);
1507 st->unicast_frames_sent =
1508 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT]);
1509 st->sent_multiple =
1510 __le64_to_cpu(hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT]);
1511 st->sent_deferred =
1512 __le64_to_cpu(hw[PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT]);
1513 st->good_octets_sent =
1514 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT]);
1515
1516 return 0;
1517 }
1518
prestera_hw_port_learning_set(struct prestera_port * port,bool enable)1519 int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
1520 {
1521 struct prestera_msg_port_attr_req req = {
1522 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_LEARNING),
1523 .port = __cpu_to_le32(port->hw_id),
1524 .dev = __cpu_to_le32(port->dev_id),
1525 .param = {
1526 .learning = enable,
1527 }
1528 };
1529
1530 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1531 &req.cmd, sizeof(req));
1532 }
1533
prestera_hw_port_uc_flood_set(struct prestera_port * port,bool flood)1534 static int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood)
1535 {
1536 struct prestera_msg_port_attr_req req = {
1537 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1538 .port = __cpu_to_le32(port->hw_id),
1539 .dev = __cpu_to_le32(port->dev_id),
1540 .param = {
1541 .flood_ext = {
1542 .type = PRESTERA_PORT_FLOOD_TYPE_UC,
1543 .enable = flood,
1544 }
1545 }
1546 };
1547
1548 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1549 &req.cmd, sizeof(req));
1550 }
1551
prestera_hw_port_mc_flood_set(struct prestera_port * port,bool flood)1552 static int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood)
1553 {
1554 struct prestera_msg_port_attr_req req = {
1555 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1556 .port = __cpu_to_le32(port->hw_id),
1557 .dev = __cpu_to_le32(port->dev_id),
1558 .param = {
1559 .flood_ext = {
1560 .type = PRESTERA_PORT_FLOOD_TYPE_MC,
1561 .enable = flood,
1562 }
1563 }
1564 };
1565
1566 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1567 &req.cmd, sizeof(req));
1568 }
1569
prestera_hw_port_flood_set_v2(struct prestera_port * port,bool flood)1570 static int prestera_hw_port_flood_set_v2(struct prestera_port *port, bool flood)
1571 {
1572 struct prestera_msg_port_attr_req req = {
1573 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1574 .port = __cpu_to_le32(port->hw_id),
1575 .dev = __cpu_to_le32(port->dev_id),
1576 .param = {
1577 .flood = flood,
1578 }
1579 };
1580
1581 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1582 &req.cmd, sizeof(req));
1583 }
1584
prestera_hw_port_flood_set(struct prestera_port * port,unsigned long mask,unsigned long val)1585 int prestera_hw_port_flood_set(struct prestera_port *port, unsigned long mask,
1586 unsigned long val)
1587 {
1588 int err;
1589
1590 if (port->sw->dev->fw_rev.maj <= 2) {
1591 if (!(mask & BR_FLOOD))
1592 return 0;
1593
1594 return prestera_hw_port_flood_set_v2(port, val & BR_FLOOD);
1595 }
1596
1597 if (mask & BR_FLOOD) {
1598 err = prestera_hw_port_uc_flood_set(port, val & BR_FLOOD);
1599 if (err)
1600 goto err_uc_flood;
1601 }
1602
1603 if (mask & BR_MCAST_FLOOD) {
1604 err = prestera_hw_port_mc_flood_set(port, val & BR_MCAST_FLOOD);
1605 if (err)
1606 goto err_mc_flood;
1607 }
1608
1609 return 0;
1610
1611 err_mc_flood:
1612 prestera_hw_port_mc_flood_set(port, 0);
1613 err_uc_flood:
1614 if (mask & BR_FLOOD)
1615 prestera_hw_port_uc_flood_set(port, 0);
1616
1617 return err;
1618 }
1619
prestera_hw_vlan_create(struct prestera_switch * sw,u16 vid)1620 int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
1621 {
1622 struct prestera_msg_vlan_req req = {
1623 .vid = __cpu_to_le16(vid),
1624 };
1625
1626 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE,
1627 &req.cmd, sizeof(req));
1628 }
1629
prestera_hw_vlan_delete(struct prestera_switch * sw,u16 vid)1630 int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid)
1631 {
1632 struct prestera_msg_vlan_req req = {
1633 .vid = __cpu_to_le16(vid),
1634 };
1635
1636 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE,
1637 &req.cmd, sizeof(req));
1638 }
1639
prestera_hw_vlan_port_set(struct prestera_port * port,u16 vid,bool is_member,bool untagged)1640 int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid,
1641 bool is_member, bool untagged)
1642 {
1643 struct prestera_msg_vlan_req req = {
1644 .port = __cpu_to_le32(port->hw_id),
1645 .dev = __cpu_to_le32(port->dev_id),
1646 .vid = __cpu_to_le16(vid),
1647 .is_member = is_member,
1648 .is_tagged = !untagged,
1649 };
1650
1651 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET,
1652 &req.cmd, sizeof(req));
1653 }
1654
prestera_hw_vlan_port_vid_set(struct prestera_port * port,u16 vid)1655 int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid)
1656 {
1657 struct prestera_msg_vlan_req req = {
1658 .port = __cpu_to_le32(port->hw_id),
1659 .dev = __cpu_to_le32(port->dev_id),
1660 .vid = __cpu_to_le16(vid),
1661 };
1662
1663 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET,
1664 &req.cmd, sizeof(req));
1665 }
1666
prestera_hw_vlan_port_stp_set(struct prestera_port * port,u16 vid,u8 state)1667 int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state)
1668 {
1669 struct prestera_msg_stp_req req = {
1670 .port = __cpu_to_le32(port->hw_id),
1671 .dev = __cpu_to_le32(port->dev_id),
1672 .vid = __cpu_to_le16(vid),
1673 .state = state,
1674 };
1675
1676 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET,
1677 &req.cmd, sizeof(req));
1678 }
1679
prestera_hw_fdb_add(struct prestera_port * port,const unsigned char * mac,u16 vid,bool dynamic)1680 int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac,
1681 u16 vid, bool dynamic)
1682 {
1683 struct prestera_msg_fdb_req req = {
1684 .dest = {
1685 .dev = __cpu_to_le32(port->dev_id),
1686 .port = __cpu_to_le32(port->hw_id),
1687 },
1688 .vid = __cpu_to_le16(vid),
1689 .dynamic = dynamic,
1690 };
1691
1692 ether_addr_copy(req.mac, mac);
1693
1694 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD,
1695 &req.cmd, sizeof(req));
1696 }
1697
prestera_hw_fdb_del(struct prestera_port * port,const unsigned char * mac,u16 vid)1698 int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac,
1699 u16 vid)
1700 {
1701 struct prestera_msg_fdb_req req = {
1702 .dest = {
1703 .dev = __cpu_to_le32(port->dev_id),
1704 .port = __cpu_to_le32(port->hw_id),
1705 },
1706 .vid = __cpu_to_le16(vid),
1707 };
1708
1709 ether_addr_copy(req.mac, mac);
1710
1711 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1712 &req.cmd, sizeof(req));
1713 }
1714
prestera_hw_lag_fdb_add(struct prestera_switch * sw,u16 lag_id,const unsigned char * mac,u16 vid,bool dynamic)1715 int prestera_hw_lag_fdb_add(struct prestera_switch *sw, u16 lag_id,
1716 const unsigned char *mac, u16 vid, bool dynamic)
1717 {
1718 struct prestera_msg_fdb_req req = {
1719 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1720 .dest = {
1721 .lag_id = __cpu_to_le16(lag_id),
1722 },
1723 .vid = __cpu_to_le16(vid),
1724 .dynamic = dynamic,
1725 };
1726
1727 ether_addr_copy(req.mac, mac);
1728
1729 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_ADD,
1730 &req.cmd, sizeof(req));
1731 }
1732
prestera_hw_lag_fdb_del(struct prestera_switch * sw,u16 lag_id,const unsigned char * mac,u16 vid)1733 int prestera_hw_lag_fdb_del(struct prestera_switch *sw, u16 lag_id,
1734 const unsigned char *mac, u16 vid)
1735 {
1736 struct prestera_msg_fdb_req req = {
1737 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1738 .dest = {
1739 .lag_id = __cpu_to_le16(lag_id),
1740 },
1741 .vid = __cpu_to_le16(vid),
1742 };
1743
1744 ether_addr_copy(req.mac, mac);
1745
1746 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1747 &req.cmd, sizeof(req));
1748 }
1749
prestera_hw_fdb_flush_port(struct prestera_port * port,u32 mode)1750 int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode)
1751 {
1752 struct prestera_msg_fdb_req req = {
1753 .dest = {
1754 .dev = __cpu_to_le32(port->dev_id),
1755 .port = __cpu_to_le32(port->hw_id),
1756 },
1757 .flush_mode = __cpu_to_le32(mode),
1758 };
1759
1760 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1761 &req.cmd, sizeof(req));
1762 }
1763
prestera_hw_fdb_flush_vlan(struct prestera_switch * sw,u16 vid,u32 mode)1764 int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode)
1765 {
1766 struct prestera_msg_fdb_req req = {
1767 .vid = __cpu_to_le16(vid),
1768 .flush_mode = __cpu_to_le32(mode),
1769 };
1770
1771 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN,
1772 &req.cmd, sizeof(req));
1773 }
1774
prestera_hw_fdb_flush_port_vlan(struct prestera_port * port,u16 vid,u32 mode)1775 int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
1776 u32 mode)
1777 {
1778 struct prestera_msg_fdb_req req = {
1779 .dest = {
1780 .dev = __cpu_to_le32(port->dev_id),
1781 .port = __cpu_to_le32(port->hw_id),
1782 },
1783 .vid = __cpu_to_le16(vid),
1784 .flush_mode = __cpu_to_le32(mode),
1785 };
1786
1787 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1788 &req.cmd, sizeof(req));
1789 }
1790
prestera_hw_fdb_flush_lag(struct prestera_switch * sw,u16 lag_id,u32 mode)1791 int prestera_hw_fdb_flush_lag(struct prestera_switch *sw, u16 lag_id,
1792 u32 mode)
1793 {
1794 struct prestera_msg_fdb_req req = {
1795 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1796 .dest = {
1797 .lag_id = __cpu_to_le16(lag_id),
1798 },
1799 .flush_mode = __cpu_to_le32(mode),
1800 };
1801
1802 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1803 &req.cmd, sizeof(req));
1804 }
1805
prestera_hw_fdb_flush_lag_vlan(struct prestera_switch * sw,u16 lag_id,u16 vid,u32 mode)1806 int prestera_hw_fdb_flush_lag_vlan(struct prestera_switch *sw,
1807 u16 lag_id, u16 vid, u32 mode)
1808 {
1809 struct prestera_msg_fdb_req req = {
1810 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1811 .dest = {
1812 .lag_id = __cpu_to_le16(lag_id),
1813 },
1814 .vid = __cpu_to_le16(vid),
1815 .flush_mode = __cpu_to_le32(mode),
1816 };
1817
1818 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1819 &req.cmd, sizeof(req));
1820 }
1821
prestera_hw_bridge_create(struct prestera_switch * sw,u16 * bridge_id)1822 int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id)
1823 {
1824 struct prestera_msg_bridge_resp resp;
1825 struct prestera_msg_bridge_req req;
1826 int err;
1827
1828 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE,
1829 &req.cmd, sizeof(req),
1830 &resp.ret, sizeof(resp));
1831 if (err)
1832 return err;
1833
1834 *bridge_id = __le16_to_cpu(resp.bridge);
1835
1836 return 0;
1837 }
1838
prestera_hw_bridge_delete(struct prestera_switch * sw,u16 bridge_id)1839 int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id)
1840 {
1841 struct prestera_msg_bridge_req req = {
1842 .bridge = __cpu_to_le16(bridge_id),
1843 };
1844
1845 return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE,
1846 &req.cmd, sizeof(req));
1847 }
1848
prestera_hw_bridge_port_add(struct prestera_port * port,u16 bridge_id)1849 int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id)
1850 {
1851 struct prestera_msg_bridge_req req = {
1852 .bridge = __cpu_to_le16(bridge_id),
1853 .port = __cpu_to_le32(port->hw_id),
1854 .dev = __cpu_to_le32(port->dev_id),
1855 };
1856
1857 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD,
1858 &req.cmd, sizeof(req));
1859 }
1860
prestera_hw_bridge_port_delete(struct prestera_port * port,u16 bridge_id)1861 int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)
1862 {
1863 struct prestera_msg_bridge_req req = {
1864 .bridge = __cpu_to_le16(bridge_id),
1865 .port = __cpu_to_le32(port->hw_id),
1866 .dev = __cpu_to_le32(port->dev_id),
1867 };
1868
1869 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE,
1870 &req.cmd, sizeof(req));
1871 }
1872
prestera_iface_to_msg(struct prestera_iface * iface,struct prestera_msg_iface * msg_if)1873 static int prestera_iface_to_msg(struct prestera_iface *iface,
1874 struct prestera_msg_iface *msg_if)
1875 {
1876 switch (iface->type) {
1877 case PRESTERA_IF_PORT_E:
1878 case PRESTERA_IF_VID_E:
1879 msg_if->port = __cpu_to_le32(iface->dev_port.port_num);
1880 msg_if->dev = __cpu_to_le32(iface->dev_port.hw_dev_num);
1881 break;
1882 case PRESTERA_IF_LAG_E:
1883 msg_if->lag_id = __cpu_to_le16(iface->lag_id);
1884 break;
1885 default:
1886 return -EOPNOTSUPP;
1887 }
1888
1889 msg_if->vr_id = __cpu_to_le16(iface->vr_id);
1890 msg_if->vid = __cpu_to_le16(iface->vlan_id);
1891 msg_if->type = iface->type;
1892 return 0;
1893 }
1894
prestera_hw_rif_create(struct prestera_switch * sw,struct prestera_iface * iif,u8 * mac,u16 * rif_id)1895 int prestera_hw_rif_create(struct prestera_switch *sw,
1896 struct prestera_iface *iif, u8 *mac, u16 *rif_id)
1897 {
1898 struct prestera_msg_rif_resp resp;
1899 struct prestera_msg_rif_req req;
1900 int err;
1901
1902 memcpy(req.mac, mac, ETH_ALEN);
1903
1904 err = prestera_iface_to_msg(iif, &req.iif);
1905 if (err)
1906 return err;
1907
1908 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_CREATE,
1909 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1910 if (err)
1911 return err;
1912
1913 *rif_id = __le16_to_cpu(resp.rif_id);
1914 return err;
1915 }
1916
prestera_hw_rif_delete(struct prestera_switch * sw,u16 rif_id,struct prestera_iface * iif)1917 int prestera_hw_rif_delete(struct prestera_switch *sw, u16 rif_id,
1918 struct prestera_iface *iif)
1919 {
1920 struct prestera_msg_rif_req req = {
1921 .rif_id = __cpu_to_le16(rif_id),
1922 };
1923 int err;
1924
1925 err = prestera_iface_to_msg(iif, &req.iif);
1926 if (err)
1927 return err;
1928
1929 return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE, &req.cmd,
1930 sizeof(req));
1931 }
1932
prestera_hw_vr_create(struct prestera_switch * sw,u16 * vr_id)1933 int prestera_hw_vr_create(struct prestera_switch *sw, u16 *vr_id)
1934 {
1935 struct prestera_msg_vr_resp resp;
1936 struct prestera_msg_vr_req req;
1937 int err;
1938
1939 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_VR_CREATE,
1940 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1941 if (err)
1942 return err;
1943
1944 *vr_id = __le16_to_cpu(resp.vr_id);
1945 return err;
1946 }
1947
prestera_hw_vr_delete(struct prestera_switch * sw,u16 vr_id)1948 int prestera_hw_vr_delete(struct prestera_switch *sw, u16 vr_id)
1949 {
1950 struct prestera_msg_vr_req req = {
1951 .vr_id = __cpu_to_le16(vr_id),
1952 };
1953
1954 return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_VR_DELETE, &req.cmd,
1955 sizeof(req));
1956 }
1957
prestera_hw_lpm_add(struct prestera_switch * sw,u16 vr_id,__be32 dst,u32 dst_len,u32 grp_id)1958 int prestera_hw_lpm_add(struct prestera_switch *sw, u16 vr_id,
1959 __be32 dst, u32 dst_len, u32 grp_id)
1960 {
1961 struct prestera_msg_lpm_req req = {
1962 .dst_len = __cpu_to_le32(dst_len),
1963 .vr_id = __cpu_to_le16(vr_id),
1964 .grp_id = __cpu_to_le32(grp_id),
1965 .dst.u.ipv4 = dst
1966 };
1967
1968 return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_ADD, &req.cmd,
1969 sizeof(req));
1970 }
1971
prestera_hw_lpm_del(struct prestera_switch * sw,u16 vr_id,__be32 dst,u32 dst_len)1972 int prestera_hw_lpm_del(struct prestera_switch *sw, u16 vr_id,
1973 __be32 dst, u32 dst_len)
1974 {
1975 struct prestera_msg_lpm_req req = {
1976 .dst_len = __cpu_to_le32(dst_len),
1977 .vr_id = __cpu_to_le16(vr_id),
1978 .dst.u.ipv4 = dst
1979 };
1980
1981 return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_DELETE, &req.cmd,
1982 sizeof(req));
1983 }
1984
prestera_hw_rxtx_init(struct prestera_switch * sw,struct prestera_rxtx_params * params)1985 int prestera_hw_rxtx_init(struct prestera_switch *sw,
1986 struct prestera_rxtx_params *params)
1987 {
1988 struct prestera_msg_rxtx_resp resp;
1989 struct prestera_msg_rxtx_req req;
1990 int err;
1991
1992 req.use_sdma = params->use_sdma;
1993
1994 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT,
1995 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1996 if (err)
1997 return err;
1998
1999 params->map_addr = __le32_to_cpu(resp.map_addr);
2000
2001 return 0;
2002 }
2003
prestera_hw_lag_member_add(struct prestera_port * port,u16 lag_id)2004 int prestera_hw_lag_member_add(struct prestera_port *port, u16 lag_id)
2005 {
2006 struct prestera_msg_lag_req req = {
2007 .port = __cpu_to_le32(port->hw_id),
2008 .dev = __cpu_to_le32(port->dev_id),
2009 .lag_id = __cpu_to_le16(lag_id),
2010 };
2011
2012 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_ADD,
2013 &req.cmd, sizeof(req));
2014 }
2015
prestera_hw_lag_member_del(struct prestera_port * port,u16 lag_id)2016 int prestera_hw_lag_member_del(struct prestera_port *port, u16 lag_id)
2017 {
2018 struct prestera_msg_lag_req req = {
2019 .port = __cpu_to_le32(port->hw_id),
2020 .dev = __cpu_to_le32(port->dev_id),
2021 .lag_id = __cpu_to_le16(lag_id),
2022 };
2023
2024 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE,
2025 &req.cmd, sizeof(req));
2026 }
2027
prestera_hw_lag_member_enable(struct prestera_port * port,u16 lag_id,bool enable)2028 int prestera_hw_lag_member_enable(struct prestera_port *port, u16 lag_id,
2029 bool enable)
2030 {
2031 struct prestera_msg_lag_req req = {
2032 .port = __cpu_to_le32(port->hw_id),
2033 .dev = __cpu_to_le32(port->dev_id),
2034 .lag_id = __cpu_to_le16(lag_id),
2035 };
2036 u32 cmd;
2037
2038 cmd = enable ? PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE :
2039 PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE;
2040
2041 return prestera_cmd(port->sw, cmd, &req.cmd, sizeof(req));
2042 }
2043
2044 int
prestera_hw_cpu_code_counters_get(struct prestera_switch * sw,u8 code,enum prestera_hw_cpu_code_cnt_t counter_type,u64 * packet_count)2045 prestera_hw_cpu_code_counters_get(struct prestera_switch *sw, u8 code,
2046 enum prestera_hw_cpu_code_cnt_t counter_type,
2047 u64 *packet_count)
2048 {
2049 struct prestera_msg_cpu_code_counter_req req = {
2050 .counter_type = counter_type,
2051 .code = code,
2052 };
2053 struct mvsw_msg_cpu_code_counter_ret resp;
2054 int err;
2055
2056 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET,
2057 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2058 if (err)
2059 return err;
2060
2061 *packet_count = __le64_to_cpu(resp.packet_count);
2062
2063 return 0;
2064 }
2065
prestera_hw_event_handler_register(struct prestera_switch * sw,enum prestera_event_type type,prestera_event_cb_t fn,void * arg)2066 int prestera_hw_event_handler_register(struct prestera_switch *sw,
2067 enum prestera_event_type type,
2068 prestera_event_cb_t fn,
2069 void *arg)
2070 {
2071 struct prestera_fw_event_handler *eh;
2072
2073 eh = __find_event_handler(sw, type);
2074 if (eh)
2075 return -EEXIST;
2076
2077 eh = kmalloc(sizeof(*eh), GFP_KERNEL);
2078 if (!eh)
2079 return -ENOMEM;
2080
2081 eh->type = type;
2082 eh->func = fn;
2083 eh->arg = arg;
2084
2085 INIT_LIST_HEAD(&eh->list);
2086
2087 list_add_rcu(&eh->list, &sw->event_handlers);
2088
2089 return 0;
2090 }
2091
prestera_hw_event_handler_unregister(struct prestera_switch * sw,enum prestera_event_type type,prestera_event_cb_t fn)2092 void prestera_hw_event_handler_unregister(struct prestera_switch *sw,
2093 enum prestera_event_type type,
2094 prestera_event_cb_t fn)
2095 {
2096 struct prestera_fw_event_handler *eh;
2097
2098 eh = __find_event_handler(sw, type);
2099 if (!eh)
2100 return;
2101
2102 list_del_rcu(&eh->list);
2103 kfree_rcu(eh, rcu);
2104 }
2105
prestera_hw_counter_trigger(struct prestera_switch * sw,u32 block_id)2106 int prestera_hw_counter_trigger(struct prestera_switch *sw, u32 block_id)
2107 {
2108 struct prestera_msg_counter_req req = {
2109 .block_id = __cpu_to_le32(block_id)
2110 };
2111
2112 return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_TRIGGER,
2113 &req.cmd, sizeof(req));
2114 }
2115
prestera_hw_counter_abort(struct prestera_switch * sw)2116 int prestera_hw_counter_abort(struct prestera_switch *sw)
2117 {
2118 struct prestera_msg_counter_req req;
2119
2120 return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_ABORT,
2121 &req.cmd, sizeof(req));
2122 }
2123
prestera_hw_counters_get(struct prestera_switch * sw,u32 idx,u32 * len,bool * done,struct prestera_counter_stats * stats)2124 int prestera_hw_counters_get(struct prestera_switch *sw, u32 idx,
2125 u32 *len, bool *done,
2126 struct prestera_counter_stats *stats)
2127 {
2128 struct prestera_msg_counter_resp *resp;
2129 struct prestera_msg_counter_req req = {
2130 .block_id = __cpu_to_le32(idx),
2131 .num_counters = __cpu_to_le32(*len),
2132 };
2133 size_t size = struct_size(resp, stats, *len);
2134 int err, i;
2135
2136 resp = kmalloc(size, GFP_KERNEL);
2137 if (!resp)
2138 return -ENOMEM;
2139
2140 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_GET,
2141 &req.cmd, sizeof(req), &resp->ret, size);
2142 if (err)
2143 goto free_buff;
2144
2145 for (i = 0; i < __le32_to_cpu(resp->num_counters); i++) {
2146 stats[i].packets += __le64_to_cpu(resp->stats[i].packets);
2147 stats[i].bytes += __le64_to_cpu(resp->stats[i].bytes);
2148 }
2149
2150 *len = __le32_to_cpu(resp->num_counters);
2151 *done = __le32_to_cpu(resp->done);
2152
2153 free_buff:
2154 kfree(resp);
2155 return err;
2156 }
2157
prestera_hw_counter_block_get(struct prestera_switch * sw,u32 client,u32 * block_id,u32 * offset,u32 * num_counters)2158 int prestera_hw_counter_block_get(struct prestera_switch *sw,
2159 u32 client, u32 *block_id, u32 *offset,
2160 u32 *num_counters)
2161 {
2162 struct prestera_msg_counter_resp resp;
2163 struct prestera_msg_counter_req req = {
2164 .client = __cpu_to_le32(client)
2165 };
2166 int err;
2167
2168 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_GET,
2169 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2170 if (err)
2171 return err;
2172
2173 *block_id = __le32_to_cpu(resp.block_id);
2174 *offset = __le32_to_cpu(resp.offset);
2175 *num_counters = __le32_to_cpu(resp.num_counters);
2176
2177 return 0;
2178 }
2179
prestera_hw_counter_block_release(struct prestera_switch * sw,u32 block_id)2180 int prestera_hw_counter_block_release(struct prestera_switch *sw,
2181 u32 block_id)
2182 {
2183 struct prestera_msg_counter_req req = {
2184 .block_id = __cpu_to_le32(block_id)
2185 };
2186
2187 return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_RELEASE,
2188 &req.cmd, sizeof(req));
2189 }
2190
prestera_hw_counter_clear(struct prestera_switch * sw,u32 block_id,u32 counter_id)2191 int prestera_hw_counter_clear(struct prestera_switch *sw, u32 block_id,
2192 u32 counter_id)
2193 {
2194 struct prestera_msg_counter_req req = {
2195 .block_id = __cpu_to_le32(block_id),
2196 .num_counters = __cpu_to_le32(counter_id)
2197 };
2198
2199 return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_CLEAR,
2200 &req.cmd, sizeof(req));
2201 }
2202
prestera_hw_policer_create(struct prestera_switch * sw,u8 type,u32 * policer_id)2203 int prestera_hw_policer_create(struct prestera_switch *sw, u8 type,
2204 u32 *policer_id)
2205 {
2206 struct prestera_msg_policer_resp resp;
2207 struct prestera_msg_policer_req req = {
2208 .type = type
2209 };
2210 int err;
2211
2212 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_POLICER_CREATE,
2213 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2214 if (err)
2215 return err;
2216
2217 *policer_id = __le32_to_cpu(resp.id);
2218 return 0;
2219 }
2220
prestera_hw_policer_release(struct prestera_switch * sw,u32 policer_id)2221 int prestera_hw_policer_release(struct prestera_switch *sw,
2222 u32 policer_id)
2223 {
2224 struct prestera_msg_policer_req req = {
2225 .id = __cpu_to_le32(policer_id)
2226 };
2227
2228 return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_RELEASE,
2229 &req.cmd, sizeof(req));
2230 }
2231
prestera_hw_policer_sr_tcm_set(struct prestera_switch * sw,u32 policer_id,u64 cir,u32 cbs)2232 int prestera_hw_policer_sr_tcm_set(struct prestera_switch *sw,
2233 u32 policer_id, u64 cir, u32 cbs)
2234 {
2235 struct prestera_msg_policer_req req = {
2236 .mode = PRESTERA_POLICER_MODE_SR_TCM,
2237 .id = __cpu_to_le32(policer_id),
2238 .sr_tcm = {
2239 .cir = __cpu_to_le64(cir),
2240 .cbs = __cpu_to_le32(cbs)
2241 }
2242 };
2243
2244 return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_SET,
2245 &req.cmd, sizeof(req));
2246 }
2247