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