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