brintos

brintos / linux-shallow public Read only

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