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/if_bridge.h>
6 #include <linux/ethtool.h>
7 #include <linux/list.h>
10 #include "prestera_hw.h"
11 #include "prestera_acl.h"
12 #include "prestera_counter.h"
14 #define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
16 #define PRESTERA_MIN_MTU 64
18 enum prestera_cmd_type_t {
19 PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1,
20 PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2,
22 PRESTERA_CMD_TYPE_PORT_ATTR_SET = 0x100,
23 PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101,
24 PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110,
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,
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,
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,
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,
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,
56 PRESTERA_CMD_TYPE_ROUTER_RIF_CREATE = 0x600,
57 PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE = 0x601,
58 PRESTERA_CMD_TYPE_ROUTER_LPM_ADD = 0x610,
59 PRESTERA_CMD_TYPE_ROUTER_LPM_DELETE = 0x611,
60 PRESTERA_CMD_TYPE_ROUTER_VR_CREATE = 0x630,
61 PRESTERA_CMD_TYPE_ROUTER_VR_DELETE = 0x631,
63 PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
65 PRESTERA_CMD_TYPE_LAG_MEMBER_ADD = 0x900,
66 PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE = 0x901,
67 PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE = 0x902,
68 PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE = 0x903,
70 PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
72 PRESTERA_CMD_TYPE_SPAN_GET = 0x1100,
73 PRESTERA_CMD_TYPE_SPAN_BIND = 0x1101,
74 PRESTERA_CMD_TYPE_SPAN_UNBIND = 0x1102,
75 PRESTERA_CMD_TYPE_SPAN_RELEASE = 0x1103,
77 PRESTERA_CMD_TYPE_POLICER_CREATE = 0x1500,
78 PRESTERA_CMD_TYPE_POLICER_RELEASE = 0x1501,
79 PRESTERA_CMD_TYPE_POLICER_SET = 0x1502,
81 PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET = 0x2000,
83 PRESTERA_CMD_TYPE_ACK = 0x10000,
88 PRESTERA_CMD_PORT_ATTR_ADMIN_STATE = 1,
89 PRESTERA_CMD_PORT_ATTR_MTU = 3,
90 PRESTERA_CMD_PORT_ATTR_MAC = 4,
91 PRESTERA_CMD_PORT_ATTR_SPEED = 5,
92 PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6,
93 PRESTERA_CMD_PORT_ATTR_LEARNING = 7,
94 PRESTERA_CMD_PORT_ATTR_FLOOD = 8,
95 PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9,
96 PRESTERA_CMD_PORT_ATTR_PHY_MODE = 12,
97 PRESTERA_CMD_PORT_ATTR_TYPE = 13,
98 PRESTERA_CMD_PORT_ATTR_STATS = 17,
99 PRESTERA_CMD_PORT_ATTR_MAC_AUTONEG_RESTART = 18,
100 PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART = 19,
101 PRESTERA_CMD_PORT_ATTR_MAC_MODE = 22,
105 PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
106 PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
111 PRESTERA_CMD_ACK_FAILED,
118 PRESTERA_PORT_TP_MDI,
119 PRESTERA_PORT_TP_MDIX,
120 PRESTERA_PORT_TP_AUTO,
124 PRESTERA_PORT_FLOOD_TYPE_UC = 0,
125 PRESTERA_PORT_FLOOD_TYPE_MC = 1,
129 PRESTERA_PORT_GOOD_OCTETS_RCV_CNT,
130 PRESTERA_PORT_BAD_OCTETS_RCV_CNT,
131 PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT,
132 PRESTERA_PORT_BRDC_PKTS_RCV_CNT,
133 PRESTERA_PORT_MC_PKTS_RCV_CNT,
134 PRESTERA_PORT_PKTS_64L_CNT,
135 PRESTERA_PORT_PKTS_65TO127L_CNT,
136 PRESTERA_PORT_PKTS_128TO255L_CNT,
137 PRESTERA_PORT_PKTS_256TO511L_CNT,
138 PRESTERA_PORT_PKTS_512TO1023L_CNT,
139 PRESTERA_PORT_PKTS_1024TOMAXL_CNT,
140 PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT,
141 PRESTERA_PORT_MC_PKTS_SENT_CNT,
142 PRESTERA_PORT_BRDC_PKTS_SENT_CNT,
143 PRESTERA_PORT_FC_SENT_CNT,
144 PRESTERA_PORT_GOOD_FC_RCV_CNT,
145 PRESTERA_PORT_DROP_EVENTS_CNT,
146 PRESTERA_PORT_UNDERSIZE_PKTS_CNT,
147 PRESTERA_PORT_FRAGMENTS_PKTS_CNT,
148 PRESTERA_PORT_OVERSIZE_PKTS_CNT,
149 PRESTERA_PORT_JABBER_PKTS_CNT,
150 PRESTERA_PORT_MAC_RCV_ERROR_CNT,
151 PRESTERA_PORT_BAD_CRC_CNT,
152 PRESTERA_PORT_COLLISIONS_CNT,
153 PRESTERA_PORT_LATE_COLLISIONS_CNT,
154 PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT,
155 PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT,
156 PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT,
157 PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT,
158 PRESTERA_PORT_GOOD_OCTETS_SENT_CNT,
160 PRESTERA_PORT_CNT_MAX
165 PRESTERA_FC_SYMMETRIC,
166 PRESTERA_FC_ASYMMETRIC,
167 PRESTERA_FC_SYMM_ASYMM,
171 PRESTERA_POLICER_MODE_SR_TCM
175 PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT = 0,
176 PRESTERA_HW_FDB_ENTRY_TYPE_LAG = 1,
177 PRESTERA_HW_FDB_ENTRY_TYPE_MAX = 2,
180 struct prestera_fw_event_handler {
181 struct list_head list;
183 enum prestera_event_type type;
184 prestera_event_cb_t func;
188 struct prestera_msg_cmd {
192 struct prestera_msg_ret {
193 struct prestera_msg_cmd cmd;
197 struct prestera_msg_common_req {
198 struct prestera_msg_cmd cmd;
201 struct prestera_msg_common_resp {
202 struct prestera_msg_ret ret;
205 struct prestera_msg_switch_attr_req {
206 struct prestera_msg_cmd cmd;
209 __le32 ageing_timeout_ms;
217 struct prestera_msg_switch_init_resp {
218 struct prestera_msg_ret ret;
221 __le32 size_tbl_router_nexthop;
227 struct prestera_msg_event_port_param {
242 } __packed phy; /* make sure always 12 bytes size */
246 struct prestera_msg_port_cap_param {
254 struct prestera_msg_port_flood_param {
260 union prestera_msg_port_param {
295 } ap_modes[PRESTERA_AP_PORT_MAX];
308 struct prestera_msg_port_cap_param cap;
309 struct prestera_msg_port_flood_param flood_ext;
310 struct prestera_msg_event_port_param link_evt;
313 struct prestera_msg_port_attr_req {
314 struct prestera_msg_cmd cmd;
318 union prestera_msg_port_param param;
321 struct prestera_msg_port_attr_resp {
322 struct prestera_msg_ret ret;
323 union prestera_msg_port_param param;
326 struct prestera_msg_port_stats_resp {
327 struct prestera_msg_ret ret;
328 __le64 stats[PRESTERA_PORT_CNT_MAX];
331 struct prestera_msg_port_info_req {
332 struct prestera_msg_cmd cmd;
336 struct prestera_msg_port_info_resp {
337 struct prestera_msg_ret ret;
344 struct prestera_msg_vlan_req {
345 struct prestera_msg_cmd cmd;
353 struct prestera_msg_fdb_req {
354 struct prestera_msg_cmd cmd;
370 struct prestera_msg_bridge_req {
371 struct prestera_msg_cmd cmd;
378 struct prestera_msg_bridge_resp {
379 struct prestera_msg_ret ret;
384 struct prestera_msg_vtcam_create_req {
385 struct prestera_msg_cmd cmd;
386 __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
392 struct prestera_msg_vtcam_destroy_req {
393 struct prestera_msg_cmd cmd;
397 struct prestera_msg_vtcam_rule_add_req {
398 struct prestera_msg_cmd cmd;
399 __le32 key[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
400 __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
406 struct prestera_msg_vtcam_rule_del_req {
407 struct prestera_msg_cmd cmd;
412 struct prestera_msg_vtcam_bind_req {
413 struct prestera_msg_cmd cmd;
426 struct prestera_msg_vtcam_resp {
427 struct prestera_msg_ret ret;
432 struct prestera_msg_acl_action {
449 struct prestera_msg_counter_req {
450 struct prestera_msg_cmd cmd;
456 struct prestera_msg_counter_stats {
461 struct prestera_msg_counter_resp {
462 struct prestera_msg_ret ret;
467 struct prestera_msg_counter_stats stats[];
470 struct prestera_msg_span_req {
471 struct prestera_msg_cmd cmd;
478 struct prestera_msg_span_resp {
479 struct prestera_msg_ret ret;
484 struct prestera_msg_stp_req {
485 struct prestera_msg_cmd cmd;
493 struct prestera_msg_rxtx_req {
494 struct prestera_msg_cmd cmd;
499 struct prestera_msg_rxtx_resp {
500 struct prestera_msg_ret ret;
504 struct prestera_msg_iface {
518 struct prestera_msg_ip_addr {
523 u8 v; /* e.g. PRESTERA_IPV4 */
527 struct prestera_msg_rif_req {
528 struct prestera_msg_cmd cmd;
529 struct prestera_msg_iface iif;
537 struct prestera_msg_rif_resp {
538 struct prestera_msg_ret ret;
543 struct prestera_msg_lpm_req {
544 struct prestera_msg_cmd cmd;
545 struct prestera_msg_ip_addr dst;
552 struct prestera_msg_vr_req {
553 struct prestera_msg_cmd cmd;
558 struct prestera_msg_vr_resp {
559 struct prestera_msg_ret ret;
564 struct prestera_msg_lag_req {
565 struct prestera_msg_cmd cmd;
572 struct prestera_msg_cpu_code_counter_req {
573 struct prestera_msg_cmd cmd;
579 struct mvsw_msg_cpu_code_counter_ret {
580 struct prestera_msg_ret ret;
584 struct prestera_msg_policer_req {
585 struct prestera_msg_cmd cmd;
591 } __packed sr_tcm; /* make sure always 12 bytes size */
599 struct prestera_msg_policer_resp {
600 struct prestera_msg_ret ret;
604 struct prestera_msg_event {
609 struct prestera_msg_event_port {
610 struct prestera_msg_event id;
612 struct prestera_msg_event_port_param param;
615 union prestera_msg_event_fdb_param {
619 struct prestera_msg_event_fdb {
620 struct prestera_msg_event id;
626 union prestera_msg_event_fdb_param param;
630 static void prestera_hw_build_tests(void)
633 BUILD_BUG_ON(sizeof(struct prestera_msg_common_req) != 4);
634 BUILD_BUG_ON(sizeof(struct prestera_msg_switch_attr_req) != 16);
635 BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_req) != 144);
636 BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_req) != 8);
637 BUILD_BUG_ON(sizeof(struct prestera_msg_vlan_req) != 16);
638 BUILD_BUG_ON(sizeof(struct prestera_msg_fdb_req) != 28);
639 BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_req) != 16);
640 BUILD_BUG_ON(sizeof(struct prestera_msg_span_req) != 16);
641 BUILD_BUG_ON(sizeof(struct prestera_msg_stp_req) != 16);
642 BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_req) != 8);
643 BUILD_BUG_ON(sizeof(struct prestera_msg_lag_req) != 16);
644 BUILD_BUG_ON(sizeof(struct prestera_msg_cpu_code_counter_req) != 8);
645 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_create_req) != 84);
646 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_destroy_req) != 8);
647 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_rule_add_req) != 168);
648 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_rule_del_req) != 12);
649 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_bind_req) != 20);
650 BUILD_BUG_ON(sizeof(struct prestera_msg_acl_action) != 32);
651 BUILD_BUG_ON(sizeof(struct prestera_msg_counter_req) != 16);
652 BUILD_BUG_ON(sizeof(struct prestera_msg_counter_stats) != 16);
653 BUILD_BUG_ON(sizeof(struct prestera_msg_rif_req) != 36);
654 BUILD_BUG_ON(sizeof(struct prestera_msg_vr_req) != 8);
655 BUILD_BUG_ON(sizeof(struct prestera_msg_lpm_req) != 36);
656 BUILD_BUG_ON(sizeof(struct prestera_msg_policer_req) != 36);
658 /* structure that are part of req/resp fw messages */
659 BUILD_BUG_ON(sizeof(struct prestera_msg_iface) != 16);
660 BUILD_BUG_ON(sizeof(struct prestera_msg_ip_addr) != 20);
662 /* check responses */
663 BUILD_BUG_ON(sizeof(struct prestera_msg_common_resp) != 8);
664 BUILD_BUG_ON(sizeof(struct prestera_msg_switch_init_resp) != 24);
665 BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_resp) != 136);
666 BUILD_BUG_ON(sizeof(struct prestera_msg_port_stats_resp) != 248);
667 BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_resp) != 20);
668 BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_resp) != 12);
669 BUILD_BUG_ON(sizeof(struct prestera_msg_span_resp) != 12);
670 BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_resp) != 12);
671 BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_resp) != 16);
672 BUILD_BUG_ON(sizeof(struct prestera_msg_counter_resp) != 24);
673 BUILD_BUG_ON(sizeof(struct prestera_msg_rif_resp) != 12);
674 BUILD_BUG_ON(sizeof(struct prestera_msg_vr_resp) != 12);
675 BUILD_BUG_ON(sizeof(struct prestera_msg_policer_resp) != 12);
678 BUILD_BUG_ON(sizeof(struct prestera_msg_event_port) != 20);
679 BUILD_BUG_ON(sizeof(struct prestera_msg_event_fdb) != 20);
682 static u8 prestera_hw_mdix_to_eth(u8 mode);
683 static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause);
685 static int __prestera_cmd_ret(struct prestera_switch *sw,
686 enum prestera_cmd_type_t type,
687 struct prestera_msg_cmd *cmd, size_t clen,
688 struct prestera_msg_ret *ret, size_t rlen,
691 struct prestera_device *dev = sw->dev;
694 cmd->type = __cpu_to_le32(type);
696 err = dev->send_req(dev, 0, cmd, clen, ret, rlen, waitms);
700 if (ret->cmd.type != __cpu_to_le32(PRESTERA_CMD_TYPE_ACK))
702 if (ret->status != __cpu_to_le32(PRESTERA_CMD_ACK_OK))
708 static int prestera_cmd_ret(struct prestera_switch *sw,
709 enum prestera_cmd_type_t type,
710 struct prestera_msg_cmd *cmd, size_t clen,
711 struct prestera_msg_ret *ret, size_t rlen)
713 return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0);
716 static int prestera_cmd_ret_wait(struct prestera_switch *sw,
717 enum prestera_cmd_type_t type,
718 struct prestera_msg_cmd *cmd, size_t clen,
719 struct prestera_msg_ret *ret, size_t rlen,
722 return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms);
725 static int prestera_cmd(struct prestera_switch *sw,
726 enum prestera_cmd_type_t type,
727 struct prestera_msg_cmd *cmd, size_t clen)
729 struct prestera_msg_common_resp resp;
731 return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp));
734 static int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt)
736 struct prestera_msg_event_port *hw_evt;
738 hw_evt = (struct prestera_msg_event_port *)msg;
740 evt->port_evt.port_id = __le32_to_cpu(hw_evt->port_id);
742 if (evt->id == PRESTERA_PORT_EVENT_MAC_STATE_CHANGED) {
743 evt->port_evt.data.mac.oper = hw_evt->param.mac.oper;
744 evt->port_evt.data.mac.mode =
745 __le32_to_cpu(hw_evt->param.mac.mode);
746 evt->port_evt.data.mac.speed =
747 __le32_to_cpu(hw_evt->param.mac.speed);
748 evt->port_evt.data.mac.duplex = hw_evt->param.mac.duplex;
749 evt->port_evt.data.mac.fc = hw_evt->param.mac.fc;
750 evt->port_evt.data.mac.fec = hw_evt->param.mac.fec;
758 static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt)
760 struct prestera_msg_event_fdb *hw_evt = msg;
762 switch (hw_evt->dest_type) {
763 case PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT:
764 evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_REG_PORT;
765 evt->fdb_evt.dest.port_id = __le32_to_cpu(hw_evt->dest.port_id);
767 case PRESTERA_HW_FDB_ENTRY_TYPE_LAG:
768 evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_LAG;
769 evt->fdb_evt.dest.lag_id = __le16_to_cpu(hw_evt->dest.lag_id);
775 evt->fdb_evt.vid = __le32_to_cpu(hw_evt->vid);
777 ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac);
782 static struct prestera_fw_evt_parser {
783 int (*func)(void *msg, struct prestera_event *evt);
784 } fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = {
785 [PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt },
786 [PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt },
789 static struct prestera_fw_event_handler *
790 __find_event_handler(const struct prestera_switch *sw,
791 enum prestera_event_type type)
793 struct prestera_fw_event_handler *eh;
795 list_for_each_entry_rcu(eh, &sw->event_handlers, list) {
796 if (eh->type == type)
803 static int prestera_find_event_handler(const struct prestera_switch *sw,
804 enum prestera_event_type type,
805 struct prestera_fw_event_handler *eh)
807 struct prestera_fw_event_handler *tmp;
811 tmp = __find_event_handler(sw, type);
821 static int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size)
823 struct prestera_switch *sw = dev->priv;
824 struct prestera_msg_event *msg = buf;
825 struct prestera_fw_event_handler eh;
826 struct prestera_event evt;
830 msg_type = __le16_to_cpu(msg->type);
831 if (msg_type >= PRESTERA_EVENT_TYPE_MAX)
833 if (!fw_event_parsers[msg_type].func)
836 err = prestera_find_event_handler(sw, msg_type, &eh);
840 evt.id = __le16_to_cpu(msg->id);
842 err = fw_event_parsers[msg_type].func(buf, &evt);
846 eh.func(sw, &evt, eh.arg);
851 static void prestera_pkt_recv(struct prestera_device *dev)
853 struct prestera_switch *sw = dev->priv;
854 struct prestera_fw_event_handler eh;
855 struct prestera_event ev;
858 ev.id = PRESTERA_RXTX_EVENT_RCV_PKT;
860 err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh);
864 eh.func(sw, &ev, eh.arg);
867 static u8 prestera_hw_mdix_to_eth(u8 mode)
870 case PRESTERA_PORT_TP_MDI:
872 case PRESTERA_PORT_TP_MDIX:
874 case PRESTERA_PORT_TP_AUTO:
875 return ETH_TP_MDI_AUTO;
877 return ETH_TP_MDI_INVALID;
881 static u8 prestera_hw_mdix_from_eth(u8 mode)
885 return PRESTERA_PORT_TP_MDI;
887 return PRESTERA_PORT_TP_MDIX;
888 case ETH_TP_MDI_AUTO:
889 return PRESTERA_PORT_TP_AUTO;
891 return PRESTERA_PORT_TP_NA;
895 int prestera_hw_port_info_get(const struct prestera_port *port,
896 u32 *dev_id, u32 *hw_id, u16 *fp_id)
898 struct prestera_msg_port_info_req req = {
899 .port = __cpu_to_le32(port->id),
901 struct prestera_msg_port_info_resp resp;
904 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET,
905 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
909 *dev_id = __le32_to_cpu(resp.dev_id);
910 *hw_id = __le32_to_cpu(resp.hw_id);
911 *fp_id = __le16_to_cpu(resp.fp_id);
916 int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac)
918 struct prestera_msg_switch_attr_req req = {
919 .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_MAC),
922 ether_addr_copy(req.param.mac, mac);
924 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
925 &req.cmd, sizeof(req));
928 int prestera_hw_switch_init(struct prestera_switch *sw)
930 struct prestera_msg_switch_init_resp resp;
931 struct prestera_msg_common_req req;
934 INIT_LIST_HEAD(&sw->event_handlers);
936 prestera_hw_build_tests();
938 err = prestera_cmd_ret_wait(sw, PRESTERA_CMD_TYPE_SWITCH_INIT,
939 &req.cmd, sizeof(req),
940 &resp.ret, sizeof(resp),
941 PRESTERA_SWITCH_INIT_TIMEOUT_MS);
945 sw->dev->recv_msg = prestera_evt_recv;
946 sw->dev->recv_pkt = prestera_pkt_recv;
947 sw->port_count = __le32_to_cpu(resp.port_count);
948 sw->mtu_min = PRESTERA_MIN_MTU;
949 sw->mtu_max = __le32_to_cpu(resp.mtu_max);
950 sw->id = resp.switch_id;
951 sw->lag_member_max = resp.lag_member_max;
952 sw->lag_max = resp.lag_max;
957 void prestera_hw_switch_fini(struct prestera_switch *sw)
959 WARN_ON(!list_empty(&sw->event_handlers));
962 int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms)
964 struct prestera_msg_switch_attr_req req = {
965 .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_AGEING),
967 .ageing_timeout_ms = __cpu_to_le32(ageing_ms),
971 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
972 &req.cmd, sizeof(req));
975 int prestera_hw_port_mac_mode_get(const struct prestera_port *port,
976 u32 *mode, u32 *speed, u8 *duplex, u8 *fec)
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_MAC_MODE),
981 .port = __cpu_to_le32(port->hw_id),
982 .dev = __cpu_to_le32(port->dev_id)
986 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
987 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
992 *mode = __le32_to_cpu(resp.param.link_evt.mac.mode);
995 *speed = __le32_to_cpu(resp.param.link_evt.mac.speed);
998 *duplex = resp.param.link_evt.mac.duplex;
1001 *fec = resp.param.link_evt.mac.fec;
1006 int prestera_hw_port_mac_mode_set(const struct prestera_port *port,
1007 bool admin, u32 mode, u8 inband,
1008 u32 speed, u8 duplex, u8 fec)
1010 struct prestera_msg_port_attr_req req = {
1011 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
1012 .port = __cpu_to_le32(port->hw_id),
1013 .dev = __cpu_to_le32(port->dev_id),
1018 .reg_mode.mode = __cpu_to_le32(mode),
1019 .reg_mode.inband = inband,
1020 .reg_mode.speed = __cpu_to_le32(speed),
1021 .reg_mode.duplex = duplex,
1028 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1029 &req.cmd, sizeof(req));
1032 int prestera_hw_port_phy_mode_get(const struct prestera_port *port,
1033 u8 *mdix, u64 *lmode_bmap,
1034 bool *fc_pause, bool *fc_asym)
1036 struct prestera_msg_port_attr_resp resp;
1037 struct prestera_msg_port_attr_req req = {
1038 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_MODE),
1039 .port = __cpu_to_le32(port->hw_id),
1040 .dev = __cpu_to_le32(port->dev_id)
1044 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1045 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1050 *mdix = prestera_hw_mdix_to_eth(resp.param.link_evt.phy.mdix);
1053 *lmode_bmap = __le64_to_cpu(resp.param.link_evt.phy.lmode_bmap);
1055 if (fc_pause && fc_asym)
1056 prestera_hw_remote_fc_to_eth(resp.param.link_evt.phy.fc,
1062 int prestera_hw_port_phy_mode_set(const struct prestera_port *port,
1063 bool admin, bool adv, u32 mode, u64 modes,
1066 struct prestera_msg_port_attr_req req = {
1067 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_MODE),
1068 .port = __cpu_to_le32(port->hw_id),
1069 .dev = __cpu_to_le32(port->dev_id),
1074 .adv_enable = adv ? 1 : 0,
1075 .mode = __cpu_to_le32(mode),
1076 .modes = __cpu_to_le64(modes),
1082 req.param.link.phy.mdix = prestera_hw_mdix_from_eth(mdix);
1084 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1085 &req.cmd, sizeof(req));
1088 int prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu)
1090 struct prestera_msg_port_attr_req req = {
1091 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MTU),
1092 .port = __cpu_to_le32(port->hw_id),
1093 .dev = __cpu_to_le32(port->dev_id),
1095 .mtu = __cpu_to_le32(mtu),
1099 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1100 &req.cmd, sizeof(req));
1103 int prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac)
1105 struct prestera_msg_port_attr_req req = {
1106 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC),
1107 .port = __cpu_to_le32(port->hw_id),
1108 .dev = __cpu_to_le32(port->dev_id),
1111 ether_addr_copy(req.param.mac, mac);
1113 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1114 &req.cmd, sizeof(req));
1117 int prestera_hw_port_accept_frm_type(struct prestera_port *port,
1118 enum prestera_accept_frm_type type)
1120 struct prestera_msg_port_attr_req req = {
1121 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE),
1122 .port = __cpu_to_le32(port->hw_id),
1123 .dev = __cpu_to_le32(port->dev_id),
1125 .accept_frm_type = type,
1129 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1130 &req.cmd, sizeof(req));
1133 int prestera_hw_port_cap_get(const struct prestera_port *port,
1134 struct prestera_port_caps *caps)
1136 struct prestera_msg_port_attr_req req = {
1137 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_CAPABILITY),
1138 .port = __cpu_to_le32(port->hw_id),
1139 .dev = __cpu_to_le32(port->dev_id),
1141 struct prestera_msg_port_attr_resp resp;
1144 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1145 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1149 caps->supp_link_modes = __le64_to_cpu(resp.param.cap.link_mode);
1150 caps->transceiver = resp.param.cap.transceiver;
1151 caps->supp_fec = resp.param.cap.fec;
1152 caps->type = resp.param.cap.type;
1157 static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause)
1160 case PRESTERA_FC_SYMMETRIC:
1162 *asym_pause = false;
1164 case PRESTERA_FC_ASYMMETRIC:
1168 case PRESTERA_FC_SYMM_ASYMM:
1174 *asym_pause = false;
1178 int prestera_hw_vtcam_create(struct prestera_switch *sw,
1179 u8 lookup, const u32 *keymask, u32 *vtcam_id,
1180 enum prestera_hw_vtcam_direction_t dir)
1183 struct prestera_msg_vtcam_resp resp;
1184 struct prestera_msg_vtcam_create_req req = {
1190 memcpy(req.keymask, keymask, sizeof(req.keymask));
1192 memset(req.keymask, 0, sizeof(req.keymask));
1194 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_CREATE,
1195 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1199 *vtcam_id = __le32_to_cpu(resp.vtcam_id);
1203 int prestera_hw_vtcam_destroy(struct prestera_switch *sw, u32 vtcam_id)
1205 struct prestera_msg_vtcam_destroy_req req = {
1206 .vtcam_id = __cpu_to_le32(vtcam_id),
1209 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_DESTROY,
1210 &req.cmd, sizeof(req));
1214 prestera_acl_rule_add_put_action(struct prestera_msg_acl_action *action,
1215 struct prestera_acl_hw_action_info *info)
1217 action->id = __cpu_to_le32(info->id);
1220 case PRESTERA_ACL_RULE_ACTION_ACCEPT:
1221 case PRESTERA_ACL_RULE_ACTION_DROP:
1222 case PRESTERA_ACL_RULE_ACTION_TRAP:
1223 /* just rule action id, no specific data */
1225 case PRESTERA_ACL_RULE_ACTION_JUMP:
1226 action->jump.index = __cpu_to_le32(info->jump.index);
1228 case PRESTERA_ACL_RULE_ACTION_POLICE:
1229 action->police.id = __cpu_to_le32(info->police.id);
1231 case PRESTERA_ACL_RULE_ACTION_COUNT:
1232 action->count.id = __cpu_to_le32(info->count.id);
1241 int prestera_hw_vtcam_rule_add(struct prestera_switch *sw,
1242 u32 vtcam_id, u32 prio, void *key, void *keymask,
1243 struct prestera_acl_hw_action_info *act,
1244 u8 n_act, u32 *rule_id)
1246 struct prestera_msg_acl_action *actions_msg;
1247 struct prestera_msg_vtcam_rule_add_req *req;
1248 struct prestera_msg_vtcam_resp resp;
1254 size = sizeof(*req) + sizeof(*actions_msg) * n_act;
1256 buff = kzalloc(size, GFP_KERNEL);
1261 req->n_act = __cpu_to_le32(n_act);
1262 actions_msg = buff + sizeof(*req);
1264 /* put acl matches into the message */
1265 memcpy(req->key, key, sizeof(req->key));
1266 memcpy(req->keymask, keymask, sizeof(req->keymask));
1268 /* put acl actions into the message */
1269 for (i = 0; i < n_act; i++) {
1270 err = prestera_acl_rule_add_put_action(&actions_msg[i],
1276 req->vtcam_id = __cpu_to_le32(vtcam_id);
1277 req->prio = __cpu_to_le32(prio);
1279 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_ADD,
1280 &req->cmd, size, &resp.ret, sizeof(resp));
1284 *rule_id = __le32_to_cpu(resp.rule_id);
1290 int prestera_hw_vtcam_rule_del(struct prestera_switch *sw,
1291 u32 vtcam_id, u32 rule_id)
1293 struct prestera_msg_vtcam_rule_del_req req = {
1294 .vtcam_id = __cpu_to_le32(vtcam_id),
1295 .id = __cpu_to_le32(rule_id)
1298 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_DELETE,
1299 &req.cmd, sizeof(req));
1302 int prestera_hw_vtcam_iface_bind(struct prestera_switch *sw,
1303 struct prestera_acl_iface *iface,
1304 u32 vtcam_id, u16 pcl_id)
1306 struct prestera_msg_vtcam_bind_req req = {
1307 .vtcam_id = __cpu_to_le32(vtcam_id),
1308 .type = __cpu_to_le16(iface->type),
1309 .pcl_id = __cpu_to_le16(pcl_id)
1312 if (iface->type == PRESTERA_ACL_IFACE_TYPE_PORT) {
1313 req.port.dev_id = __cpu_to_le32(iface->port->dev_id);
1314 req.port.hw_id = __cpu_to_le32(iface->port->hw_id);
1316 req.index = __cpu_to_le32(iface->index);
1319 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_BIND,
1320 &req.cmd, sizeof(req));
1323 int prestera_hw_vtcam_iface_unbind(struct prestera_switch *sw,
1324 struct prestera_acl_iface *iface,
1327 struct prestera_msg_vtcam_bind_req req = {
1328 .vtcam_id = __cpu_to_le32(vtcam_id),
1329 .type = __cpu_to_le16(iface->type)
1332 if (iface->type == PRESTERA_ACL_IFACE_TYPE_PORT) {
1333 req.port.dev_id = __cpu_to_le32(iface->port->dev_id);
1334 req.port.hw_id = __cpu_to_le32(iface->port->hw_id);
1336 req.index = __cpu_to_le32(iface->index);
1339 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_UNBIND,
1340 &req.cmd, sizeof(req));
1343 int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id)
1345 struct prestera_msg_span_resp resp;
1346 struct prestera_msg_span_req req = {
1347 .port = __cpu_to_le32(port->hw_id),
1348 .dev = __cpu_to_le32(port->dev_id),
1352 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_SPAN_GET,
1353 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1362 int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id)
1364 struct prestera_msg_span_req req = {
1365 .port = __cpu_to_le32(port->hw_id),
1366 .dev = __cpu_to_le32(port->dev_id),
1370 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_BIND,
1371 &req.cmd, sizeof(req));
1374 int prestera_hw_span_unbind(const struct prestera_port *port)
1376 struct prestera_msg_span_req req = {
1377 .port = __cpu_to_le32(port->hw_id),
1378 .dev = __cpu_to_le32(port->dev_id),
1381 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_UNBIND,
1382 &req.cmd, sizeof(req));
1385 int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id)
1387 struct prestera_msg_span_req req = {
1391 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SPAN_RELEASE,
1392 &req.cmd, sizeof(req));
1395 int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
1397 struct prestera_msg_port_attr_req req = {
1398 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_TYPE),
1399 .port = __cpu_to_le32(port->hw_id),
1400 .dev = __cpu_to_le32(port->dev_id),
1402 struct prestera_msg_port_attr_resp resp;
1405 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1406 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1410 *type = resp.param.type;
1415 int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed)
1417 struct prestera_msg_port_attr_req req = {
1418 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_SPEED),
1419 .port = __cpu_to_le32(port->hw_id),
1420 .dev = __cpu_to_le32(port->dev_id),
1422 struct prestera_msg_port_attr_resp resp;
1425 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1426 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1430 *speed = __le32_to_cpu(resp.param.speed);
1435 int prestera_hw_port_autoneg_restart(struct prestera_port *port)
1437 struct prestera_msg_port_attr_req req = {
1439 __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART),
1440 .port = __cpu_to_le32(port->hw_id),
1441 .dev = __cpu_to_le32(port->dev_id),
1444 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1445 &req.cmd, sizeof(req));
1448 int prestera_hw_port_stats_get(const struct prestera_port *port,
1449 struct prestera_port_stats *st)
1451 struct prestera_msg_port_attr_req req = {
1452 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_STATS),
1453 .port = __cpu_to_le32(port->hw_id),
1454 .dev = __cpu_to_le32(port->dev_id),
1456 struct prestera_msg_port_stats_resp resp;
1457 __le64 *hw = resp.stats;
1460 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1461 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1465 st->good_octets_received =
1466 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_RCV_CNT]);
1467 st->bad_octets_received =
1468 __le64_to_cpu(hw[PRESTERA_PORT_BAD_OCTETS_RCV_CNT]);
1469 st->mac_trans_error =
1470 __le64_to_cpu(hw[PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT]);
1471 st->broadcast_frames_received =
1472 __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_RCV_CNT]);
1473 st->multicast_frames_received =
1474 __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_RCV_CNT]);
1475 st->frames_64_octets = __le64_to_cpu(hw[PRESTERA_PORT_PKTS_64L_CNT]);
1476 st->frames_65_to_127_octets =
1477 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_65TO127L_CNT]);
1478 st->frames_128_to_255_octets =
1479 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_128TO255L_CNT]);
1480 st->frames_256_to_511_octets =
1481 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_256TO511L_CNT]);
1482 st->frames_512_to_1023_octets =
1483 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_512TO1023L_CNT]);
1484 st->frames_1024_to_max_octets =
1485 __le64_to_cpu(hw[PRESTERA_PORT_PKTS_1024TOMAXL_CNT]);
1486 st->excessive_collision =
1487 __le64_to_cpu(hw[PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT]);
1488 st->multicast_frames_sent =
1489 __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_SENT_CNT]);
1490 st->broadcast_frames_sent =
1491 __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_SENT_CNT]);
1492 st->fc_sent = __le64_to_cpu(hw[PRESTERA_PORT_FC_SENT_CNT]);
1493 st->fc_received = __le64_to_cpu(hw[PRESTERA_PORT_GOOD_FC_RCV_CNT]);
1494 st->buffer_overrun = __le64_to_cpu(hw[PRESTERA_PORT_DROP_EVENTS_CNT]);
1495 st->undersize = __le64_to_cpu(hw[PRESTERA_PORT_UNDERSIZE_PKTS_CNT]);
1496 st->fragments = __le64_to_cpu(hw[PRESTERA_PORT_FRAGMENTS_PKTS_CNT]);
1497 st->oversize = __le64_to_cpu(hw[PRESTERA_PORT_OVERSIZE_PKTS_CNT]);
1498 st->jabber = __le64_to_cpu(hw[PRESTERA_PORT_JABBER_PKTS_CNT]);
1499 st->rx_error_frame_received =
1500 __le64_to_cpu(hw[PRESTERA_PORT_MAC_RCV_ERROR_CNT]);
1501 st->bad_crc = __le64_to_cpu(hw[PRESTERA_PORT_BAD_CRC_CNT]);
1502 st->collisions = __le64_to_cpu(hw[PRESTERA_PORT_COLLISIONS_CNT]);
1503 st->late_collision =
1504 __le64_to_cpu(hw[PRESTERA_PORT_LATE_COLLISIONS_CNT]);
1505 st->unicast_frames_received =
1506 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT]);
1507 st->unicast_frames_sent =
1508 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT]);
1510 __le64_to_cpu(hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT]);
1512 __le64_to_cpu(hw[PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT]);
1513 st->good_octets_sent =
1514 __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT]);
1519 int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
1521 struct prestera_msg_port_attr_req req = {
1522 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_LEARNING),
1523 .port = __cpu_to_le32(port->hw_id),
1524 .dev = __cpu_to_le32(port->dev_id),
1530 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1531 &req.cmd, sizeof(req));
1534 static int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood)
1536 struct prestera_msg_port_attr_req req = {
1537 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1538 .port = __cpu_to_le32(port->hw_id),
1539 .dev = __cpu_to_le32(port->dev_id),
1542 .type = PRESTERA_PORT_FLOOD_TYPE_UC,
1548 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1549 &req.cmd, sizeof(req));
1552 static int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood)
1554 struct prestera_msg_port_attr_req req = {
1555 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1556 .port = __cpu_to_le32(port->hw_id),
1557 .dev = __cpu_to_le32(port->dev_id),
1560 .type = PRESTERA_PORT_FLOOD_TYPE_MC,
1566 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1567 &req.cmd, sizeof(req));
1570 static int prestera_hw_port_flood_set_v2(struct prestera_port *port, bool flood)
1572 struct prestera_msg_port_attr_req req = {
1573 .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1574 .port = __cpu_to_le32(port->hw_id),
1575 .dev = __cpu_to_le32(port->dev_id),
1581 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1582 &req.cmd, sizeof(req));
1585 int prestera_hw_port_flood_set(struct prestera_port *port, unsigned long mask,
1590 if (port->sw->dev->fw_rev.maj <= 2) {
1591 if (!(mask & BR_FLOOD))
1594 return prestera_hw_port_flood_set_v2(port, val & BR_FLOOD);
1597 if (mask & BR_FLOOD) {
1598 err = prestera_hw_port_uc_flood_set(port, val & BR_FLOOD);
1603 if (mask & BR_MCAST_FLOOD) {
1604 err = prestera_hw_port_mc_flood_set(port, val & BR_MCAST_FLOOD);
1612 prestera_hw_port_mc_flood_set(port, 0);
1614 if (mask & BR_FLOOD)
1615 prestera_hw_port_uc_flood_set(port, 0);
1620 int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
1622 struct prestera_msg_vlan_req req = {
1623 .vid = __cpu_to_le16(vid),
1626 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE,
1627 &req.cmd, sizeof(req));
1630 int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid)
1632 struct prestera_msg_vlan_req req = {
1633 .vid = __cpu_to_le16(vid),
1636 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE,
1637 &req.cmd, sizeof(req));
1640 int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid,
1641 bool is_member, bool untagged)
1643 struct prestera_msg_vlan_req req = {
1644 .port = __cpu_to_le32(port->hw_id),
1645 .dev = __cpu_to_le32(port->dev_id),
1646 .vid = __cpu_to_le16(vid),
1647 .is_member = is_member,
1648 .is_tagged = !untagged,
1651 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET,
1652 &req.cmd, sizeof(req));
1655 int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid)
1657 struct prestera_msg_vlan_req req = {
1658 .port = __cpu_to_le32(port->hw_id),
1659 .dev = __cpu_to_le32(port->dev_id),
1660 .vid = __cpu_to_le16(vid),
1663 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET,
1664 &req.cmd, sizeof(req));
1667 int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state)
1669 struct prestera_msg_stp_req req = {
1670 .port = __cpu_to_le32(port->hw_id),
1671 .dev = __cpu_to_le32(port->dev_id),
1672 .vid = __cpu_to_le16(vid),
1676 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET,
1677 &req.cmd, sizeof(req));
1680 int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac,
1681 u16 vid, bool dynamic)
1683 struct prestera_msg_fdb_req req = {
1685 .dev = __cpu_to_le32(port->dev_id),
1686 .port = __cpu_to_le32(port->hw_id),
1688 .vid = __cpu_to_le16(vid),
1692 ether_addr_copy(req.mac, mac);
1694 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD,
1695 &req.cmd, sizeof(req));
1698 int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac,
1701 struct prestera_msg_fdb_req req = {
1703 .dev = __cpu_to_le32(port->dev_id),
1704 .port = __cpu_to_le32(port->hw_id),
1706 .vid = __cpu_to_le16(vid),
1709 ether_addr_copy(req.mac, mac);
1711 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1712 &req.cmd, sizeof(req));
1715 int prestera_hw_lag_fdb_add(struct prestera_switch *sw, u16 lag_id,
1716 const unsigned char *mac, u16 vid, bool dynamic)
1718 struct prestera_msg_fdb_req req = {
1719 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1721 .lag_id = __cpu_to_le16(lag_id),
1723 .vid = __cpu_to_le16(vid),
1727 ether_addr_copy(req.mac, mac);
1729 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_ADD,
1730 &req.cmd, sizeof(req));
1733 int prestera_hw_lag_fdb_del(struct prestera_switch *sw, u16 lag_id,
1734 const unsigned char *mac, u16 vid)
1736 struct prestera_msg_fdb_req req = {
1737 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1739 .lag_id = __cpu_to_le16(lag_id),
1741 .vid = __cpu_to_le16(vid),
1744 ether_addr_copy(req.mac, mac);
1746 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1747 &req.cmd, sizeof(req));
1750 int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode)
1752 struct prestera_msg_fdb_req req = {
1754 .dev = __cpu_to_le32(port->dev_id),
1755 .port = __cpu_to_le32(port->hw_id),
1757 .flush_mode = __cpu_to_le32(mode),
1760 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1761 &req.cmd, sizeof(req));
1764 int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode)
1766 struct prestera_msg_fdb_req req = {
1767 .vid = __cpu_to_le16(vid),
1768 .flush_mode = __cpu_to_le32(mode),
1771 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN,
1772 &req.cmd, sizeof(req));
1775 int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
1778 struct prestera_msg_fdb_req req = {
1780 .dev = __cpu_to_le32(port->dev_id),
1781 .port = __cpu_to_le32(port->hw_id),
1783 .vid = __cpu_to_le16(vid),
1784 .flush_mode = __cpu_to_le32(mode),
1787 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1788 &req.cmd, sizeof(req));
1791 int prestera_hw_fdb_flush_lag(struct prestera_switch *sw, u16 lag_id,
1794 struct prestera_msg_fdb_req req = {
1795 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1797 .lag_id = __cpu_to_le16(lag_id),
1799 .flush_mode = __cpu_to_le32(mode),
1802 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1803 &req.cmd, sizeof(req));
1806 int prestera_hw_fdb_flush_lag_vlan(struct prestera_switch *sw,
1807 u16 lag_id, u16 vid, u32 mode)
1809 struct prestera_msg_fdb_req req = {
1810 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1812 .lag_id = __cpu_to_le16(lag_id),
1814 .vid = __cpu_to_le16(vid),
1815 .flush_mode = __cpu_to_le32(mode),
1818 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1819 &req.cmd, sizeof(req));
1822 int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id)
1824 struct prestera_msg_bridge_resp resp;
1825 struct prestera_msg_bridge_req req;
1828 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE,
1829 &req.cmd, sizeof(req),
1830 &resp.ret, sizeof(resp));
1834 *bridge_id = __le16_to_cpu(resp.bridge);
1839 int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id)
1841 struct prestera_msg_bridge_req req = {
1842 .bridge = __cpu_to_le16(bridge_id),
1845 return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE,
1846 &req.cmd, sizeof(req));
1849 int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id)
1851 struct prestera_msg_bridge_req req = {
1852 .bridge = __cpu_to_le16(bridge_id),
1853 .port = __cpu_to_le32(port->hw_id),
1854 .dev = __cpu_to_le32(port->dev_id),
1857 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD,
1858 &req.cmd, sizeof(req));
1861 int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)
1863 struct prestera_msg_bridge_req req = {
1864 .bridge = __cpu_to_le16(bridge_id),
1865 .port = __cpu_to_le32(port->hw_id),
1866 .dev = __cpu_to_le32(port->dev_id),
1869 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE,
1870 &req.cmd, sizeof(req));
1873 static int prestera_iface_to_msg(struct prestera_iface *iface,
1874 struct prestera_msg_iface *msg_if)
1876 switch (iface->type) {
1877 case PRESTERA_IF_PORT_E:
1878 case PRESTERA_IF_VID_E:
1879 msg_if->port = __cpu_to_le32(iface->dev_port.port_num);
1880 msg_if->dev = __cpu_to_le32(iface->dev_port.hw_dev_num);
1882 case PRESTERA_IF_LAG_E:
1883 msg_if->lag_id = __cpu_to_le16(iface->lag_id);
1889 msg_if->vr_id = __cpu_to_le16(iface->vr_id);
1890 msg_if->vid = __cpu_to_le16(iface->vlan_id);
1891 msg_if->type = iface->type;
1895 int prestera_hw_rif_create(struct prestera_switch *sw,
1896 struct prestera_iface *iif, u8 *mac, u16 *rif_id)
1898 struct prestera_msg_rif_resp resp;
1899 struct prestera_msg_rif_req req;
1902 memcpy(req.mac, mac, ETH_ALEN);
1904 err = prestera_iface_to_msg(iif, &req.iif);
1908 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_CREATE,
1909 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1913 *rif_id = __le16_to_cpu(resp.rif_id);
1917 int prestera_hw_rif_delete(struct prestera_switch *sw, u16 rif_id,
1918 struct prestera_iface *iif)
1920 struct prestera_msg_rif_req req = {
1921 .rif_id = __cpu_to_le16(rif_id),
1925 err = prestera_iface_to_msg(iif, &req.iif);
1929 return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE, &req.cmd,
1933 int prestera_hw_vr_create(struct prestera_switch *sw, u16 *vr_id)
1935 struct prestera_msg_vr_resp resp;
1936 struct prestera_msg_vr_req req;
1939 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_VR_CREATE,
1940 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1944 *vr_id = __le16_to_cpu(resp.vr_id);
1948 int prestera_hw_vr_delete(struct prestera_switch *sw, u16 vr_id)
1950 struct prestera_msg_vr_req req = {
1951 .vr_id = __cpu_to_le16(vr_id),
1954 return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_VR_DELETE, &req.cmd,
1958 int prestera_hw_lpm_add(struct prestera_switch *sw, u16 vr_id,
1959 __be32 dst, u32 dst_len, u32 grp_id)
1961 struct prestera_msg_lpm_req req = {
1962 .dst_len = __cpu_to_le32(dst_len),
1963 .vr_id = __cpu_to_le16(vr_id),
1964 .grp_id = __cpu_to_le32(grp_id),
1968 return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_ADD, &req.cmd,
1972 int prestera_hw_lpm_del(struct prestera_switch *sw, u16 vr_id,
1973 __be32 dst, u32 dst_len)
1975 struct prestera_msg_lpm_req req = {
1976 .dst_len = __cpu_to_le32(dst_len),
1977 .vr_id = __cpu_to_le16(vr_id),
1981 return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_DELETE, &req.cmd,
1985 int prestera_hw_rxtx_init(struct prestera_switch *sw,
1986 struct prestera_rxtx_params *params)
1988 struct prestera_msg_rxtx_resp resp;
1989 struct prestera_msg_rxtx_req req;
1992 req.use_sdma = params->use_sdma;
1994 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT,
1995 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1999 params->map_addr = __le32_to_cpu(resp.map_addr);
2004 int prestera_hw_lag_member_add(struct prestera_port *port, u16 lag_id)
2006 struct prestera_msg_lag_req req = {
2007 .port = __cpu_to_le32(port->hw_id),
2008 .dev = __cpu_to_le32(port->dev_id),
2009 .lag_id = __cpu_to_le16(lag_id),
2012 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_ADD,
2013 &req.cmd, sizeof(req));
2016 int prestera_hw_lag_member_del(struct prestera_port *port, u16 lag_id)
2018 struct prestera_msg_lag_req req = {
2019 .port = __cpu_to_le32(port->hw_id),
2020 .dev = __cpu_to_le32(port->dev_id),
2021 .lag_id = __cpu_to_le16(lag_id),
2024 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE,
2025 &req.cmd, sizeof(req));
2028 int prestera_hw_lag_member_enable(struct prestera_port *port, u16 lag_id,
2031 struct prestera_msg_lag_req req = {
2032 .port = __cpu_to_le32(port->hw_id),
2033 .dev = __cpu_to_le32(port->dev_id),
2034 .lag_id = __cpu_to_le16(lag_id),
2038 cmd = enable ? PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE :
2039 PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE;
2041 return prestera_cmd(port->sw, cmd, &req.cmd, sizeof(req));
2045 prestera_hw_cpu_code_counters_get(struct prestera_switch *sw, u8 code,
2046 enum prestera_hw_cpu_code_cnt_t counter_type,
2049 struct prestera_msg_cpu_code_counter_req req = {
2050 .counter_type = counter_type,
2053 struct mvsw_msg_cpu_code_counter_ret resp;
2056 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET,
2057 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2061 *packet_count = __le64_to_cpu(resp.packet_count);
2066 int prestera_hw_event_handler_register(struct prestera_switch *sw,
2067 enum prestera_event_type type,
2068 prestera_event_cb_t fn,
2071 struct prestera_fw_event_handler *eh;
2073 eh = __find_event_handler(sw, type);
2077 eh = kmalloc(sizeof(*eh), GFP_KERNEL);
2085 INIT_LIST_HEAD(&eh->list);
2087 list_add_rcu(&eh->list, &sw->event_handlers);
2092 void prestera_hw_event_handler_unregister(struct prestera_switch *sw,
2093 enum prestera_event_type type,
2094 prestera_event_cb_t fn)
2096 struct prestera_fw_event_handler *eh;
2098 eh = __find_event_handler(sw, type);
2102 list_del_rcu(&eh->list);
2106 int prestera_hw_counter_trigger(struct prestera_switch *sw, u32 block_id)
2108 struct prestera_msg_counter_req req = {
2109 .block_id = __cpu_to_le32(block_id)
2112 return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_TRIGGER,
2113 &req.cmd, sizeof(req));
2116 int prestera_hw_counter_abort(struct prestera_switch *sw)
2118 struct prestera_msg_counter_req req;
2120 return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_ABORT,
2121 &req.cmd, sizeof(req));
2124 int prestera_hw_counters_get(struct prestera_switch *sw, u32 idx,
2125 u32 *len, bool *done,
2126 struct prestera_counter_stats *stats)
2128 struct prestera_msg_counter_resp *resp;
2129 struct prestera_msg_counter_req req = {
2130 .block_id = __cpu_to_le32(idx),
2131 .num_counters = __cpu_to_le32(*len),
2133 size_t size = struct_size(resp, stats, *len);
2136 resp = kmalloc(size, GFP_KERNEL);
2140 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_GET,
2141 &req.cmd, sizeof(req), &resp->ret, size);
2145 for (i = 0; i < __le32_to_cpu(resp->num_counters); i++) {
2146 stats[i].packets += __le64_to_cpu(resp->stats[i].packets);
2147 stats[i].bytes += __le64_to_cpu(resp->stats[i].bytes);
2150 *len = __le32_to_cpu(resp->num_counters);
2151 *done = __le32_to_cpu(resp->done);
2158 int prestera_hw_counter_block_get(struct prestera_switch *sw,
2159 u32 client, u32 *block_id, u32 *offset,
2162 struct prestera_msg_counter_resp resp;
2163 struct prestera_msg_counter_req req = {
2164 .client = __cpu_to_le32(client)
2168 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_GET,
2169 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2173 *block_id = __le32_to_cpu(resp.block_id);
2174 *offset = __le32_to_cpu(resp.offset);
2175 *num_counters = __le32_to_cpu(resp.num_counters);
2180 int prestera_hw_counter_block_release(struct prestera_switch *sw,
2183 struct prestera_msg_counter_req req = {
2184 .block_id = __cpu_to_le32(block_id)
2187 return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_RELEASE,
2188 &req.cmd, sizeof(req));
2191 int prestera_hw_counter_clear(struct prestera_switch *sw, u32 block_id,
2194 struct prestera_msg_counter_req req = {
2195 .block_id = __cpu_to_le32(block_id),
2196 .num_counters = __cpu_to_le32(counter_id)
2199 return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_CLEAR,
2200 &req.cmd, sizeof(req));
2203 int prestera_hw_policer_create(struct prestera_switch *sw, u8 type,
2206 struct prestera_msg_policer_resp resp;
2207 struct prestera_msg_policer_req req = {
2212 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_POLICER_CREATE,
2213 &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2217 *policer_id = __le32_to_cpu(resp.id);
2221 int prestera_hw_policer_release(struct prestera_switch *sw,
2224 struct prestera_msg_policer_req req = {
2225 .id = __cpu_to_le32(policer_id)
2228 return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_RELEASE,
2229 &req.cmd, sizeof(req));
2232 int prestera_hw_policer_sr_tcm_set(struct prestera_switch *sw,
2233 u32 policer_id, u64 cir, u32 cbs)
2235 struct prestera_msg_policer_req req = {
2236 .mode = PRESTERA_POLICER_MODE_SR_TCM,
2237 .id = __cpu_to_le32(policer_id),
2239 .cir = __cpu_to_le64(cir),
2240 .cbs = __cpu_to_le32(cbs)
2244 return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_SET,
2245 &req.cmd, sizeof(req));