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