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