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