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