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 
12 #define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
13 
14 #define PRESTERA_MIN_MTU 64
15 
16 enum prestera_cmd_type_t {
17 	PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1,
18 	PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2,
19 
20 	PRESTERA_CMD_TYPE_PORT_ATTR_SET = 0x100,
21 	PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101,
22 	PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110,
23 
24 	PRESTERA_CMD_TYPE_VLAN_CREATE = 0x200,
25 	PRESTERA_CMD_TYPE_VLAN_DELETE = 0x201,
26 	PRESTERA_CMD_TYPE_VLAN_PORT_SET = 0x202,
27 	PRESTERA_CMD_TYPE_VLAN_PVID_SET = 0x203,
28 
29 	PRESTERA_CMD_TYPE_FDB_ADD = 0x300,
30 	PRESTERA_CMD_TYPE_FDB_DELETE = 0x301,
31 	PRESTERA_CMD_TYPE_FDB_FLUSH_PORT = 0x310,
32 	PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN = 0x311,
33 	PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN = 0x312,
34 
35 	PRESTERA_CMD_TYPE_BRIDGE_CREATE = 0x400,
36 	PRESTERA_CMD_TYPE_BRIDGE_DELETE = 0x401,
37 	PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD = 0x402,
38 	PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE = 0x403,
39 
40 	PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
41 	PRESTERA_CMD_TYPE_RXTX_PORT_INIT = 0x801,
42 
43 	PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
44 
45 	PRESTERA_CMD_TYPE_ACK = 0x10000,
46 	PRESTERA_CMD_TYPE_MAX
47 };
48 
49 enum {
50 	PRESTERA_CMD_PORT_ATTR_ADMIN_STATE = 1,
51 	PRESTERA_CMD_PORT_ATTR_MTU = 3,
52 	PRESTERA_CMD_PORT_ATTR_MAC = 4,
53 	PRESTERA_CMD_PORT_ATTR_SPEED = 5,
54 	PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6,
55 	PRESTERA_CMD_PORT_ATTR_LEARNING = 7,
56 	PRESTERA_CMD_PORT_ATTR_FLOOD = 8,
57 	PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9,
58 	PRESTERA_CMD_PORT_ATTR_REMOTE_CAPABILITY = 10,
59 	PRESTERA_CMD_PORT_ATTR_REMOTE_FC = 11,
60 	PRESTERA_CMD_PORT_ATTR_LINK_MODE = 12,
61 	PRESTERA_CMD_PORT_ATTR_TYPE = 13,
62 	PRESTERA_CMD_PORT_ATTR_FEC = 14,
63 	PRESTERA_CMD_PORT_ATTR_AUTONEG = 15,
64 	PRESTERA_CMD_PORT_ATTR_DUPLEX = 16,
65 	PRESTERA_CMD_PORT_ATTR_STATS = 17,
66 	PRESTERA_CMD_PORT_ATTR_MDIX = 18,
67 	PRESTERA_CMD_PORT_ATTR_AUTONEG_RESTART = 19,
68 };
69 
70 enum {
71 	PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
72 	PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
73 };
74 
75 enum {
76 	PRESTERA_CMD_ACK_OK,
77 	PRESTERA_CMD_ACK_FAILED,
78 
79 	PRESTERA_CMD_ACK_MAX
80 };
81 
82 enum {
83 	PRESTERA_PORT_TP_NA,
84 	PRESTERA_PORT_TP_MDI,
85 	PRESTERA_PORT_TP_MDIX,
86 	PRESTERA_PORT_TP_AUTO,
87 };
88 
89 enum {
90 	PRESTERA_PORT_FLOOD_TYPE_UC = 0,
91 	PRESTERA_PORT_FLOOD_TYPE_MC = 1,
92 };
93 
94 enum {
95 	PRESTERA_PORT_GOOD_OCTETS_RCV_CNT,
96 	PRESTERA_PORT_BAD_OCTETS_RCV_CNT,
97 	PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT,
98 	PRESTERA_PORT_BRDC_PKTS_RCV_CNT,
99 	PRESTERA_PORT_MC_PKTS_RCV_CNT,
100 	PRESTERA_PORT_PKTS_64L_CNT,
101 	PRESTERA_PORT_PKTS_65TO127L_CNT,
102 	PRESTERA_PORT_PKTS_128TO255L_CNT,
103 	PRESTERA_PORT_PKTS_256TO511L_CNT,
104 	PRESTERA_PORT_PKTS_512TO1023L_CNT,
105 	PRESTERA_PORT_PKTS_1024TOMAXL_CNT,
106 	PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT,
107 	PRESTERA_PORT_MC_PKTS_SENT_CNT,
108 	PRESTERA_PORT_BRDC_PKTS_SENT_CNT,
109 	PRESTERA_PORT_FC_SENT_CNT,
110 	PRESTERA_PORT_GOOD_FC_RCV_CNT,
111 	PRESTERA_PORT_DROP_EVENTS_CNT,
112 	PRESTERA_PORT_UNDERSIZE_PKTS_CNT,
113 	PRESTERA_PORT_FRAGMENTS_PKTS_CNT,
114 	PRESTERA_PORT_OVERSIZE_PKTS_CNT,
115 	PRESTERA_PORT_JABBER_PKTS_CNT,
116 	PRESTERA_PORT_MAC_RCV_ERROR_CNT,
117 	PRESTERA_PORT_BAD_CRC_CNT,
118 	PRESTERA_PORT_COLLISIONS_CNT,
119 	PRESTERA_PORT_LATE_COLLISIONS_CNT,
120 	PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT,
121 	PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT,
122 	PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT,
123 	PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT,
124 	PRESTERA_PORT_GOOD_OCTETS_SENT_CNT,
125 
126 	PRESTERA_PORT_CNT_MAX
127 };
128 
129 enum {
130 	PRESTERA_FC_NONE,
131 	PRESTERA_FC_SYMMETRIC,
132 	PRESTERA_FC_ASYMMETRIC,
133 	PRESTERA_FC_SYMM_ASYMM,
134 };
135 
136 struct prestera_fw_event_handler {
137 	struct list_head list;
138 	struct rcu_head rcu;
139 	enum prestera_event_type type;
140 	prestera_event_cb_t func;
141 	void *arg;
142 };
143 
144 struct prestera_msg_cmd {
145 	u32 type;
146 };
147 
148 struct prestera_msg_ret {
149 	struct prestera_msg_cmd cmd;
150 	u32 status;
151 };
152 
153 struct prestera_msg_common_req {
154 	struct prestera_msg_cmd cmd;
155 };
156 
157 struct prestera_msg_common_resp {
158 	struct prestera_msg_ret ret;
159 };
160 
161 union prestera_msg_switch_param {
162 	u8 mac[ETH_ALEN];
163 	u32 ageing_timeout_ms;
164 };
165 
166 struct prestera_msg_switch_attr_req {
167 	struct prestera_msg_cmd cmd;
168 	u32 attr;
169 	union prestera_msg_switch_param param;
170 };
171 
172 struct prestera_msg_switch_init_resp {
173 	struct prestera_msg_ret ret;
174 	u32 port_count;
175 	u32 mtu_max;
176 	u8  switch_id;
177 };
178 
179 struct prestera_msg_port_autoneg_param {
180 	u64 link_mode;
181 	u8  enable;
182 	u8  fec;
183 };
184 
185 struct prestera_msg_port_cap_param {
186 	u64 link_mode;
187 	u8  type;
188 	u8  fec;
189 	u8  transceiver;
190 };
191 
192 struct prestera_msg_port_mdix_param {
193 	u8 status;
194 	u8 admin_mode;
195 };
196 
197 struct prestera_msg_port_flood_param {
198 	u8 type;
199 	u8 enable;
200 };
201 
202 union prestera_msg_port_param {
203 	u8  admin_state;
204 	u8  oper_state;
205 	u32 mtu;
206 	u8  mac[ETH_ALEN];
207 	u8  accept_frm_type;
208 	u32 speed;
209 	u8 learning;
210 	u8 flood;
211 	u32 link_mode;
212 	u8  type;
213 	u8  duplex;
214 	u8  fec;
215 	u8  fc;
216 	struct prestera_msg_port_mdix_param mdix;
217 	struct prestera_msg_port_autoneg_param autoneg;
218 	struct prestera_msg_port_cap_param cap;
219 	struct prestera_msg_port_flood_param flood_ext;
220 };
221 
222 struct prestera_msg_port_attr_req {
223 	struct prestera_msg_cmd cmd;
224 	u32 attr;
225 	u32 port;
226 	u32 dev;
227 	union prestera_msg_port_param param;
228 };
229 
230 struct prestera_msg_port_attr_resp {
231 	struct prestera_msg_ret ret;
232 	union prestera_msg_port_param param;
233 };
234 
235 struct prestera_msg_port_stats_resp {
236 	struct prestera_msg_ret ret;
237 	u64 stats[PRESTERA_PORT_CNT_MAX];
238 };
239 
240 struct prestera_msg_port_info_req {
241 	struct prestera_msg_cmd cmd;
242 	u32 port;
243 };
244 
245 struct prestera_msg_port_info_resp {
246 	struct prestera_msg_ret ret;
247 	u32 hw_id;
248 	u32 dev_id;
249 	u16 fp_id;
250 };
251 
252 struct prestera_msg_vlan_req {
253 	struct prestera_msg_cmd cmd;
254 	u32 port;
255 	u32 dev;
256 	u16 vid;
257 	u8  is_member;
258 	u8  is_tagged;
259 };
260 
261 struct prestera_msg_fdb_req {
262 	struct prestera_msg_cmd cmd;
263 	u8 dest_type;
264 	u32 port;
265 	u32 dev;
266 	u8  mac[ETH_ALEN];
267 	u16 vid;
268 	u8  dynamic;
269 	u32 flush_mode;
270 };
271 
272 struct prestera_msg_bridge_req {
273 	struct prestera_msg_cmd cmd;
274 	u32 port;
275 	u32 dev;
276 	u16 bridge;
277 };
278 
279 struct prestera_msg_bridge_resp {
280 	struct prestera_msg_ret ret;
281 	u16 bridge;
282 };
283 
284 struct prestera_msg_stp_req {
285 	struct prestera_msg_cmd cmd;
286 	u32 port;
287 	u32 dev;
288 	u16 vid;
289 	u8  state;
290 };
291 
292 struct prestera_msg_rxtx_req {
293 	struct prestera_msg_cmd cmd;
294 	u8 use_sdma;
295 };
296 
297 struct prestera_msg_rxtx_resp {
298 	struct prestera_msg_ret ret;
299 	u32 map_addr;
300 };
301 
302 struct prestera_msg_rxtx_port_req {
303 	struct prestera_msg_cmd cmd;
304 	u32 port;
305 	u32 dev;
306 };
307 
308 struct prestera_msg_event {
309 	u16 type;
310 	u16 id;
311 };
312 
313 union prestera_msg_event_port_param {
314 	u32 oper_state;
315 };
316 
317 struct prestera_msg_event_port {
318 	struct prestera_msg_event id;
319 	u32 port_id;
320 	union prestera_msg_event_port_param param;
321 };
322 
323 union prestera_msg_event_fdb_param {
324 	u8 mac[ETH_ALEN];
325 };
326 
327 struct prestera_msg_event_fdb {
328 	struct prestera_msg_event id;
329 	u8 dest_type;
330 	u32 port_id;
331 	u32 vid;
332 	union prestera_msg_event_fdb_param param;
333 };
334 
335 static int __prestera_cmd_ret(struct prestera_switch *sw,
336 			      enum prestera_cmd_type_t type,
337 			      struct prestera_msg_cmd *cmd, size_t clen,
338 			      struct prestera_msg_ret *ret, size_t rlen,
339 			      int waitms)
340 {
341 	struct prestera_device *dev = sw->dev;
342 	int err;
343 
344 	cmd->type = type;
345 
346 	err = dev->send_req(dev, cmd, clen, ret, rlen, waitms);
347 	if (err)
348 		return err;
349 
350 	if (ret->cmd.type != PRESTERA_CMD_TYPE_ACK)
351 		return -EBADE;
352 	if (ret->status != PRESTERA_CMD_ACK_OK)
353 		return -EINVAL;
354 
355 	return 0;
356 }
357 
358 static int prestera_cmd_ret(struct prestera_switch *sw,
359 			    enum prestera_cmd_type_t type,
360 			    struct prestera_msg_cmd *cmd, size_t clen,
361 			    struct prestera_msg_ret *ret, size_t rlen)
362 {
363 	return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0);
364 }
365 
366 static int prestera_cmd_ret_wait(struct prestera_switch *sw,
367 				 enum prestera_cmd_type_t type,
368 				 struct prestera_msg_cmd *cmd, size_t clen,
369 				 struct prestera_msg_ret *ret, size_t rlen,
370 				 int waitms)
371 {
372 	return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms);
373 }
374 
375 static int prestera_cmd(struct prestera_switch *sw,
376 			enum prestera_cmd_type_t type,
377 			struct prestera_msg_cmd *cmd, size_t clen)
378 {
379 	struct prestera_msg_common_resp resp;
380 
381 	return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp));
382 }
383 
384 static int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt)
385 {
386 	struct prestera_msg_event_port *hw_evt = msg;
387 
388 	if (evt->id != PRESTERA_PORT_EVENT_STATE_CHANGED)
389 		return -EINVAL;
390 
391 	evt->port_evt.data.oper_state = hw_evt->param.oper_state;
392 	evt->port_evt.port_id = hw_evt->port_id;
393 
394 	return 0;
395 }
396 
397 static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt)
398 {
399 	struct prestera_msg_event_fdb *hw_evt = msg;
400 
401 	evt->fdb_evt.port_id = hw_evt->port_id;
402 	evt->fdb_evt.vid = hw_evt->vid;
403 
404 	ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac);
405 
406 	return 0;
407 }
408 
409 static struct prestera_fw_evt_parser {
410 	int (*func)(void *msg, struct prestera_event *evt);
411 } fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = {
412 	[PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt },
413 	[PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt },
414 };
415 
416 static struct prestera_fw_event_handler *
417 __find_event_handler(const struct prestera_switch *sw,
418 		     enum prestera_event_type type)
419 {
420 	struct prestera_fw_event_handler *eh;
421 
422 	list_for_each_entry_rcu(eh, &sw->event_handlers, list) {
423 		if (eh->type == type)
424 			return eh;
425 	}
426 
427 	return NULL;
428 }
429 
430 static int prestera_find_event_handler(const struct prestera_switch *sw,
431 				       enum prestera_event_type type,
432 				       struct prestera_fw_event_handler *eh)
433 {
434 	struct prestera_fw_event_handler *tmp;
435 	int err = 0;
436 
437 	rcu_read_lock();
438 	tmp = __find_event_handler(sw, type);
439 	if (tmp)
440 		*eh = *tmp;
441 	else
442 		err = -ENOENT;
443 	rcu_read_unlock();
444 
445 	return err;
446 }
447 
448 static int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size)
449 {
450 	struct prestera_switch *sw = dev->priv;
451 	struct prestera_msg_event *msg = buf;
452 	struct prestera_fw_event_handler eh;
453 	struct prestera_event evt;
454 	int err;
455 
456 	if (msg->type >= PRESTERA_EVENT_TYPE_MAX)
457 		return -EINVAL;
458 	if (!fw_event_parsers[msg->type].func)
459 		return -ENOENT;
460 
461 	err = prestera_find_event_handler(sw, msg->type, &eh);
462 	if (err)
463 		return err;
464 
465 	evt.id = msg->id;
466 
467 	err = fw_event_parsers[msg->type].func(buf, &evt);
468 	if (err)
469 		return err;
470 
471 	eh.func(sw, &evt, eh.arg);
472 
473 	return 0;
474 }
475 
476 static void prestera_pkt_recv(struct prestera_device *dev)
477 {
478 	struct prestera_switch *sw = dev->priv;
479 	struct prestera_fw_event_handler eh;
480 	struct prestera_event ev;
481 	int err;
482 
483 	ev.id = PRESTERA_RXTX_EVENT_RCV_PKT;
484 
485 	err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh);
486 	if (err)
487 		return;
488 
489 	eh.func(sw, &ev, eh.arg);
490 }
491 
492 int prestera_hw_port_info_get(const struct prestera_port *port,
493 			      u32 *dev_id, u32 *hw_id, u16 *fp_id)
494 {
495 	struct prestera_msg_port_info_req req = {
496 		.port = port->id,
497 	};
498 	struct prestera_msg_port_info_resp resp;
499 	int err;
500 
501 	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET,
502 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
503 	if (err)
504 		return err;
505 
506 	*dev_id = resp.dev_id;
507 	*hw_id = resp.hw_id;
508 	*fp_id = resp.fp_id;
509 
510 	return 0;
511 }
512 
513 int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac)
514 {
515 	struct prestera_msg_switch_attr_req req = {
516 		.attr = PRESTERA_CMD_SWITCH_ATTR_MAC,
517 	};
518 
519 	ether_addr_copy(req.param.mac, mac);
520 
521 	return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
522 			    &req.cmd, sizeof(req));
523 }
524 
525 int prestera_hw_switch_init(struct prestera_switch *sw)
526 {
527 	struct prestera_msg_switch_init_resp resp;
528 	struct prestera_msg_common_req req;
529 	int err;
530 
531 	INIT_LIST_HEAD(&sw->event_handlers);
532 
533 	err = prestera_cmd_ret_wait(sw, PRESTERA_CMD_TYPE_SWITCH_INIT,
534 				    &req.cmd, sizeof(req),
535 				    &resp.ret, sizeof(resp),
536 				    PRESTERA_SWITCH_INIT_TIMEOUT_MS);
537 	if (err)
538 		return err;
539 
540 	sw->dev->recv_msg = prestera_evt_recv;
541 	sw->dev->recv_pkt = prestera_pkt_recv;
542 	sw->port_count = resp.port_count;
543 	sw->mtu_min = PRESTERA_MIN_MTU;
544 	sw->mtu_max = resp.mtu_max;
545 	sw->id = resp.switch_id;
546 
547 	return 0;
548 }
549 
550 void prestera_hw_switch_fini(struct prestera_switch *sw)
551 {
552 	WARN_ON(!list_empty(&sw->event_handlers));
553 }
554 
555 int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms)
556 {
557 	struct prestera_msg_switch_attr_req req = {
558 		.attr = PRESTERA_CMD_SWITCH_ATTR_AGEING,
559 		.param = {
560 			.ageing_timeout_ms = ageing_ms,
561 		},
562 	};
563 
564 	return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
565 			    &req.cmd, sizeof(req));
566 }
567 
568 int prestera_hw_port_state_set(const struct prestera_port *port,
569 			       bool admin_state)
570 {
571 	struct prestera_msg_port_attr_req req = {
572 		.attr = PRESTERA_CMD_PORT_ATTR_ADMIN_STATE,
573 		.port = port->hw_id,
574 		.dev = port->dev_id,
575 		.param = {
576 			.admin_state = admin_state,
577 		}
578 	};
579 
580 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
581 			    &req.cmd, sizeof(req));
582 }
583 
584 int prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu)
585 {
586 	struct prestera_msg_port_attr_req req = {
587 		.attr = PRESTERA_CMD_PORT_ATTR_MTU,
588 		.port = port->hw_id,
589 		.dev = port->dev_id,
590 		.param = {
591 			.mtu = mtu,
592 		}
593 	};
594 
595 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
596 			    &req.cmd, sizeof(req));
597 }
598 
599 int prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac)
600 {
601 	struct prestera_msg_port_attr_req req = {
602 		.attr = PRESTERA_CMD_PORT_ATTR_MAC,
603 		.port = port->hw_id,
604 		.dev = port->dev_id,
605 	};
606 
607 	ether_addr_copy(req.param.mac, mac);
608 
609 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
610 			    &req.cmd, sizeof(req));
611 }
612 
613 int prestera_hw_port_accept_frm_type(struct prestera_port *port,
614 				     enum prestera_accept_frm_type type)
615 {
616 	struct prestera_msg_port_attr_req req = {
617 		.attr = PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE,
618 		.port = port->hw_id,
619 		.dev = port->dev_id,
620 		.param = {
621 			.accept_frm_type = type,
622 		}
623 	};
624 
625 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
626 			    &req.cmd, sizeof(req));
627 }
628 
629 int prestera_hw_port_cap_get(const struct prestera_port *port,
630 			     struct prestera_port_caps *caps)
631 {
632 	struct prestera_msg_port_attr_req req = {
633 		.attr = PRESTERA_CMD_PORT_ATTR_CAPABILITY,
634 		.port = port->hw_id,
635 		.dev = port->dev_id,
636 	};
637 	struct prestera_msg_port_attr_resp resp;
638 	int err;
639 
640 	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
641 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
642 	if (err)
643 		return err;
644 
645 	caps->supp_link_modes = resp.param.cap.link_mode;
646 	caps->transceiver = resp.param.cap.transceiver;
647 	caps->supp_fec = resp.param.cap.fec;
648 	caps->type = resp.param.cap.type;
649 
650 	return err;
651 }
652 
653 int prestera_hw_port_remote_cap_get(const struct prestera_port *port,
654 				    u64 *link_mode_bitmap)
655 {
656 	struct prestera_msg_port_attr_req req = {
657 		.attr = PRESTERA_CMD_PORT_ATTR_REMOTE_CAPABILITY,
658 		.port = port->hw_id,
659 		.dev = port->dev_id,
660 	};
661 	struct prestera_msg_port_attr_resp resp;
662 	int err;
663 
664 	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
665 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
666 	if (err)
667 		return err;
668 
669 	*link_mode_bitmap = resp.param.cap.link_mode;
670 
671 	return 0;
672 }
673 
674 int prestera_hw_port_remote_fc_get(const struct prestera_port *port,
675 				   bool *pause, bool *asym_pause)
676 {
677 	struct prestera_msg_port_attr_req req = {
678 		.attr = PRESTERA_CMD_PORT_ATTR_REMOTE_FC,
679 		.port = port->hw_id,
680 		.dev = port->dev_id,
681 	};
682 	struct prestera_msg_port_attr_resp resp;
683 	int err;
684 
685 	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
686 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
687 	if (err)
688 		return err;
689 
690 	switch (resp.param.fc) {
691 	case PRESTERA_FC_SYMMETRIC:
692 		*pause = true;
693 		*asym_pause = false;
694 		break;
695 	case PRESTERA_FC_ASYMMETRIC:
696 		*pause = false;
697 		*asym_pause = true;
698 		break;
699 	case PRESTERA_FC_SYMM_ASYMM:
700 		*pause = true;
701 		*asym_pause = true;
702 		break;
703 	default:
704 		*pause = false;
705 		*asym_pause = false;
706 	}
707 
708 	return 0;
709 }
710 
711 int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
712 {
713 	struct prestera_msg_port_attr_req req = {
714 		.attr = PRESTERA_CMD_PORT_ATTR_TYPE,
715 		.port = port->hw_id,
716 		.dev = port->dev_id,
717 	};
718 	struct prestera_msg_port_attr_resp resp;
719 	int err;
720 
721 	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
722 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
723 	if (err)
724 		return err;
725 
726 	*type = resp.param.type;
727 
728 	return 0;
729 }
730 
731 int prestera_hw_port_fec_get(const struct prestera_port *port, u8 *fec)
732 {
733 	struct prestera_msg_port_attr_req req = {
734 		.attr = PRESTERA_CMD_PORT_ATTR_FEC,
735 		.port = port->hw_id,
736 		.dev = port->dev_id,
737 	};
738 	struct prestera_msg_port_attr_resp resp;
739 	int err;
740 
741 	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
742 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
743 	if (err)
744 		return err;
745 
746 	*fec = resp.param.fec;
747 
748 	return 0;
749 }
750 
751 int prestera_hw_port_fec_set(const struct prestera_port *port, u8 fec)
752 {
753 	struct prestera_msg_port_attr_req req = {
754 		.attr = PRESTERA_CMD_PORT_ATTR_FEC,
755 		.port = port->hw_id,
756 		.dev = port->dev_id,
757 		.param = {
758 			.fec = fec,
759 		}
760 	};
761 
762 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
763 			    &req.cmd, sizeof(req));
764 }
765 
766 static u8 prestera_hw_mdix_to_eth(u8 mode)
767 {
768 	switch (mode) {
769 	case PRESTERA_PORT_TP_MDI:
770 		return ETH_TP_MDI;
771 	case PRESTERA_PORT_TP_MDIX:
772 		return ETH_TP_MDI_X;
773 	case PRESTERA_PORT_TP_AUTO:
774 		return ETH_TP_MDI_AUTO;
775 	default:
776 		return ETH_TP_MDI_INVALID;
777 	}
778 }
779 
780 static u8 prestera_hw_mdix_from_eth(u8 mode)
781 {
782 	switch (mode) {
783 	case ETH_TP_MDI:
784 		return PRESTERA_PORT_TP_MDI;
785 	case ETH_TP_MDI_X:
786 		return PRESTERA_PORT_TP_MDIX;
787 	case ETH_TP_MDI_AUTO:
788 		return PRESTERA_PORT_TP_AUTO;
789 	default:
790 		return PRESTERA_PORT_TP_NA;
791 	}
792 }
793 
794 int prestera_hw_port_mdix_get(const struct prestera_port *port, u8 *status,
795 			      u8 *admin_mode)
796 {
797 	struct prestera_msg_port_attr_req req = {
798 		.attr = PRESTERA_CMD_PORT_ATTR_MDIX,
799 		.port = port->hw_id,
800 		.dev = port->dev_id,
801 	};
802 	struct prestera_msg_port_attr_resp resp;
803 	int err;
804 
805 	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
806 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
807 	if (err)
808 		return err;
809 
810 	*status = prestera_hw_mdix_to_eth(resp.param.mdix.status);
811 	*admin_mode = prestera_hw_mdix_to_eth(resp.param.mdix.admin_mode);
812 
813 	return 0;
814 }
815 
816 int prestera_hw_port_mdix_set(const struct prestera_port *port, u8 mode)
817 {
818 	struct prestera_msg_port_attr_req req = {
819 		.attr = PRESTERA_CMD_PORT_ATTR_MDIX,
820 		.port = port->hw_id,
821 		.dev = port->dev_id,
822 	};
823 
824 	req.param.mdix.admin_mode = prestera_hw_mdix_from_eth(mode);
825 
826 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
827 			    &req.cmd, sizeof(req));
828 }
829 
830 int prestera_hw_port_link_mode_set(const struct prestera_port *port, u32 mode)
831 {
832 	struct prestera_msg_port_attr_req req = {
833 		.attr = PRESTERA_CMD_PORT_ATTR_LINK_MODE,
834 		.port = port->hw_id,
835 		.dev = port->dev_id,
836 		.param = {
837 			.link_mode = mode,
838 		}
839 	};
840 
841 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
842 			    &req.cmd, sizeof(req));
843 }
844 
845 int prestera_hw_port_link_mode_get(const struct prestera_port *port, u32 *mode)
846 {
847 	struct prestera_msg_port_attr_req req = {
848 		.attr = PRESTERA_CMD_PORT_ATTR_LINK_MODE,
849 		.port = port->hw_id,
850 		.dev = port->dev_id,
851 	};
852 	struct prestera_msg_port_attr_resp resp;
853 	int err;
854 
855 	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
856 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
857 	if (err)
858 		return err;
859 
860 	*mode = resp.param.link_mode;
861 
862 	return 0;
863 }
864 
865 int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed)
866 {
867 	struct prestera_msg_port_attr_req req = {
868 		.attr = PRESTERA_CMD_PORT_ATTR_SPEED,
869 		.port = port->hw_id,
870 		.dev = port->dev_id,
871 	};
872 	struct prestera_msg_port_attr_resp resp;
873 	int err;
874 
875 	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
876 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
877 	if (err)
878 		return err;
879 
880 	*speed = resp.param.speed;
881 
882 	return 0;
883 }
884 
885 int prestera_hw_port_autoneg_set(const struct prestera_port *port,
886 				 bool autoneg, u64 link_modes, u8 fec)
887 {
888 	struct prestera_msg_port_attr_req req = {
889 		.attr = PRESTERA_CMD_PORT_ATTR_AUTONEG,
890 		.port = port->hw_id,
891 		.dev = port->dev_id,
892 		.param = {
893 			.autoneg = {
894 				.link_mode = link_modes,
895 				.enable = autoneg,
896 				.fec = fec,
897 			}
898 		}
899 	};
900 
901 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
902 			    &req.cmd, sizeof(req));
903 }
904 
905 int prestera_hw_port_autoneg_restart(struct prestera_port *port)
906 {
907 	struct prestera_msg_port_attr_req req = {
908 		.attr = PRESTERA_CMD_PORT_ATTR_AUTONEG_RESTART,
909 		.port = port->hw_id,
910 		.dev = port->dev_id,
911 	};
912 
913 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
914 			    &req.cmd, sizeof(req));
915 }
916 
917 int prestera_hw_port_duplex_get(const struct prestera_port *port, u8 *duplex)
918 {
919 	struct prestera_msg_port_attr_req req = {
920 		.attr = PRESTERA_CMD_PORT_ATTR_DUPLEX,
921 		.port = port->hw_id,
922 		.dev = port->dev_id,
923 	};
924 	struct prestera_msg_port_attr_resp resp;
925 	int err;
926 
927 	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
928 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
929 	if (err)
930 		return err;
931 
932 	*duplex = resp.param.duplex;
933 
934 	return 0;
935 }
936 
937 int prestera_hw_port_stats_get(const struct prestera_port *port,
938 			       struct prestera_port_stats *st)
939 {
940 	struct prestera_msg_port_attr_req req = {
941 		.attr = PRESTERA_CMD_PORT_ATTR_STATS,
942 		.port = port->hw_id,
943 		.dev = port->dev_id,
944 	};
945 	struct prestera_msg_port_stats_resp resp;
946 	u64 *hw = resp.stats;
947 	int err;
948 
949 	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
950 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
951 	if (err)
952 		return err;
953 
954 	st->good_octets_received = hw[PRESTERA_PORT_GOOD_OCTETS_RCV_CNT];
955 	st->bad_octets_received = hw[PRESTERA_PORT_BAD_OCTETS_RCV_CNT];
956 	st->mac_trans_error = hw[PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT];
957 	st->broadcast_frames_received = hw[PRESTERA_PORT_BRDC_PKTS_RCV_CNT];
958 	st->multicast_frames_received = hw[PRESTERA_PORT_MC_PKTS_RCV_CNT];
959 	st->frames_64_octets = hw[PRESTERA_PORT_PKTS_64L_CNT];
960 	st->frames_65_to_127_octets = hw[PRESTERA_PORT_PKTS_65TO127L_CNT];
961 	st->frames_128_to_255_octets = hw[PRESTERA_PORT_PKTS_128TO255L_CNT];
962 	st->frames_256_to_511_octets = hw[PRESTERA_PORT_PKTS_256TO511L_CNT];
963 	st->frames_512_to_1023_octets = hw[PRESTERA_PORT_PKTS_512TO1023L_CNT];
964 	st->frames_1024_to_max_octets = hw[PRESTERA_PORT_PKTS_1024TOMAXL_CNT];
965 	st->excessive_collision = hw[PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT];
966 	st->multicast_frames_sent = hw[PRESTERA_PORT_MC_PKTS_SENT_CNT];
967 	st->broadcast_frames_sent = hw[PRESTERA_PORT_BRDC_PKTS_SENT_CNT];
968 	st->fc_sent = hw[PRESTERA_PORT_FC_SENT_CNT];
969 	st->fc_received = hw[PRESTERA_PORT_GOOD_FC_RCV_CNT];
970 	st->buffer_overrun = hw[PRESTERA_PORT_DROP_EVENTS_CNT];
971 	st->undersize = hw[PRESTERA_PORT_UNDERSIZE_PKTS_CNT];
972 	st->fragments = hw[PRESTERA_PORT_FRAGMENTS_PKTS_CNT];
973 	st->oversize = hw[PRESTERA_PORT_OVERSIZE_PKTS_CNT];
974 	st->jabber = hw[PRESTERA_PORT_JABBER_PKTS_CNT];
975 	st->rx_error_frame_received = hw[PRESTERA_PORT_MAC_RCV_ERROR_CNT];
976 	st->bad_crc = hw[PRESTERA_PORT_BAD_CRC_CNT];
977 	st->collisions = hw[PRESTERA_PORT_COLLISIONS_CNT];
978 	st->late_collision = hw[PRESTERA_PORT_LATE_COLLISIONS_CNT];
979 	st->unicast_frames_received = hw[PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT];
980 	st->unicast_frames_sent = hw[PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT];
981 	st->sent_multiple = hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT];
982 	st->sent_deferred = hw[PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT];
983 	st->good_octets_sent = hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT];
984 
985 	return 0;
986 }
987 
988 int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
989 {
990 	struct prestera_msg_port_attr_req req = {
991 		.attr = PRESTERA_CMD_PORT_ATTR_LEARNING,
992 		.port = port->hw_id,
993 		.dev = port->dev_id,
994 		.param = {
995 			.learning = enable,
996 		}
997 	};
998 
999 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1000 			    &req.cmd, sizeof(req));
1001 }
1002 
1003 static int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood)
1004 {
1005 	struct prestera_msg_port_attr_req req = {
1006 		.attr = PRESTERA_CMD_PORT_ATTR_FLOOD,
1007 		.port = port->hw_id,
1008 		.dev = port->dev_id,
1009 		.param = {
1010 			.flood_ext = {
1011 				.type = PRESTERA_PORT_FLOOD_TYPE_UC,
1012 				.enable = flood,
1013 			}
1014 		}
1015 	};
1016 
1017 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1018 			    &req.cmd, sizeof(req));
1019 }
1020 
1021 static int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood)
1022 {
1023 	struct prestera_msg_port_attr_req req = {
1024 		.attr = PRESTERA_CMD_PORT_ATTR_FLOOD,
1025 		.port = port->hw_id,
1026 		.dev = port->dev_id,
1027 		.param = {
1028 			.flood_ext = {
1029 				.type = PRESTERA_PORT_FLOOD_TYPE_MC,
1030 				.enable = flood,
1031 			}
1032 		}
1033 	};
1034 
1035 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1036 			    &req.cmd, sizeof(req));
1037 }
1038 
1039 static int prestera_hw_port_flood_set_v2(struct prestera_port *port, bool flood)
1040 {
1041 	struct prestera_msg_port_attr_req req = {
1042 		.attr = PRESTERA_CMD_PORT_ATTR_FLOOD,
1043 		.port = port->hw_id,
1044 		.dev = port->dev_id,
1045 		.param = {
1046 			.flood = flood,
1047 		}
1048 	};
1049 
1050 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1051 			    &req.cmd, sizeof(req));
1052 }
1053 
1054 int prestera_hw_port_flood_set(struct prestera_port *port, unsigned long mask,
1055 			       unsigned long val)
1056 {
1057 	int err;
1058 
1059 	if (port->sw->dev->fw_rev.maj <= 2) {
1060 		if (!(mask & BR_FLOOD))
1061 			return 0;
1062 
1063 		return prestera_hw_port_flood_set_v2(port, val & BR_FLOOD);
1064 	}
1065 
1066 	if (mask & BR_FLOOD) {
1067 		err = prestera_hw_port_uc_flood_set(port, val & BR_FLOOD);
1068 		if (err)
1069 			goto err_uc_flood;
1070 	}
1071 
1072 	if (mask & BR_MCAST_FLOOD) {
1073 		err = prestera_hw_port_mc_flood_set(port, val & BR_MCAST_FLOOD);
1074 		if (err)
1075 			goto err_mc_flood;
1076 	}
1077 
1078 	return 0;
1079 
1080 err_mc_flood:
1081 	prestera_hw_port_mc_flood_set(port, 0);
1082 err_uc_flood:
1083 	if (mask & BR_FLOOD)
1084 		prestera_hw_port_uc_flood_set(port, 0);
1085 
1086 	return err;
1087 }
1088 
1089 int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
1090 {
1091 	struct prestera_msg_vlan_req req = {
1092 		.vid = vid,
1093 	};
1094 
1095 	return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE,
1096 			    &req.cmd, sizeof(req));
1097 }
1098 
1099 int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid)
1100 {
1101 	struct prestera_msg_vlan_req req = {
1102 		.vid = vid,
1103 	};
1104 
1105 	return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE,
1106 			    &req.cmd, sizeof(req));
1107 }
1108 
1109 int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid,
1110 			      bool is_member, bool untagged)
1111 {
1112 	struct prestera_msg_vlan_req req = {
1113 		.port = port->hw_id,
1114 		.dev = port->dev_id,
1115 		.vid = vid,
1116 		.is_member = is_member,
1117 		.is_tagged = !untagged,
1118 	};
1119 
1120 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET,
1121 			    &req.cmd, sizeof(req));
1122 }
1123 
1124 int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid)
1125 {
1126 	struct prestera_msg_vlan_req req = {
1127 		.port = port->hw_id,
1128 		.dev = port->dev_id,
1129 		.vid = vid,
1130 	};
1131 
1132 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET,
1133 			    &req.cmd, sizeof(req));
1134 }
1135 
1136 int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state)
1137 {
1138 	struct prestera_msg_stp_req req = {
1139 		.port = port->hw_id,
1140 		.dev = port->dev_id,
1141 		.vid = vid,
1142 		.state = state,
1143 	};
1144 
1145 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET,
1146 			    &req.cmd, sizeof(req));
1147 }
1148 
1149 int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac,
1150 			u16 vid, bool dynamic)
1151 {
1152 	struct prestera_msg_fdb_req req = {
1153 		.port = port->hw_id,
1154 		.dev = port->dev_id,
1155 		.vid = vid,
1156 		.dynamic = dynamic,
1157 	};
1158 
1159 	ether_addr_copy(req.mac, mac);
1160 
1161 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD,
1162 			    &req.cmd, sizeof(req));
1163 }
1164 
1165 int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac,
1166 			u16 vid)
1167 {
1168 	struct prestera_msg_fdb_req req = {
1169 		.port = port->hw_id,
1170 		.dev = port->dev_id,
1171 		.vid = vid,
1172 	};
1173 
1174 	ether_addr_copy(req.mac, mac);
1175 
1176 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1177 			    &req.cmd, sizeof(req));
1178 }
1179 
1180 int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode)
1181 {
1182 	struct prestera_msg_fdb_req req = {
1183 		.port = port->hw_id,
1184 		.dev = port->dev_id,
1185 		.flush_mode = mode,
1186 	};
1187 
1188 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1189 			    &req.cmd, sizeof(req));
1190 }
1191 
1192 int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode)
1193 {
1194 	struct prestera_msg_fdb_req req = {
1195 		.vid = vid,
1196 		.flush_mode = mode,
1197 	};
1198 
1199 	return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN,
1200 			    &req.cmd, sizeof(req));
1201 }
1202 
1203 int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
1204 				    u32 mode)
1205 {
1206 	struct prestera_msg_fdb_req req = {
1207 		.port = port->hw_id,
1208 		.dev = port->dev_id,
1209 		.vid = vid,
1210 		.flush_mode = mode,
1211 	};
1212 
1213 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1214 			    &req.cmd, sizeof(req));
1215 }
1216 
1217 int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id)
1218 {
1219 	struct prestera_msg_bridge_resp resp;
1220 	struct prestera_msg_bridge_req req;
1221 	int err;
1222 
1223 	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE,
1224 			       &req.cmd, sizeof(req),
1225 			       &resp.ret, sizeof(resp));
1226 	if (err)
1227 		return err;
1228 
1229 	*bridge_id = resp.bridge;
1230 
1231 	return 0;
1232 }
1233 
1234 int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id)
1235 {
1236 	struct prestera_msg_bridge_req req = {
1237 		.bridge = bridge_id,
1238 	};
1239 
1240 	return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE,
1241 			    &req.cmd, sizeof(req));
1242 }
1243 
1244 int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id)
1245 {
1246 	struct prestera_msg_bridge_req req = {
1247 		.bridge = bridge_id,
1248 		.port = port->hw_id,
1249 		.dev = port->dev_id,
1250 	};
1251 
1252 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD,
1253 			    &req.cmd, sizeof(req));
1254 }
1255 
1256 int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)
1257 {
1258 	struct prestera_msg_bridge_req req = {
1259 		.bridge = bridge_id,
1260 		.port = port->hw_id,
1261 		.dev = port->dev_id,
1262 	};
1263 
1264 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE,
1265 			    &req.cmd, sizeof(req));
1266 }
1267 
1268 int prestera_hw_rxtx_init(struct prestera_switch *sw,
1269 			  struct prestera_rxtx_params *params)
1270 {
1271 	struct prestera_msg_rxtx_resp resp;
1272 	struct prestera_msg_rxtx_req req;
1273 	int err;
1274 
1275 	req.use_sdma = params->use_sdma;
1276 
1277 	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT,
1278 			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1279 	if (err)
1280 		return err;
1281 
1282 	params->map_addr = resp.map_addr;
1283 
1284 	return 0;
1285 }
1286 
1287 int prestera_hw_rxtx_port_init(struct prestera_port *port)
1288 {
1289 	struct prestera_msg_rxtx_port_req req = {
1290 		.port = port->hw_id,
1291 		.dev = port->dev_id,
1292 	};
1293 
1294 	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_RXTX_PORT_INIT,
1295 			    &req.cmd, sizeof(req));
1296 }
1297 
1298 int prestera_hw_event_handler_register(struct prestera_switch *sw,
1299 				       enum prestera_event_type type,
1300 				       prestera_event_cb_t fn,
1301 				       void *arg)
1302 {
1303 	struct prestera_fw_event_handler *eh;
1304 
1305 	eh = __find_event_handler(sw, type);
1306 	if (eh)
1307 		return -EEXIST;
1308 
1309 	eh = kmalloc(sizeof(*eh), GFP_KERNEL);
1310 	if (!eh)
1311 		return -ENOMEM;
1312 
1313 	eh->type = type;
1314 	eh->func = fn;
1315 	eh->arg = arg;
1316 
1317 	INIT_LIST_HEAD(&eh->list);
1318 
1319 	list_add_rcu(&eh->list, &sw->event_handlers);
1320 
1321 	return 0;
1322 }
1323 
1324 void prestera_hw_event_handler_unregister(struct prestera_switch *sw,
1325 					  enum prestera_event_type type,
1326 					  prestera_event_cb_t fn)
1327 {
1328 	struct prestera_fw_event_handler *eh;
1329 
1330 	eh = __find_event_handler(sw, type);
1331 	if (!eh)
1332 		return;
1333 
1334 	list_del_rcu(&eh->list);
1335 	kfree_rcu(eh, rcu);
1336 }
1337