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