1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
4 #include <linux/etherdevice.h>
5 #include <linux/ethtool.h>
6 #include <linux/list.h>
9 #include "prestera_hw.h"
11 #define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
13 #define PRESTERA_MIN_MTU 64
15 enum prestera_cmd_type_t {
16 PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1,
17 PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2,
19 PRESTERA_CMD_TYPE_PORT_ATTR_SET = 0x100,
20 PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101,
21 PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110,
23 PRESTERA_CMD_TYPE_VLAN_CREATE = 0x200,
24 PRESTERA_CMD_TYPE_VLAN_DELETE = 0x201,
25 PRESTERA_CMD_TYPE_VLAN_PORT_SET = 0x202,
26 PRESTERA_CMD_TYPE_VLAN_PVID_SET = 0x203,
28 PRESTERA_CMD_TYPE_FDB_ADD = 0x300,
29 PRESTERA_CMD_TYPE_FDB_DELETE = 0x301,
30 PRESTERA_CMD_TYPE_FDB_FLUSH_PORT = 0x310,
31 PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN = 0x311,
32 PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN = 0x312,
34 PRESTERA_CMD_TYPE_BRIDGE_CREATE = 0x400,
35 PRESTERA_CMD_TYPE_BRIDGE_DELETE = 0x401,
36 PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD = 0x402,
37 PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE = 0x403,
39 PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
40 PRESTERA_CMD_TYPE_RXTX_PORT_INIT = 0x801,
42 PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
44 PRESTERA_CMD_TYPE_ACK = 0x10000,
49 PRESTERA_CMD_PORT_ATTR_ADMIN_STATE = 1,
50 PRESTERA_CMD_PORT_ATTR_MTU = 3,
51 PRESTERA_CMD_PORT_ATTR_MAC = 4,
52 PRESTERA_CMD_PORT_ATTR_SPEED = 5,
53 PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6,
54 PRESTERA_CMD_PORT_ATTR_LEARNING = 7,
55 PRESTERA_CMD_PORT_ATTR_FLOOD = 8,
56 PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9,
57 PRESTERA_CMD_PORT_ATTR_REMOTE_CAPABILITY = 10,
58 PRESTERA_CMD_PORT_ATTR_REMOTE_FC = 11,
59 PRESTERA_CMD_PORT_ATTR_LINK_MODE = 12,
60 PRESTERA_CMD_PORT_ATTR_TYPE = 13,
61 PRESTERA_CMD_PORT_ATTR_FEC = 14,
62 PRESTERA_CMD_PORT_ATTR_AUTONEG = 15,
63 PRESTERA_CMD_PORT_ATTR_DUPLEX = 16,
64 PRESTERA_CMD_PORT_ATTR_STATS = 17,
65 PRESTERA_CMD_PORT_ATTR_MDIX = 18,
66 PRESTERA_CMD_PORT_ATTR_AUTONEG_RESTART = 19,
70 PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
71 PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
76 PRESTERA_CMD_ACK_FAILED,
84 PRESTERA_PORT_TP_MDIX,
85 PRESTERA_PORT_TP_AUTO,
89 PRESTERA_PORT_GOOD_OCTETS_RCV_CNT,
90 PRESTERA_PORT_BAD_OCTETS_RCV_CNT,
91 PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT,
92 PRESTERA_PORT_BRDC_PKTS_RCV_CNT,
93 PRESTERA_PORT_MC_PKTS_RCV_CNT,
94 PRESTERA_PORT_PKTS_64L_CNT,
95 PRESTERA_PORT_PKTS_65TO127L_CNT,
96 PRESTERA_PORT_PKTS_128TO255L_CNT,
97 PRESTERA_PORT_PKTS_256TO511L_CNT,
98 PRESTERA_PORT_PKTS_512TO1023L_CNT,
99 PRESTERA_PORT_PKTS_1024TOMAXL_CNT,
100 PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT,
101 PRESTERA_PORT_MC_PKTS_SENT_CNT,
102 PRESTERA_PORT_BRDC_PKTS_SENT_CNT,
103 PRESTERA_PORT_FC_SENT_CNT,
104 PRESTERA_PORT_GOOD_FC_RCV_CNT,
105 PRESTERA_PORT_DROP_EVENTS_CNT,
106 PRESTERA_PORT_UNDERSIZE_PKTS_CNT,
107 PRESTERA_PORT_FRAGMENTS_PKTS_CNT,
108 PRESTERA_PORT_OVERSIZE_PKTS_CNT,
109 PRESTERA_PORT_JABBER_PKTS_CNT,
110 PRESTERA_PORT_MAC_RCV_ERROR_CNT,
111 PRESTERA_PORT_BAD_CRC_CNT,
112 PRESTERA_PORT_COLLISIONS_CNT,
113 PRESTERA_PORT_LATE_COLLISIONS_CNT,
114 PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT,
115 PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT,
116 PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT,
117 PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT,
118 PRESTERA_PORT_GOOD_OCTETS_SENT_CNT,
120 PRESTERA_PORT_CNT_MAX
125 PRESTERA_FC_SYMMETRIC,
126 PRESTERA_FC_ASYMMETRIC,
127 PRESTERA_FC_SYMM_ASYMM,
130 struct prestera_fw_event_handler {
131 struct list_head list;
133 enum prestera_event_type type;
134 prestera_event_cb_t func;
138 struct prestera_msg_cmd {
142 struct prestera_msg_ret {
143 struct prestera_msg_cmd cmd;
147 struct prestera_msg_common_req {
148 struct prestera_msg_cmd cmd;
151 struct prestera_msg_common_resp {
152 struct prestera_msg_ret ret;
155 union prestera_msg_switch_param {
157 u32 ageing_timeout_ms;
160 struct prestera_msg_switch_attr_req {
161 struct prestera_msg_cmd cmd;
163 union prestera_msg_switch_param param;
166 struct prestera_msg_switch_init_resp {
167 struct prestera_msg_ret ret;
173 struct prestera_msg_port_autoneg_param {
179 struct prestera_msg_port_cap_param {
186 struct prestera_msg_port_mdix_param {
191 union prestera_msg_port_param {
205 struct prestera_msg_port_mdix_param mdix;
206 struct prestera_msg_port_autoneg_param autoneg;
207 struct prestera_msg_port_cap_param cap;
210 struct prestera_msg_port_attr_req {
211 struct prestera_msg_cmd cmd;
215 union prestera_msg_port_param param;
218 struct prestera_msg_port_attr_resp {
219 struct prestera_msg_ret ret;
220 union prestera_msg_port_param param;
223 struct prestera_msg_port_stats_resp {
224 struct prestera_msg_ret ret;
225 u64 stats[PRESTERA_PORT_CNT_MAX];
228 struct prestera_msg_port_info_req {
229 struct prestera_msg_cmd cmd;
233 struct prestera_msg_port_info_resp {
234 struct prestera_msg_ret ret;
240 struct prestera_msg_vlan_req {
241 struct prestera_msg_cmd cmd;
249 struct prestera_msg_fdb_req {
250 struct prestera_msg_cmd cmd;
260 struct prestera_msg_bridge_req {
261 struct prestera_msg_cmd cmd;
267 struct prestera_msg_bridge_resp {
268 struct prestera_msg_ret ret;
272 struct prestera_msg_stp_req {
273 struct prestera_msg_cmd cmd;
280 struct prestera_msg_rxtx_req {
281 struct prestera_msg_cmd cmd;
285 struct prestera_msg_rxtx_resp {
286 struct prestera_msg_ret ret;
290 struct prestera_msg_rxtx_port_req {
291 struct prestera_msg_cmd cmd;
296 struct prestera_msg_event {
301 union prestera_msg_event_port_param {
305 struct prestera_msg_event_port {
306 struct prestera_msg_event id;
308 union prestera_msg_event_port_param param;
311 union prestera_msg_event_fdb_param {
315 struct prestera_msg_event_fdb {
316 struct prestera_msg_event id;
320 union prestera_msg_event_fdb_param param;
323 static int __prestera_cmd_ret(struct prestera_switch *sw,
324 enum prestera_cmd_type_t type,
325 struct prestera_msg_cmd *cmd, size_t clen,
326 struct prestera_msg_ret *ret, size_t rlen,
329 struct prestera_device *dev = sw->dev;
334 err = dev->send_req(dev, cmd, clen, ret, rlen, waitms);
338 if (ret->cmd.type != PRESTERA_CMD_TYPE_ACK)
340 if (ret->status != PRESTERA_CMD_ACK_OK)
346 static int prestera_cmd_ret(struct prestera_switch *sw,
347 enum prestera_cmd_type_t type,
348 struct prestera_msg_cmd *cmd, size_t clen,
349 struct prestera_msg_ret *ret, size_t rlen)
351 return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0);
354 static int prestera_cmd_ret_wait(struct prestera_switch *sw,
355 enum prestera_cmd_type_t type,
356 struct prestera_msg_cmd *cmd, size_t clen,
357 struct prestera_msg_ret *ret, size_t rlen,
360 return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms);
363 static int prestera_cmd(struct prestera_switch *sw,
364 enum prestera_cmd_type_t type,
365 struct prestera_msg_cmd *cmd, size_t clen)
367 struct prestera_msg_common_resp resp;
369 return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp));
372 static int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt)
374 struct prestera_msg_event_port *hw_evt = msg;
376 if (evt->id != PRESTERA_PORT_EVENT_STATE_CHANGED)
379 evt->port_evt.data.oper_state = hw_evt->param.oper_state;
380 evt->port_evt.port_id = hw_evt->port_id;
385 static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt)
387 struct prestera_msg_event_fdb *hw_evt = msg;
389 evt->fdb_evt.port_id = hw_evt->port_id;
390 evt->fdb_evt.vid = hw_evt->vid;
392 ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac);
397 static struct prestera_fw_evt_parser {
398 int (*func)(void *msg, struct prestera_event *evt);
399 } fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = {
400 [PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt },
401 [PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt },
404 static struct prestera_fw_event_handler *
405 __find_event_handler(const struct prestera_switch *sw,
406 enum prestera_event_type type)
408 struct prestera_fw_event_handler *eh;
410 list_for_each_entry_rcu(eh, &sw->event_handlers, list) {
411 if (eh->type == type)
418 static int prestera_find_event_handler(const struct prestera_switch *sw,
419 enum prestera_event_type type,
420 struct prestera_fw_event_handler *eh)
422 struct prestera_fw_event_handler *tmp;
426 tmp = __find_event_handler(sw, type);
436 static int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size)
438 struct prestera_switch *sw = dev->priv;
439 struct prestera_msg_event *msg = buf;
440 struct prestera_fw_event_handler eh;
441 struct prestera_event evt;
444 if (msg->type >= PRESTERA_EVENT_TYPE_MAX)
446 if (!fw_event_parsers[msg->type].func)
449 err = prestera_find_event_handler(sw, msg->type, &eh);
455 err = fw_event_parsers[msg->type].func(buf, &evt);
459 eh.func(sw, &evt, eh.arg);
464 static void prestera_pkt_recv(struct prestera_device *dev)
466 struct prestera_switch *sw = dev->priv;
467 struct prestera_fw_event_handler eh;
468 struct prestera_event ev;
471 ev.id = PRESTERA_RXTX_EVENT_RCV_PKT;
473 err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh);
477 eh.func(sw, &ev, eh.arg);
480 int prestera_hw_port_info_get(const struct prestera_port *port,
481 u32 *dev_id, u32 *hw_id, u16 *fp_id)
483 struct prestera_msg_port_info_req req = {
486 struct prestera_msg_port_info_resp resp;
489 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET,
490 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
494 *dev_id = resp.dev_id;
501 int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac)
503 struct prestera_msg_switch_attr_req req = {
504 .attr = PRESTERA_CMD_SWITCH_ATTR_MAC,
507 ether_addr_copy(req.param.mac, mac);
509 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
510 &req.cmd, sizeof(req));
513 int prestera_hw_switch_init(struct prestera_switch *sw)
515 struct prestera_msg_switch_init_resp resp;
516 struct prestera_msg_common_req req;
519 INIT_LIST_HEAD(&sw->event_handlers);
521 err = prestera_cmd_ret_wait(sw, PRESTERA_CMD_TYPE_SWITCH_INIT,
522 &req.cmd, sizeof(req),
523 &resp.ret, sizeof(resp),
524 PRESTERA_SWITCH_INIT_TIMEOUT_MS);
528 sw->dev->recv_msg = prestera_evt_recv;
529 sw->dev->recv_pkt = prestera_pkt_recv;
530 sw->port_count = resp.port_count;
531 sw->mtu_min = PRESTERA_MIN_MTU;
532 sw->mtu_max = resp.mtu_max;
533 sw->id = resp.switch_id;
538 void prestera_hw_switch_fini(struct prestera_switch *sw)
540 WARN_ON(!list_empty(&sw->event_handlers));
543 int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms)
545 struct prestera_msg_switch_attr_req req = {
546 .attr = PRESTERA_CMD_SWITCH_ATTR_AGEING,
548 .ageing_timeout_ms = ageing_ms,
552 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
553 &req.cmd, sizeof(req));
556 int prestera_hw_port_state_set(const struct prestera_port *port,
559 struct prestera_msg_port_attr_req req = {
560 .attr = PRESTERA_CMD_PORT_ATTR_ADMIN_STATE,
564 .admin_state = admin_state,
568 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
569 &req.cmd, sizeof(req));
572 int prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu)
574 struct prestera_msg_port_attr_req req = {
575 .attr = PRESTERA_CMD_PORT_ATTR_MTU,
583 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
584 &req.cmd, sizeof(req));
587 int prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac)
589 struct prestera_msg_port_attr_req req = {
590 .attr = PRESTERA_CMD_PORT_ATTR_MAC,
595 ether_addr_copy(req.param.mac, mac);
597 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
598 &req.cmd, sizeof(req));
601 int prestera_hw_port_accept_frm_type(struct prestera_port *port,
602 enum prestera_accept_frm_type type)
604 struct prestera_msg_port_attr_req req = {
605 .attr = PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE,
609 .accept_frm_type = type,
613 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
614 &req.cmd, sizeof(req));
617 int prestera_hw_port_cap_get(const struct prestera_port *port,
618 struct prestera_port_caps *caps)
620 struct prestera_msg_port_attr_req req = {
621 .attr = PRESTERA_CMD_PORT_ATTR_CAPABILITY,
625 struct prestera_msg_port_attr_resp resp;
628 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
629 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
633 caps->supp_link_modes = resp.param.cap.link_mode;
634 caps->transceiver = resp.param.cap.transceiver;
635 caps->supp_fec = resp.param.cap.fec;
636 caps->type = resp.param.cap.type;
641 int prestera_hw_port_remote_cap_get(const struct prestera_port *port,
642 u64 *link_mode_bitmap)
644 struct prestera_msg_port_attr_req req = {
645 .attr = PRESTERA_CMD_PORT_ATTR_REMOTE_CAPABILITY,
649 struct prestera_msg_port_attr_resp resp;
652 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
653 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
657 *link_mode_bitmap = resp.param.cap.link_mode;
662 int prestera_hw_port_remote_fc_get(const struct prestera_port *port,
663 bool *pause, bool *asym_pause)
665 struct prestera_msg_port_attr_req req = {
666 .attr = PRESTERA_CMD_PORT_ATTR_REMOTE_FC,
670 struct prestera_msg_port_attr_resp resp;
673 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
674 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
678 switch (resp.param.fc) {
679 case PRESTERA_FC_SYMMETRIC:
683 case PRESTERA_FC_ASYMMETRIC:
687 case PRESTERA_FC_SYMM_ASYMM:
699 int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
701 struct prestera_msg_port_attr_req req = {
702 .attr = PRESTERA_CMD_PORT_ATTR_TYPE,
706 struct prestera_msg_port_attr_resp resp;
709 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
710 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
714 *type = resp.param.type;
719 int prestera_hw_port_fec_get(const struct prestera_port *port, u8 *fec)
721 struct prestera_msg_port_attr_req req = {
722 .attr = PRESTERA_CMD_PORT_ATTR_FEC,
726 struct prestera_msg_port_attr_resp resp;
729 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
730 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
734 *fec = resp.param.fec;
739 int prestera_hw_port_fec_set(const struct prestera_port *port, u8 fec)
741 struct prestera_msg_port_attr_req req = {
742 .attr = PRESTERA_CMD_PORT_ATTR_FEC,
750 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
751 &req.cmd, sizeof(req));
754 static u8 prestera_hw_mdix_to_eth(u8 mode)
757 case PRESTERA_PORT_TP_MDI:
759 case PRESTERA_PORT_TP_MDIX:
761 case PRESTERA_PORT_TP_AUTO:
762 return ETH_TP_MDI_AUTO;
764 return ETH_TP_MDI_INVALID;
768 static u8 prestera_hw_mdix_from_eth(u8 mode)
772 return PRESTERA_PORT_TP_MDI;
774 return PRESTERA_PORT_TP_MDIX;
775 case ETH_TP_MDI_AUTO:
776 return PRESTERA_PORT_TP_AUTO;
778 return PRESTERA_PORT_TP_NA;
782 int prestera_hw_port_mdix_get(const struct prestera_port *port, u8 *status,
785 struct prestera_msg_port_attr_req req = {
786 .attr = PRESTERA_CMD_PORT_ATTR_MDIX,
790 struct prestera_msg_port_attr_resp resp;
793 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
794 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
798 *status = prestera_hw_mdix_to_eth(resp.param.mdix.status);
799 *admin_mode = prestera_hw_mdix_to_eth(resp.param.mdix.admin_mode);
804 int prestera_hw_port_mdix_set(const struct prestera_port *port, u8 mode)
806 struct prestera_msg_port_attr_req req = {
807 .attr = PRESTERA_CMD_PORT_ATTR_MDIX,
812 req.param.mdix.admin_mode = prestera_hw_mdix_from_eth(mode);
814 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
815 &req.cmd, sizeof(req));
818 int prestera_hw_port_link_mode_set(const struct prestera_port *port, u32 mode)
820 struct prestera_msg_port_attr_req req = {
821 .attr = PRESTERA_CMD_PORT_ATTR_LINK_MODE,
829 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
830 &req.cmd, sizeof(req));
833 int prestera_hw_port_link_mode_get(const struct prestera_port *port, u32 *mode)
835 struct prestera_msg_port_attr_req req = {
836 .attr = PRESTERA_CMD_PORT_ATTR_LINK_MODE,
840 struct prestera_msg_port_attr_resp resp;
843 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
844 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
848 *mode = resp.param.link_mode;
853 int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed)
855 struct prestera_msg_port_attr_req req = {
856 .attr = PRESTERA_CMD_PORT_ATTR_SPEED,
860 struct prestera_msg_port_attr_resp resp;
863 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
864 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
868 *speed = resp.param.speed;
873 int prestera_hw_port_autoneg_set(const struct prestera_port *port,
874 bool autoneg, u64 link_modes, u8 fec)
876 struct prestera_msg_port_attr_req req = {
877 .attr = PRESTERA_CMD_PORT_ATTR_AUTONEG,
882 .link_mode = link_modes,
889 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
890 &req.cmd, sizeof(req));
893 int prestera_hw_port_autoneg_restart(struct prestera_port *port)
895 struct prestera_msg_port_attr_req req = {
896 .attr = PRESTERA_CMD_PORT_ATTR_AUTONEG_RESTART,
901 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
902 &req.cmd, sizeof(req));
905 int prestera_hw_port_duplex_get(const struct prestera_port *port, u8 *duplex)
907 struct prestera_msg_port_attr_req req = {
908 .attr = PRESTERA_CMD_PORT_ATTR_DUPLEX,
912 struct prestera_msg_port_attr_resp resp;
915 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
916 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
920 *duplex = resp.param.duplex;
925 int prestera_hw_port_stats_get(const struct prestera_port *port,
926 struct prestera_port_stats *st)
928 struct prestera_msg_port_attr_req req = {
929 .attr = PRESTERA_CMD_PORT_ATTR_STATS,
933 struct prestera_msg_port_stats_resp resp;
934 u64 *hw = resp.stats;
937 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
938 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
942 st->good_octets_received = hw[PRESTERA_PORT_GOOD_OCTETS_RCV_CNT];
943 st->bad_octets_received = hw[PRESTERA_PORT_BAD_OCTETS_RCV_CNT];
944 st->mac_trans_error = hw[PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT];
945 st->broadcast_frames_received = hw[PRESTERA_PORT_BRDC_PKTS_RCV_CNT];
946 st->multicast_frames_received = hw[PRESTERA_PORT_MC_PKTS_RCV_CNT];
947 st->frames_64_octets = hw[PRESTERA_PORT_PKTS_64L_CNT];
948 st->frames_65_to_127_octets = hw[PRESTERA_PORT_PKTS_65TO127L_CNT];
949 st->frames_128_to_255_octets = hw[PRESTERA_PORT_PKTS_128TO255L_CNT];
950 st->frames_256_to_511_octets = hw[PRESTERA_PORT_PKTS_256TO511L_CNT];
951 st->frames_512_to_1023_octets = hw[PRESTERA_PORT_PKTS_512TO1023L_CNT];
952 st->frames_1024_to_max_octets = hw[PRESTERA_PORT_PKTS_1024TOMAXL_CNT];
953 st->excessive_collision = hw[PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT];
954 st->multicast_frames_sent = hw[PRESTERA_PORT_MC_PKTS_SENT_CNT];
955 st->broadcast_frames_sent = hw[PRESTERA_PORT_BRDC_PKTS_SENT_CNT];
956 st->fc_sent = hw[PRESTERA_PORT_FC_SENT_CNT];
957 st->fc_received = hw[PRESTERA_PORT_GOOD_FC_RCV_CNT];
958 st->buffer_overrun = hw[PRESTERA_PORT_DROP_EVENTS_CNT];
959 st->undersize = hw[PRESTERA_PORT_UNDERSIZE_PKTS_CNT];
960 st->fragments = hw[PRESTERA_PORT_FRAGMENTS_PKTS_CNT];
961 st->oversize = hw[PRESTERA_PORT_OVERSIZE_PKTS_CNT];
962 st->jabber = hw[PRESTERA_PORT_JABBER_PKTS_CNT];
963 st->rx_error_frame_received = hw[PRESTERA_PORT_MAC_RCV_ERROR_CNT];
964 st->bad_crc = hw[PRESTERA_PORT_BAD_CRC_CNT];
965 st->collisions = hw[PRESTERA_PORT_COLLISIONS_CNT];
966 st->late_collision = hw[PRESTERA_PORT_LATE_COLLISIONS_CNT];
967 st->unicast_frames_received = hw[PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT];
968 st->unicast_frames_sent = hw[PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT];
969 st->sent_multiple = hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT];
970 st->sent_deferred = hw[PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT];
971 st->good_octets_sent = hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT];
976 int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
978 struct prestera_msg_port_attr_req req = {
979 .attr = PRESTERA_CMD_PORT_ATTR_LEARNING,
987 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
988 &req.cmd, sizeof(req));
991 int prestera_hw_port_flood_set(struct prestera_port *port, bool flood)
993 struct prestera_msg_port_attr_req req = {
994 .attr = PRESTERA_CMD_PORT_ATTR_FLOOD,
1002 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1003 &req.cmd, sizeof(req));
1006 int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
1008 struct prestera_msg_vlan_req req = {
1012 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE,
1013 &req.cmd, sizeof(req));
1016 int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid)
1018 struct prestera_msg_vlan_req req = {
1022 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE,
1023 &req.cmd, sizeof(req));
1026 int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid,
1027 bool is_member, bool untagged)
1029 struct prestera_msg_vlan_req req = {
1030 .port = port->hw_id,
1031 .dev = port->dev_id,
1033 .is_member = is_member,
1034 .is_tagged = !untagged,
1037 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET,
1038 &req.cmd, sizeof(req));
1041 int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid)
1043 struct prestera_msg_vlan_req req = {
1044 .port = port->hw_id,
1045 .dev = port->dev_id,
1049 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET,
1050 &req.cmd, sizeof(req));
1053 int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state)
1055 struct prestera_msg_stp_req req = {
1056 .port = port->hw_id,
1057 .dev = port->dev_id,
1062 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET,
1063 &req.cmd, sizeof(req));
1066 int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac,
1067 u16 vid, bool dynamic)
1069 struct prestera_msg_fdb_req req = {
1070 .port = port->hw_id,
1071 .dev = port->dev_id,
1076 ether_addr_copy(req.mac, mac);
1078 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD,
1079 &req.cmd, sizeof(req));
1082 int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac,
1085 struct prestera_msg_fdb_req req = {
1086 .port = port->hw_id,
1087 .dev = port->dev_id,
1091 ether_addr_copy(req.mac, mac);
1093 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1094 &req.cmd, sizeof(req));
1097 int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode)
1099 struct prestera_msg_fdb_req req = {
1100 .port = port->hw_id,
1101 .dev = port->dev_id,
1105 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1106 &req.cmd, sizeof(req));
1109 int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode)
1111 struct prestera_msg_fdb_req req = {
1116 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN,
1117 &req.cmd, sizeof(req));
1120 int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
1123 struct prestera_msg_fdb_req req = {
1124 .port = port->hw_id,
1125 .dev = port->dev_id,
1130 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1131 &req.cmd, sizeof(req));
1134 int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id)
1136 struct prestera_msg_bridge_resp resp;
1137 struct prestera_msg_bridge_req req;
1140 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE,
1141 &req.cmd, sizeof(req),
1142 &resp.ret, sizeof(resp));
1146 *bridge_id = resp.bridge;
1151 int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id)
1153 struct prestera_msg_bridge_req req = {
1154 .bridge = bridge_id,
1157 return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE,
1158 &req.cmd, sizeof(req));
1161 int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id)
1163 struct prestera_msg_bridge_req req = {
1164 .bridge = bridge_id,
1165 .port = port->hw_id,
1166 .dev = port->dev_id,
1169 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD,
1170 &req.cmd, sizeof(req));
1173 int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)
1175 struct prestera_msg_bridge_req req = {
1176 .bridge = bridge_id,
1177 .port = port->hw_id,
1178 .dev = port->dev_id,
1181 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE,
1182 &req.cmd, sizeof(req));
1185 int prestera_hw_rxtx_init(struct prestera_switch *sw,
1186 struct prestera_rxtx_params *params)
1188 struct prestera_msg_rxtx_resp resp;
1189 struct prestera_msg_rxtx_req req;
1192 req.use_sdma = params->use_sdma;
1194 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT,
1195 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1199 params->map_addr = resp.map_addr;
1204 int prestera_hw_rxtx_port_init(struct prestera_port *port)
1206 struct prestera_msg_rxtx_port_req req = {
1207 .port = port->hw_id,
1208 .dev = port->dev_id,
1211 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_RXTX_PORT_INIT,
1212 &req.cmd, sizeof(req));
1215 int prestera_hw_event_handler_register(struct prestera_switch *sw,
1216 enum prestera_event_type type,
1217 prestera_event_cb_t fn,
1220 struct prestera_fw_event_handler *eh;
1222 eh = __find_event_handler(sw, type);
1226 eh = kmalloc(sizeof(*eh), GFP_KERNEL);
1234 INIT_LIST_HEAD(&eh->list);
1236 list_add_rcu(&eh->list, &sw->event_handlers);
1241 void prestera_hw_event_handler_unregister(struct prestera_switch *sw,
1242 enum prestera_event_type type,
1243 prestera_event_cb_t fn)
1245 struct prestera_fw_event_handler *eh;
1247 eh = __find_event_handler(sw, type);
1251 list_del_rcu(&eh->list);