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