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