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