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