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