cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

prestera_hw.c (54953B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
      3
      4#include <linux/etherdevice.h>
      5#include <linux/if_bridge.h>
      6#include <linux/ethtool.h>
      7#include <linux/list.h>
      8
      9#include "prestera.h"
     10#include "prestera_hw.h"
     11#include "prestera_acl.h"
     12#include "prestera_counter.h"
     13
     14#define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
     15
     16#define PRESTERA_MIN_MTU 64
     17
     18enum prestera_cmd_type_t {
     19	PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1,
     20	PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2,
     21
     22	PRESTERA_CMD_TYPE_PORT_ATTR_SET = 0x100,
     23	PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101,
     24	PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110,
     25
     26	PRESTERA_CMD_TYPE_VLAN_CREATE = 0x200,
     27	PRESTERA_CMD_TYPE_VLAN_DELETE = 0x201,
     28	PRESTERA_CMD_TYPE_VLAN_PORT_SET = 0x202,
     29	PRESTERA_CMD_TYPE_VLAN_PVID_SET = 0x203,
     30
     31	PRESTERA_CMD_TYPE_FDB_ADD = 0x300,
     32	PRESTERA_CMD_TYPE_FDB_DELETE = 0x301,
     33	PRESTERA_CMD_TYPE_FDB_FLUSH_PORT = 0x310,
     34	PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN = 0x311,
     35	PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN = 0x312,
     36
     37	PRESTERA_CMD_TYPE_BRIDGE_CREATE = 0x400,
     38	PRESTERA_CMD_TYPE_BRIDGE_DELETE = 0x401,
     39	PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD = 0x402,
     40	PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE = 0x403,
     41
     42	PRESTERA_CMD_TYPE_COUNTER_GET = 0x510,
     43	PRESTERA_CMD_TYPE_COUNTER_ABORT = 0x511,
     44	PRESTERA_CMD_TYPE_COUNTER_TRIGGER = 0x512,
     45	PRESTERA_CMD_TYPE_COUNTER_BLOCK_GET = 0x513,
     46	PRESTERA_CMD_TYPE_COUNTER_BLOCK_RELEASE = 0x514,
     47	PRESTERA_CMD_TYPE_COUNTER_CLEAR = 0x515,
     48
     49	PRESTERA_CMD_TYPE_VTCAM_CREATE = 0x540,
     50	PRESTERA_CMD_TYPE_VTCAM_DESTROY = 0x541,
     51	PRESTERA_CMD_TYPE_VTCAM_RULE_ADD = 0x550,
     52	PRESTERA_CMD_TYPE_VTCAM_RULE_DELETE = 0x551,
     53	PRESTERA_CMD_TYPE_VTCAM_IFACE_BIND = 0x560,
     54	PRESTERA_CMD_TYPE_VTCAM_IFACE_UNBIND = 0x561,
     55
     56	PRESTERA_CMD_TYPE_ROUTER_RIF_CREATE = 0x600,
     57	PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE = 0x601,
     58	PRESTERA_CMD_TYPE_ROUTER_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,
     62
     63	PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
     64
     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,
     69
     70	PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
     71
     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,
     76
     77	PRESTERA_CMD_TYPE_POLICER_CREATE = 0x1500,
     78	PRESTERA_CMD_TYPE_POLICER_RELEASE = 0x1501,
     79	PRESTERA_CMD_TYPE_POLICER_SET = 0x1502,
     80
     81	PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET = 0x2000,
     82
     83	PRESTERA_CMD_TYPE_ACK = 0x10000,
     84	PRESTERA_CMD_TYPE_MAX
     85};
     86
     87enum {
     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,
    102};
    103
    104enum {
    105	PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
    106	PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
    107};
    108
    109enum {
    110	PRESTERA_CMD_ACK_OK,
    111	PRESTERA_CMD_ACK_FAILED,
    112
    113	PRESTERA_CMD_ACK_MAX
    114};
    115
    116enum {
    117	PRESTERA_PORT_TP_NA,
    118	PRESTERA_PORT_TP_MDI,
    119	PRESTERA_PORT_TP_MDIX,
    120	PRESTERA_PORT_TP_AUTO,
    121};
    122
    123enum {
    124	PRESTERA_PORT_FLOOD_TYPE_UC = 0,
    125	PRESTERA_PORT_FLOOD_TYPE_MC = 1,
    126};
    127
    128enum {
    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,
    159
    160	PRESTERA_PORT_CNT_MAX
    161};
    162
    163enum {
    164	PRESTERA_FC_NONE,
    165	PRESTERA_FC_SYMMETRIC,
    166	PRESTERA_FC_ASYMMETRIC,
    167	PRESTERA_FC_SYMM_ASYMM,
    168};
    169
    170enum {
    171	PRESTERA_POLICER_MODE_SR_TCM
    172};
    173
    174enum {
    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,
    178};
    179
    180struct prestera_fw_event_handler {
    181	struct list_head list;
    182	struct rcu_head rcu;
    183	enum prestera_event_type type;
    184	prestera_event_cb_t func;
    185	void *arg;
    186};
    187
    188struct prestera_msg_cmd {
    189	__le32 type;
    190};
    191
    192struct prestera_msg_ret {
    193	struct prestera_msg_cmd cmd;
    194	__le32 status;
    195};
    196
    197struct prestera_msg_common_req {
    198	struct prestera_msg_cmd cmd;
    199};
    200
    201struct prestera_msg_common_resp {
    202	struct prestera_msg_ret ret;
    203};
    204
    205struct prestera_msg_switch_attr_req {
    206	struct prestera_msg_cmd cmd;
    207	__le32 attr;
    208	union {
    209		__le32 ageing_timeout_ms;
    210		struct {
    211			u8 mac[ETH_ALEN];
    212			u8 __pad[2];
    213		};
    214	} param;
    215};
    216
    217struct prestera_msg_switch_init_resp {
    218	struct prestera_msg_ret ret;
    219	__le32 port_count;
    220	__le32 mtu_max;
    221	__le32 size_tbl_router_nexthop;
    222	u8 switch_id;
    223	u8 lag_max;
    224	u8 lag_member_max;
    225};
    226
    227struct prestera_msg_event_port_param {
    228	union {
    229		struct {
    230			__le32 mode;
    231			__le32 speed;
    232			u8 oper;
    233			u8 duplex;
    234			u8 fc;
    235			u8 fec;
    236		} mac;
    237		struct {
    238			__le64 lmode_bmap;
    239			u8 mdix;
    240			u8 fc;
    241			u8 __pad[2];
    242		} __packed phy; /* make sure always 12 bytes size */
    243	};
    244};
    245
    246struct prestera_msg_port_cap_param {
    247	__le64 link_mode;
    248	u8 type;
    249	u8 fec;
    250	u8 fc;
    251	u8 transceiver;
    252};
    253
    254struct prestera_msg_port_flood_param {
    255	u8 type;
    256	u8 enable;
    257	u8 __pad[2];
    258};
    259
    260union prestera_msg_port_param {
    261	__le32 mtu;
    262	__le32 speed;
    263	__le32 link_mode;
    264	u8 admin_state;
    265	u8 oper_state;
    266	u8 mac[ETH_ALEN];
    267	u8 accept_frm_type;
    268	u8 learning;
    269	u8 flood;
    270	u8 type;
    271	u8 duplex;
    272	u8 fec;
    273	u8 fc;
    274	union {
    275		struct {
    276			u8 admin;
    277			u8 fc;
    278			u8 ap_enable;
    279			u8 __reserved[5];
    280			union {
    281				struct {
    282					__le32 mode;
    283					__le32 speed;
    284					u8 inband;
    285					u8 duplex;
    286					u8 fec;
    287					u8 fec_supp;
    288				} reg_mode;
    289				struct {
    290					__le32 mode;
    291					__le32 speed;
    292					u8 fec;
    293					u8 fec_supp;
    294					u8 __pad[2];
    295				} ap_modes[PRESTERA_AP_PORT_MAX];
    296			};
    297		} mac;
    298		struct {
    299			__le64 modes;
    300			__le32 mode;
    301			u8 admin;
    302			u8 adv_enable;
    303			u8 mdix;
    304			u8 __pad;
    305		} phy;
    306	} link;
    307
    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;
    311};
    312
    313struct prestera_msg_port_attr_req {
    314	struct prestera_msg_cmd cmd;
    315	__le32 attr;
    316	__le32 port;
    317	__le32 dev;
    318	union prestera_msg_port_param param;
    319};
    320
    321struct prestera_msg_port_attr_resp {
    322	struct prestera_msg_ret ret;
    323	union prestera_msg_port_param param;
    324};
    325
    326struct prestera_msg_port_stats_resp {
    327	struct prestera_msg_ret ret;
    328	__le64 stats[PRESTERA_PORT_CNT_MAX];
    329};
    330
    331struct prestera_msg_port_info_req {
    332	struct prestera_msg_cmd cmd;
    333	__le32 port;
    334};
    335
    336struct prestera_msg_port_info_resp {
    337	struct prestera_msg_ret ret;
    338	__le32 hw_id;
    339	__le32 dev_id;
    340	__le16 fp_id;
    341	u8 pad[2];
    342};
    343
    344struct prestera_msg_vlan_req {
    345	struct prestera_msg_cmd cmd;
    346	__le32 port;
    347	__le32 dev;
    348	__le16 vid;
    349	u8 is_member;
    350	u8 is_tagged;
    351};
    352
    353struct prestera_msg_fdb_req {
    354	struct prestera_msg_cmd cmd;
    355	__le32 flush_mode;
    356	union {
    357		struct {
    358			__le32 port;
    359			__le32 dev;
    360		};
    361		__le16 lag_id;
    362	} dest;
    363	__le16 vid;
    364	u8 dest_type;
    365	u8 dynamic;
    366	u8 mac[ETH_ALEN];
    367	u8 __pad[2];
    368};
    369
    370struct prestera_msg_bridge_req {
    371	struct prestera_msg_cmd cmd;
    372	__le32 port;
    373	__le32 dev;
    374	__le16 bridge;
    375	u8 pad[2];
    376};
    377
    378struct prestera_msg_bridge_resp {
    379	struct prestera_msg_ret ret;
    380	__le16 bridge;
    381	u8 pad[2];
    382};
    383
    384struct prestera_msg_vtcam_create_req {
    385	struct prestera_msg_cmd cmd;
    386	__le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
    387	u8 direction;
    388	u8 lookup;
    389	u8 pad[2];
    390};
    391
    392struct prestera_msg_vtcam_destroy_req {
    393	struct prestera_msg_cmd cmd;
    394	__le32 vtcam_id;
    395};
    396
    397struct 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];
    401	__le32 vtcam_id;
    402	__le32 prio;
    403	__le32 n_act;
    404};
    405
    406struct prestera_msg_vtcam_rule_del_req {
    407	struct prestera_msg_cmd cmd;
    408	__le32 vtcam_id;
    409	__le32 id;
    410};
    411
    412struct prestera_msg_vtcam_bind_req {
    413	struct prestera_msg_cmd cmd;
    414	union {
    415		struct {
    416			__le32 hw_id;
    417			__le32 dev_id;
    418		} port;
    419		__le32 index;
    420	};
    421	__le32 vtcam_id;
    422	__le16 pcl_id;
    423	__le16 type;
    424};
    425
    426struct prestera_msg_vtcam_resp {
    427	struct prestera_msg_ret ret;
    428	__le32 vtcam_id;
    429	__le32 rule_id;
    430};
    431
    432struct prestera_msg_acl_action {
    433	__le32 id;
    434	__le32 __reserved;
    435	union {
    436		struct {
    437			__le32 index;
    438		} jump;
    439		struct {
    440			__le32 id;
    441		} police;
    442		struct {
    443			__le32 id;
    444		} count;
    445		__le32 reserved[6];
    446	};
    447};
    448
    449struct prestera_msg_counter_req {
    450	struct prestera_msg_cmd cmd;
    451	__le32 client;
    452	__le32 block_id;
    453	__le32 num_counters;
    454};
    455
    456struct prestera_msg_counter_stats {
    457	__le64 packets;
    458	__le64 bytes;
    459};
    460
    461struct prestera_msg_counter_resp {
    462	struct prestera_msg_ret ret;
    463	__le32 block_id;
    464	__le32 offset;
    465	__le32 num_counters;
    466	__le32 done;
    467	struct prestera_msg_counter_stats stats[];
    468};
    469
    470struct prestera_msg_span_req {
    471	struct prestera_msg_cmd cmd;
    472	__le32 port;
    473	__le32 dev;
    474	u8 id;
    475	u8 pad[3];
    476};
    477
    478struct prestera_msg_span_resp {
    479	struct prestera_msg_ret ret;
    480	u8 id;
    481	u8 pad[3];
    482};
    483
    484struct prestera_msg_stp_req {
    485	struct prestera_msg_cmd cmd;
    486	__le32 port;
    487	__le32 dev;
    488	__le16 vid;
    489	u8 state;
    490	u8 __pad;
    491};
    492
    493struct prestera_msg_rxtx_req {
    494	struct prestera_msg_cmd cmd;
    495	u8 use_sdma;
    496	u8 pad[3];
    497};
    498
    499struct prestera_msg_rxtx_resp {
    500	struct prestera_msg_ret ret;
    501	__le32 map_addr;
    502};
    503
    504struct prestera_msg_iface {
    505	union {
    506		struct {
    507			__le32 dev;
    508			__le32 port;
    509		};
    510		__le16 lag_id;
    511	};
    512	__le16 vr_id;
    513	__le16 vid;
    514	u8 type;
    515	u8 __pad[3];
    516};
    517
    518struct prestera_msg_ip_addr {
    519	union {
    520		__be32 ipv4;
    521		__be32 ipv6[4];
    522	} u;
    523	u8 v; /* e.g. PRESTERA_IPV4 */
    524	u8 __pad[3];
    525};
    526
    527struct prestera_msg_rif_req {
    528	struct prestera_msg_cmd cmd;
    529	struct prestera_msg_iface iif;
    530	__le32 mtu;
    531	__le16 rif_id;
    532	__le16 __reserved;
    533	u8 mac[ETH_ALEN];
    534	u8 __pad[2];
    535};
    536
    537struct prestera_msg_rif_resp {
    538	struct prestera_msg_ret ret;
    539	__le16 rif_id;
    540	u8 __pad[2];
    541};
    542
    543struct prestera_msg_lpm_req {
    544	struct prestera_msg_cmd cmd;
    545	struct prestera_msg_ip_addr dst;
    546	__le32 grp_id;
    547	__le32 dst_len;
    548	__le16 vr_id;
    549	u8 __pad[2];
    550};
    551
    552struct prestera_msg_vr_req {
    553	struct prestera_msg_cmd cmd;
    554	__le16 vr_id;
    555	u8 __pad[2];
    556};
    557
    558struct prestera_msg_vr_resp {
    559	struct prestera_msg_ret ret;
    560	__le16 vr_id;
    561	u8 __pad[2];
    562};
    563
    564struct prestera_msg_lag_req {
    565	struct prestera_msg_cmd cmd;
    566	__le32 port;
    567	__le32 dev;
    568	__le16 lag_id;
    569	u8 pad[2];
    570};
    571
    572struct prestera_msg_cpu_code_counter_req {
    573	struct prestera_msg_cmd cmd;
    574	u8 counter_type;
    575	u8 code;
    576	u8 pad[2];
    577};
    578
    579struct mvsw_msg_cpu_code_counter_ret {
    580	struct prestera_msg_ret ret;
    581	__le64 packet_count;
    582};
    583
    584struct prestera_msg_policer_req {
    585	struct prestera_msg_cmd cmd;
    586	__le32 id;
    587	union {
    588		struct {
    589			__le64 cir;
    590			__le32 cbs;
    591		} __packed sr_tcm; /* make sure always 12 bytes size */
    592		__le32 reserved[6];
    593	};
    594	u8 mode;
    595	u8 type;
    596	u8 pad[2];
    597};
    598
    599struct prestera_msg_policer_resp {
    600	struct prestera_msg_ret ret;
    601	__le32 id;
    602};
    603
    604struct prestera_msg_event {
    605	__le16 type;
    606	__le16 id;
    607};
    608
    609struct prestera_msg_event_port {
    610	struct prestera_msg_event id;
    611	__le32 port_id;
    612	struct prestera_msg_event_port_param param;
    613};
    614
    615union prestera_msg_event_fdb_param {
    616	u8 mac[ETH_ALEN];
    617};
    618
    619struct prestera_msg_event_fdb {
    620	struct prestera_msg_event id;
    621	__le32 vid;
    622	union {
    623		__le32 port_id;
    624		__le16 lag_id;
    625	} dest;
    626	union prestera_msg_event_fdb_param param;
    627	u8 dest_type;
    628};
    629
    630static void prestera_hw_build_tests(void)
    631{
    632	/* check requests */
    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);
    657
    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);
    661
    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);
    676
    677	/* check events */
    678	BUILD_BUG_ON(sizeof(struct prestera_msg_event_port) != 20);
    679	BUILD_BUG_ON(sizeof(struct prestera_msg_event_fdb) != 20);
    680}
    681
    682static u8 prestera_hw_mdix_to_eth(u8 mode);
    683static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause);
    684
    685static 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,
    689			      int waitms)
    690{
    691	struct prestera_device *dev = sw->dev;
    692	int err;
    693
    694	cmd->type = __cpu_to_le32(type);
    695
    696	err = dev->send_req(dev, 0, cmd, clen, ret, rlen, waitms);
    697	if (err)
    698		return err;
    699
    700	if (ret->cmd.type != __cpu_to_le32(PRESTERA_CMD_TYPE_ACK))
    701		return -EBADE;
    702	if (ret->status != __cpu_to_le32(PRESTERA_CMD_ACK_OK))
    703		return -EINVAL;
    704
    705	return 0;
    706}
    707
    708static 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)
    712{
    713	return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0);
    714}
    715
    716static 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,
    720				 int waitms)
    721{
    722	return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms);
    723}
    724
    725static int prestera_cmd(struct prestera_switch *sw,
    726			enum prestera_cmd_type_t type,
    727			struct prestera_msg_cmd *cmd, size_t clen)
    728{
    729	struct prestera_msg_common_resp resp;
    730
    731	return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp));
    732}
    733
    734static int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt)
    735{
    736	struct prestera_msg_event_port *hw_evt;
    737
    738	hw_evt = (struct prestera_msg_event_port *)msg;
    739
    740	evt->port_evt.port_id = __le32_to_cpu(hw_evt->port_id);
    741
    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;
    751	} else {
    752		return -EINVAL;
    753	}
    754
    755	return 0;
    756}
    757
    758static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt)
    759{
    760	struct prestera_msg_event_fdb *hw_evt = msg;
    761
    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);
    766		break;
    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);
    770		break;
    771	default:
    772		return -EINVAL;
    773	}
    774
    775	evt->fdb_evt.vid = __le32_to_cpu(hw_evt->vid);
    776
    777	ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac);
    778
    779	return 0;
    780}
    781
    782static 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 },
    787};
    788
    789static struct prestera_fw_event_handler *
    790__find_event_handler(const struct prestera_switch *sw,
    791		     enum prestera_event_type type)
    792{
    793	struct prestera_fw_event_handler *eh;
    794
    795	list_for_each_entry_rcu(eh, &sw->event_handlers, list) {
    796		if (eh->type == type)
    797			return eh;
    798	}
    799
    800	return NULL;
    801}
    802
    803static int prestera_find_event_handler(const struct prestera_switch *sw,
    804				       enum prestera_event_type type,
    805				       struct prestera_fw_event_handler *eh)
    806{
    807	struct prestera_fw_event_handler *tmp;
    808	int err = 0;
    809
    810	rcu_read_lock();
    811	tmp = __find_event_handler(sw, type);
    812	if (tmp)
    813		*eh = *tmp;
    814	else
    815		err = -ENOENT;
    816	rcu_read_unlock();
    817
    818	return err;
    819}
    820
    821static int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size)
    822{
    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;
    827	u16 msg_type;
    828	int err;
    829
    830	msg_type = __le16_to_cpu(msg->type);
    831	if (msg_type >= PRESTERA_EVENT_TYPE_MAX)
    832		return -EINVAL;
    833	if (!fw_event_parsers[msg_type].func)
    834		return -ENOENT;
    835
    836	err = prestera_find_event_handler(sw, msg_type, &eh);
    837	if (err)
    838		return err;
    839
    840	evt.id = __le16_to_cpu(msg->id);
    841
    842	err = fw_event_parsers[msg_type].func(buf, &evt);
    843	if (err)
    844		return err;
    845
    846	eh.func(sw, &evt, eh.arg);
    847
    848	return 0;
    849}
    850
    851static void prestera_pkt_recv(struct prestera_device *dev)
    852{
    853	struct prestera_switch *sw = dev->priv;
    854	struct prestera_fw_event_handler eh;
    855	struct prestera_event ev;
    856	int err;
    857
    858	ev.id = PRESTERA_RXTX_EVENT_RCV_PKT;
    859
    860	err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh);
    861	if (err)
    862		return;
    863
    864	eh.func(sw, &ev, eh.arg);
    865}
    866
    867static u8 prestera_hw_mdix_to_eth(u8 mode)
    868{
    869	switch (mode) {
    870	case PRESTERA_PORT_TP_MDI:
    871		return ETH_TP_MDI;
    872	case PRESTERA_PORT_TP_MDIX:
    873		return ETH_TP_MDI_X;
    874	case PRESTERA_PORT_TP_AUTO:
    875		return ETH_TP_MDI_AUTO;
    876	default:
    877		return ETH_TP_MDI_INVALID;
    878	}
    879}
    880
    881static u8 prestera_hw_mdix_from_eth(u8 mode)
    882{
    883	switch (mode) {
    884	case ETH_TP_MDI:
    885		return PRESTERA_PORT_TP_MDI;
    886	case ETH_TP_MDI_X:
    887		return PRESTERA_PORT_TP_MDIX;
    888	case ETH_TP_MDI_AUTO:
    889		return PRESTERA_PORT_TP_AUTO;
    890	default:
    891		return PRESTERA_PORT_TP_NA;
    892	}
    893}
    894
    895int prestera_hw_port_info_get(const struct prestera_port *port,
    896			      u32 *dev_id, u32 *hw_id, u16 *fp_id)
    897{
    898	struct prestera_msg_port_info_req req = {
    899		.port = __cpu_to_le32(port->id),
    900	};
    901	struct prestera_msg_port_info_resp resp;
    902	int err;
    903
    904	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET,
    905			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
    906	if (err)
    907		return err;
    908
    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);
    912
    913	return 0;
    914}
    915
    916int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac)
    917{
    918	struct prestera_msg_switch_attr_req req = {
    919		.attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_MAC),
    920	};
    921
    922	ether_addr_copy(req.param.mac, mac);
    923
    924	return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
    925			    &req.cmd, sizeof(req));
    926}
    927
    928int prestera_hw_switch_init(struct prestera_switch *sw)
    929{
    930	struct prestera_msg_switch_init_resp resp;
    931	struct prestera_msg_common_req req;
    932	int err;
    933
    934	INIT_LIST_HEAD(&sw->event_handlers);
    935
    936	prestera_hw_build_tests();
    937
    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);
    942	if (err)
    943		return err;
    944
    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;
    953
    954	return 0;
    955}
    956
    957void prestera_hw_switch_fini(struct prestera_switch *sw)
    958{
    959	WARN_ON(!list_empty(&sw->event_handlers));
    960}
    961
    962int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms)
    963{
    964	struct prestera_msg_switch_attr_req req = {
    965		.attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_AGEING),
    966		.param = {
    967			.ageing_timeout_ms = __cpu_to_le32(ageing_ms),
    968		},
    969	};
    970
    971	return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
    972			    &req.cmd, sizeof(req));
    973}
    974
    975int prestera_hw_port_mac_mode_get(const struct prestera_port *port,
    976				  u32 *mode, u32 *speed, u8 *duplex, u8 *fec)
    977{
    978	struct prestera_msg_port_attr_resp resp;
    979	struct prestera_msg_port_attr_req req = {
    980		.attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
    981		.port = __cpu_to_le32(port->hw_id),
    982		.dev = __cpu_to_le32(port->dev_id)
    983	};
    984	int err;
    985
    986	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
    987			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
    988	if (err)
    989		return err;
    990
    991	if (mode)
    992		*mode = __le32_to_cpu(resp.param.link_evt.mac.mode);
    993
    994	if (speed)
    995		*speed = __le32_to_cpu(resp.param.link_evt.mac.speed);
    996
    997	if (duplex)
    998		*duplex = resp.param.link_evt.mac.duplex;
    999
   1000	if (fec)
   1001		*fec = resp.param.link_evt.mac.fec;
   1002
   1003	return err;
   1004}
   1005
   1006int 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)
   1009{
   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),
   1014		.param = {
   1015			.link = {
   1016				.mac = {
   1017					.admin = admin,
   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,
   1022					.reg_mode.fec = fec
   1023				}
   1024			}
   1025		}
   1026	};
   1027
   1028	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
   1029			    &req.cmd, sizeof(req));
   1030}
   1031
   1032int prestera_hw_port_phy_mode_get(const struct prestera_port *port,
   1033				  u8 *mdix, u64 *lmode_bmap,
   1034				  bool *fc_pause, bool *fc_asym)
   1035{
   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)
   1041	};
   1042	int err;
   1043
   1044	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
   1045			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   1046	if (err)
   1047		return err;
   1048
   1049	if (mdix)
   1050		*mdix = prestera_hw_mdix_to_eth(resp.param.link_evt.phy.mdix);
   1051
   1052	if (lmode_bmap)
   1053		*lmode_bmap = __le64_to_cpu(resp.param.link_evt.phy.lmode_bmap);
   1054
   1055	if (fc_pause && fc_asym)
   1056		prestera_hw_remote_fc_to_eth(resp.param.link_evt.phy.fc,
   1057					     fc_pause, fc_asym);
   1058
   1059	return err;
   1060}
   1061
   1062int prestera_hw_port_phy_mode_set(const struct prestera_port *port,
   1063				  bool admin, bool adv, u32 mode, u64 modes,
   1064				  u8 mdix)
   1065{
   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),
   1070		.param = {
   1071			.link = {
   1072				.phy = {
   1073					.admin = admin,
   1074					.adv_enable = adv ? 1 : 0,
   1075					.mode = __cpu_to_le32(mode),
   1076					.modes = __cpu_to_le64(modes),
   1077				}
   1078			}
   1079		}
   1080	};
   1081
   1082	req.param.link.phy.mdix = prestera_hw_mdix_from_eth(mdix);
   1083
   1084	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
   1085			    &req.cmd, sizeof(req));
   1086}
   1087
   1088int prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu)
   1089{
   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),
   1094		.param = {
   1095			.mtu = __cpu_to_le32(mtu),
   1096		}
   1097	};
   1098
   1099	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
   1100			    &req.cmd, sizeof(req));
   1101}
   1102
   1103int prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac)
   1104{
   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),
   1109	};
   1110
   1111	ether_addr_copy(req.param.mac, mac);
   1112
   1113	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
   1114			    &req.cmd, sizeof(req));
   1115}
   1116
   1117int prestera_hw_port_accept_frm_type(struct prestera_port *port,
   1118				     enum prestera_accept_frm_type type)
   1119{
   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),
   1124		.param = {
   1125			.accept_frm_type = type,
   1126		}
   1127	};
   1128
   1129	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
   1130			    &req.cmd, sizeof(req));
   1131}
   1132
   1133int prestera_hw_port_cap_get(const struct prestera_port *port,
   1134			     struct prestera_port_caps *caps)
   1135{
   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),
   1140	};
   1141	struct prestera_msg_port_attr_resp resp;
   1142	int err;
   1143
   1144	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
   1145			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   1146	if (err)
   1147		return err;
   1148
   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;
   1153
   1154	return err;
   1155}
   1156
   1157static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause)
   1158{
   1159	switch (fc) {
   1160	case PRESTERA_FC_SYMMETRIC:
   1161		*pause = true;
   1162		*asym_pause = false;
   1163		break;
   1164	case PRESTERA_FC_ASYMMETRIC:
   1165		*pause = false;
   1166		*asym_pause = true;
   1167		break;
   1168	case PRESTERA_FC_SYMM_ASYMM:
   1169		*pause = true;
   1170		*asym_pause = true;
   1171		break;
   1172	default:
   1173		*pause = false;
   1174		*asym_pause = false;
   1175	}
   1176}
   1177
   1178int 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)
   1181{
   1182	int err;
   1183	struct prestera_msg_vtcam_resp resp;
   1184	struct prestera_msg_vtcam_create_req req = {
   1185		.lookup = lookup,
   1186		.direction = dir,
   1187	};
   1188
   1189	if (keymask)
   1190		memcpy(req.keymask, keymask, sizeof(req.keymask));
   1191	else
   1192		memset(req.keymask, 0, sizeof(req.keymask));
   1193
   1194	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_CREATE,
   1195			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   1196	if (err)
   1197		return err;
   1198
   1199	*vtcam_id = __le32_to_cpu(resp.vtcam_id);
   1200	return 0;
   1201}
   1202
   1203int prestera_hw_vtcam_destroy(struct prestera_switch *sw, u32 vtcam_id)
   1204{
   1205	struct prestera_msg_vtcam_destroy_req req = {
   1206		.vtcam_id = __cpu_to_le32(vtcam_id),
   1207	};
   1208
   1209	return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_DESTROY,
   1210			    &req.cmd, sizeof(req));
   1211}
   1212
   1213static int
   1214prestera_acl_rule_add_put_action(struct prestera_msg_acl_action *action,
   1215				 struct prestera_acl_hw_action_info *info)
   1216{
   1217	action->id = __cpu_to_le32(info->id);
   1218
   1219	switch (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 */
   1224		break;
   1225	case PRESTERA_ACL_RULE_ACTION_JUMP:
   1226		action->jump.index = __cpu_to_le32(info->jump.index);
   1227		break;
   1228	case PRESTERA_ACL_RULE_ACTION_POLICE:
   1229		action->police.id = __cpu_to_le32(info->police.id);
   1230		break;
   1231	case PRESTERA_ACL_RULE_ACTION_COUNT:
   1232		action->count.id = __cpu_to_le32(info->count.id);
   1233		break;
   1234	default:
   1235		return -EINVAL;
   1236	}
   1237
   1238	return 0;
   1239}
   1240
   1241int 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)
   1245{
   1246	struct prestera_msg_acl_action *actions_msg;
   1247	struct prestera_msg_vtcam_rule_add_req *req;
   1248	struct prestera_msg_vtcam_resp resp;
   1249	void *buff;
   1250	u32 size;
   1251	int err;
   1252	u8 i;
   1253
   1254	size = sizeof(*req) + sizeof(*actions_msg) * n_act;
   1255
   1256	buff = kzalloc(size, GFP_KERNEL);
   1257	if (!buff)
   1258		return -ENOMEM;
   1259
   1260	req = buff;
   1261	req->n_act = __cpu_to_le32(n_act);
   1262	actions_msg = buff + sizeof(*req);
   1263
   1264	/* put acl matches into the message */
   1265	memcpy(req->key, key, sizeof(req->key));
   1266	memcpy(req->keymask, keymask, sizeof(req->keymask));
   1267
   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],
   1271						       &act[i]);
   1272		if (err)
   1273			goto free_buff;
   1274	}
   1275
   1276	req->vtcam_id = __cpu_to_le32(vtcam_id);
   1277	req->prio = __cpu_to_le32(prio);
   1278
   1279	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_ADD,
   1280			       &req->cmd, size, &resp.ret, sizeof(resp));
   1281	if (err)
   1282		goto free_buff;
   1283
   1284	*rule_id = __le32_to_cpu(resp.rule_id);
   1285free_buff:
   1286	kfree(buff);
   1287	return err;
   1288}
   1289
   1290int prestera_hw_vtcam_rule_del(struct prestera_switch *sw,
   1291			       u32 vtcam_id, u32 rule_id)
   1292{
   1293	struct prestera_msg_vtcam_rule_del_req req = {
   1294		.vtcam_id = __cpu_to_le32(vtcam_id),
   1295		.id = __cpu_to_le32(rule_id)
   1296	};
   1297
   1298	return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_DELETE,
   1299			    &req.cmd, sizeof(req));
   1300}
   1301
   1302int prestera_hw_vtcam_iface_bind(struct prestera_switch *sw,
   1303				 struct prestera_acl_iface *iface,
   1304				 u32 vtcam_id, u16 pcl_id)
   1305{
   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)
   1310	};
   1311
   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);
   1315	} else {
   1316		req.index = __cpu_to_le32(iface->index);
   1317	}
   1318
   1319	return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_BIND,
   1320			    &req.cmd, sizeof(req));
   1321}
   1322
   1323int prestera_hw_vtcam_iface_unbind(struct prestera_switch *sw,
   1324				   struct prestera_acl_iface *iface,
   1325				   u32 vtcam_id)
   1326{
   1327	struct prestera_msg_vtcam_bind_req req = {
   1328		.vtcam_id = __cpu_to_le32(vtcam_id),
   1329		.type = __cpu_to_le16(iface->type)
   1330	};
   1331
   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);
   1335	} else {
   1336		req.index = __cpu_to_le32(iface->index);
   1337	}
   1338
   1339	return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_UNBIND,
   1340			    &req.cmd, sizeof(req));
   1341}
   1342
   1343int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id)
   1344{
   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),
   1349	};
   1350	int err;
   1351
   1352	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_SPAN_GET,
   1353			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   1354	if (err)
   1355		return err;
   1356
   1357	*span_id = resp.id;
   1358
   1359	return 0;
   1360}
   1361
   1362int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id)
   1363{
   1364	struct prestera_msg_span_req req = {
   1365		.port = __cpu_to_le32(port->hw_id),
   1366		.dev = __cpu_to_le32(port->dev_id),
   1367		.id = span_id,
   1368	};
   1369
   1370	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_BIND,
   1371			    &req.cmd, sizeof(req));
   1372}
   1373
   1374int prestera_hw_span_unbind(const struct prestera_port *port)
   1375{
   1376	struct prestera_msg_span_req req = {
   1377		.port = __cpu_to_le32(port->hw_id),
   1378		.dev = __cpu_to_le32(port->dev_id),
   1379	};
   1380
   1381	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_UNBIND,
   1382			    &req.cmd, sizeof(req));
   1383}
   1384
   1385int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id)
   1386{
   1387	struct prestera_msg_span_req req = {
   1388		.id = span_id
   1389	};
   1390
   1391	return prestera_cmd(sw, PRESTERA_CMD_TYPE_SPAN_RELEASE,
   1392			    &req.cmd, sizeof(req));
   1393}
   1394
   1395int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
   1396{
   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),
   1401	};
   1402	struct prestera_msg_port_attr_resp resp;
   1403	int err;
   1404
   1405	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
   1406			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   1407	if (err)
   1408		return err;
   1409
   1410	*type = resp.param.type;
   1411
   1412	return 0;
   1413}
   1414
   1415int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed)
   1416{
   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),
   1421	};
   1422	struct prestera_msg_port_attr_resp resp;
   1423	int err;
   1424
   1425	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
   1426			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   1427	if (err)
   1428		return err;
   1429
   1430	*speed = __le32_to_cpu(resp.param.speed);
   1431
   1432	return 0;
   1433}
   1434
   1435int prestera_hw_port_autoneg_restart(struct prestera_port *port)
   1436{
   1437	struct prestera_msg_port_attr_req req = {
   1438		.attr =
   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),
   1442	};
   1443
   1444	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
   1445			    &req.cmd, sizeof(req));
   1446}
   1447
   1448int prestera_hw_port_stats_get(const struct prestera_port *port,
   1449			       struct prestera_port_stats *st)
   1450{
   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),
   1455	};
   1456	struct prestera_msg_port_stats_resp resp;
   1457	__le64 *hw = resp.stats;
   1458	int err;
   1459
   1460	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
   1461			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   1462	if (err)
   1463		return err;
   1464
   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]);
   1509	st->sent_multiple =
   1510		__le64_to_cpu(hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT]);
   1511	st->sent_deferred =
   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]);
   1515
   1516	return 0;
   1517}
   1518
   1519int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
   1520{
   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),
   1525		.param = {
   1526			.learning = enable,
   1527		}
   1528	};
   1529
   1530	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
   1531			    &req.cmd, sizeof(req));
   1532}
   1533
   1534static int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood)
   1535{
   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),
   1540		.param = {
   1541			.flood_ext = {
   1542				.type = PRESTERA_PORT_FLOOD_TYPE_UC,
   1543				.enable = flood,
   1544			}
   1545		}
   1546	};
   1547
   1548	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
   1549			    &req.cmd, sizeof(req));
   1550}
   1551
   1552static int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood)
   1553{
   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),
   1558		.param = {
   1559			.flood_ext = {
   1560				.type = PRESTERA_PORT_FLOOD_TYPE_MC,
   1561				.enable = flood,
   1562			}
   1563		}
   1564	};
   1565
   1566	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
   1567			    &req.cmd, sizeof(req));
   1568}
   1569
   1570static int prestera_hw_port_flood_set_v2(struct prestera_port *port, bool flood)
   1571{
   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),
   1576		.param = {
   1577			.flood = flood,
   1578		}
   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_flood_set(struct prestera_port *port, unsigned long mask,
   1586			       unsigned long val)
   1587{
   1588	int err;
   1589
   1590	if (port->sw->dev->fw_rev.maj <= 2) {
   1591		if (!(mask & BR_FLOOD))
   1592			return 0;
   1593
   1594		return prestera_hw_port_flood_set_v2(port, val & BR_FLOOD);
   1595	}
   1596
   1597	if (mask & BR_FLOOD) {
   1598		err = prestera_hw_port_uc_flood_set(port, val & BR_FLOOD);
   1599		if (err)
   1600			goto err_uc_flood;
   1601	}
   1602
   1603	if (mask & BR_MCAST_FLOOD) {
   1604		err = prestera_hw_port_mc_flood_set(port, val & BR_MCAST_FLOOD);
   1605		if (err)
   1606			goto err_mc_flood;
   1607	}
   1608
   1609	return 0;
   1610
   1611err_mc_flood:
   1612	prestera_hw_port_mc_flood_set(port, 0);
   1613err_uc_flood:
   1614	if (mask & BR_FLOOD)
   1615		prestera_hw_port_uc_flood_set(port, 0);
   1616
   1617	return err;
   1618}
   1619
   1620int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
   1621{
   1622	struct prestera_msg_vlan_req req = {
   1623		.vid = __cpu_to_le16(vid),
   1624	};
   1625
   1626	return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE,
   1627			    &req.cmd, sizeof(req));
   1628}
   1629
   1630int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid)
   1631{
   1632	struct prestera_msg_vlan_req req = {
   1633		.vid = __cpu_to_le16(vid),
   1634	};
   1635
   1636	return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE,
   1637			    &req.cmd, sizeof(req));
   1638}
   1639
   1640int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid,
   1641			      bool is_member, bool untagged)
   1642{
   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,
   1649	};
   1650
   1651	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET,
   1652			    &req.cmd, sizeof(req));
   1653}
   1654
   1655int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid)
   1656{
   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),
   1661	};
   1662
   1663	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET,
   1664			    &req.cmd, sizeof(req));
   1665}
   1666
   1667int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state)
   1668{
   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),
   1673		.state = state,
   1674	};
   1675
   1676	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET,
   1677			    &req.cmd, sizeof(req));
   1678}
   1679
   1680int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac,
   1681			u16 vid, bool dynamic)
   1682{
   1683	struct prestera_msg_fdb_req req = {
   1684		.dest = {
   1685			.dev = __cpu_to_le32(port->dev_id),
   1686			.port = __cpu_to_le32(port->hw_id),
   1687		},
   1688		.vid = __cpu_to_le16(vid),
   1689		.dynamic = dynamic,
   1690	};
   1691
   1692	ether_addr_copy(req.mac, mac);
   1693
   1694	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD,
   1695			    &req.cmd, sizeof(req));
   1696}
   1697
   1698int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac,
   1699			u16 vid)
   1700{
   1701	struct prestera_msg_fdb_req req = {
   1702		.dest = {
   1703			.dev = __cpu_to_le32(port->dev_id),
   1704			.port = __cpu_to_le32(port->hw_id),
   1705		},
   1706		.vid = __cpu_to_le16(vid),
   1707	};
   1708
   1709	ether_addr_copy(req.mac, mac);
   1710
   1711	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE,
   1712			    &req.cmd, sizeof(req));
   1713}
   1714
   1715int prestera_hw_lag_fdb_add(struct prestera_switch *sw, u16 lag_id,
   1716			    const unsigned char *mac, u16 vid, bool dynamic)
   1717{
   1718	struct prestera_msg_fdb_req req = {
   1719		.dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
   1720		.dest = {
   1721			.lag_id = __cpu_to_le16(lag_id),
   1722		},
   1723		.vid = __cpu_to_le16(vid),
   1724		.dynamic = dynamic,
   1725	};
   1726
   1727	ether_addr_copy(req.mac, mac);
   1728
   1729	return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_ADD,
   1730			    &req.cmd, sizeof(req));
   1731}
   1732
   1733int prestera_hw_lag_fdb_del(struct prestera_switch *sw, u16 lag_id,
   1734			    const unsigned char *mac, u16 vid)
   1735{
   1736	struct prestera_msg_fdb_req req = {
   1737		.dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
   1738		.dest = {
   1739			.lag_id = __cpu_to_le16(lag_id),
   1740		},
   1741		.vid = __cpu_to_le16(vid),
   1742	};
   1743
   1744	ether_addr_copy(req.mac, mac);
   1745
   1746	return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_DELETE,
   1747			    &req.cmd, sizeof(req));
   1748}
   1749
   1750int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode)
   1751{
   1752	struct prestera_msg_fdb_req req = {
   1753		.dest = {
   1754			.dev = __cpu_to_le32(port->dev_id),
   1755			.port = __cpu_to_le32(port->hw_id),
   1756		},
   1757		.flush_mode = __cpu_to_le32(mode),
   1758	};
   1759
   1760	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
   1761			    &req.cmd, sizeof(req));
   1762}
   1763
   1764int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode)
   1765{
   1766	struct prestera_msg_fdb_req req = {
   1767		.vid = __cpu_to_le16(vid),
   1768		.flush_mode = __cpu_to_le32(mode),
   1769	};
   1770
   1771	return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN,
   1772			    &req.cmd, sizeof(req));
   1773}
   1774
   1775int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
   1776				    u32 mode)
   1777{
   1778	struct prestera_msg_fdb_req req = {
   1779		.dest = {
   1780			.dev = __cpu_to_le32(port->dev_id),
   1781			.port = __cpu_to_le32(port->hw_id),
   1782		},
   1783		.vid = __cpu_to_le16(vid),
   1784		.flush_mode = __cpu_to_le32(mode),
   1785	};
   1786
   1787	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
   1788			    &req.cmd, sizeof(req));
   1789}
   1790
   1791int prestera_hw_fdb_flush_lag(struct prestera_switch *sw, u16 lag_id,
   1792			      u32 mode)
   1793{
   1794	struct prestera_msg_fdb_req req = {
   1795		.dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
   1796		.dest = {
   1797			.lag_id = __cpu_to_le16(lag_id),
   1798		},
   1799		.flush_mode = __cpu_to_le32(mode),
   1800	};
   1801
   1802	return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
   1803			    &req.cmd, sizeof(req));
   1804}
   1805
   1806int prestera_hw_fdb_flush_lag_vlan(struct prestera_switch *sw,
   1807				   u16 lag_id, u16 vid, u32 mode)
   1808{
   1809	struct prestera_msg_fdb_req req = {
   1810		.dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
   1811		.dest = {
   1812			.lag_id = __cpu_to_le16(lag_id),
   1813		},
   1814		.vid = __cpu_to_le16(vid),
   1815		.flush_mode = __cpu_to_le32(mode),
   1816	};
   1817
   1818	return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
   1819			    &req.cmd, sizeof(req));
   1820}
   1821
   1822int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id)
   1823{
   1824	struct prestera_msg_bridge_resp resp;
   1825	struct prestera_msg_bridge_req req;
   1826	int err;
   1827
   1828	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE,
   1829			       &req.cmd, sizeof(req),
   1830			       &resp.ret, sizeof(resp));
   1831	if (err)
   1832		return err;
   1833
   1834	*bridge_id = __le16_to_cpu(resp.bridge);
   1835
   1836	return 0;
   1837}
   1838
   1839int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id)
   1840{
   1841	struct prestera_msg_bridge_req req = {
   1842		.bridge = __cpu_to_le16(bridge_id),
   1843	};
   1844
   1845	return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE,
   1846			    &req.cmd, sizeof(req));
   1847}
   1848
   1849int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id)
   1850{
   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),
   1855	};
   1856
   1857	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD,
   1858			    &req.cmd, sizeof(req));
   1859}
   1860
   1861int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)
   1862{
   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),
   1867	};
   1868
   1869	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE,
   1870			    &req.cmd, sizeof(req));
   1871}
   1872
   1873static int prestera_iface_to_msg(struct prestera_iface *iface,
   1874				 struct prestera_msg_iface *msg_if)
   1875{
   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);
   1881		break;
   1882	case PRESTERA_IF_LAG_E:
   1883		msg_if->lag_id = __cpu_to_le16(iface->lag_id);
   1884		break;
   1885	default:
   1886		return -EOPNOTSUPP;
   1887	}
   1888
   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;
   1892	return 0;
   1893}
   1894
   1895int prestera_hw_rif_create(struct prestera_switch *sw,
   1896			   struct prestera_iface *iif, u8 *mac, u16 *rif_id)
   1897{
   1898	struct prestera_msg_rif_resp resp;
   1899	struct prestera_msg_rif_req req;
   1900	int err;
   1901
   1902	memcpy(req.mac, mac, ETH_ALEN);
   1903
   1904	err = prestera_iface_to_msg(iif, &req.iif);
   1905	if (err)
   1906		return err;
   1907
   1908	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_CREATE,
   1909			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   1910	if (err)
   1911		return err;
   1912
   1913	*rif_id = __le16_to_cpu(resp.rif_id);
   1914	return err;
   1915}
   1916
   1917int prestera_hw_rif_delete(struct prestera_switch *sw, u16 rif_id,
   1918			   struct prestera_iface *iif)
   1919{
   1920	struct prestera_msg_rif_req req = {
   1921		.rif_id = __cpu_to_le16(rif_id),
   1922	};
   1923	int err;
   1924
   1925	err = prestera_iface_to_msg(iif, &req.iif);
   1926	if (err)
   1927		return err;
   1928
   1929	return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE, &req.cmd,
   1930			    sizeof(req));
   1931}
   1932
   1933int prestera_hw_vr_create(struct prestera_switch *sw, u16 *vr_id)
   1934{
   1935	struct prestera_msg_vr_resp resp;
   1936	struct prestera_msg_vr_req req;
   1937	int err;
   1938
   1939	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_VR_CREATE,
   1940			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   1941	if (err)
   1942		return err;
   1943
   1944	*vr_id = __le16_to_cpu(resp.vr_id);
   1945	return err;
   1946}
   1947
   1948int prestera_hw_vr_delete(struct prestera_switch *sw, u16 vr_id)
   1949{
   1950	struct prestera_msg_vr_req req = {
   1951		.vr_id = __cpu_to_le16(vr_id),
   1952	};
   1953
   1954	return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_VR_DELETE, &req.cmd,
   1955			    sizeof(req));
   1956}
   1957
   1958int prestera_hw_lpm_add(struct prestera_switch *sw, u16 vr_id,
   1959			__be32 dst, u32 dst_len, u32 grp_id)
   1960{
   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),
   1965		.dst.u.ipv4 = dst
   1966	};
   1967
   1968	return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_ADD, &req.cmd,
   1969			    sizeof(req));
   1970}
   1971
   1972int prestera_hw_lpm_del(struct prestera_switch *sw, u16 vr_id,
   1973			__be32 dst, u32 dst_len)
   1974{
   1975	struct prestera_msg_lpm_req req = {
   1976		.dst_len = __cpu_to_le32(dst_len),
   1977		.vr_id = __cpu_to_le16(vr_id),
   1978		.dst.u.ipv4 = dst
   1979	};
   1980
   1981	return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_DELETE, &req.cmd,
   1982			    sizeof(req));
   1983}
   1984
   1985int prestera_hw_rxtx_init(struct prestera_switch *sw,
   1986			  struct prestera_rxtx_params *params)
   1987{
   1988	struct prestera_msg_rxtx_resp resp;
   1989	struct prestera_msg_rxtx_req req;
   1990	int err;
   1991
   1992	req.use_sdma = params->use_sdma;
   1993
   1994	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT,
   1995			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   1996	if (err)
   1997		return err;
   1998
   1999	params->map_addr = __le32_to_cpu(resp.map_addr);
   2000
   2001	return 0;
   2002}
   2003
   2004int prestera_hw_lag_member_add(struct prestera_port *port, u16 lag_id)
   2005{
   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),
   2010	};
   2011
   2012	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_ADD,
   2013			    &req.cmd, sizeof(req));
   2014}
   2015
   2016int prestera_hw_lag_member_del(struct prestera_port *port, u16 lag_id)
   2017{
   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),
   2022	};
   2023
   2024	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE,
   2025			    &req.cmd, sizeof(req));
   2026}
   2027
   2028int prestera_hw_lag_member_enable(struct prestera_port *port, u16 lag_id,
   2029				  bool enable)
   2030{
   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),
   2035	};
   2036	u32 cmd;
   2037
   2038	cmd = enable ? PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE :
   2039			PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE;
   2040
   2041	return prestera_cmd(port->sw, cmd, &req.cmd, sizeof(req));
   2042}
   2043
   2044int
   2045prestera_hw_cpu_code_counters_get(struct prestera_switch *sw, u8 code,
   2046				  enum prestera_hw_cpu_code_cnt_t counter_type,
   2047				  u64 *packet_count)
   2048{
   2049	struct prestera_msg_cpu_code_counter_req req = {
   2050		.counter_type = counter_type,
   2051		.code = code,
   2052	};
   2053	struct mvsw_msg_cpu_code_counter_ret resp;
   2054	int err;
   2055
   2056	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET,
   2057			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   2058	if (err)
   2059		return err;
   2060
   2061	*packet_count = __le64_to_cpu(resp.packet_count);
   2062
   2063	return 0;
   2064}
   2065
   2066int prestera_hw_event_handler_register(struct prestera_switch *sw,
   2067				       enum prestera_event_type type,
   2068				       prestera_event_cb_t fn,
   2069				       void *arg)
   2070{
   2071	struct prestera_fw_event_handler *eh;
   2072
   2073	eh = __find_event_handler(sw, type);
   2074	if (eh)
   2075		return -EEXIST;
   2076
   2077	eh = kmalloc(sizeof(*eh), GFP_KERNEL);
   2078	if (!eh)
   2079		return -ENOMEM;
   2080
   2081	eh->type = type;
   2082	eh->func = fn;
   2083	eh->arg = arg;
   2084
   2085	INIT_LIST_HEAD(&eh->list);
   2086
   2087	list_add_rcu(&eh->list, &sw->event_handlers);
   2088
   2089	return 0;
   2090}
   2091
   2092void prestera_hw_event_handler_unregister(struct prestera_switch *sw,
   2093					  enum prestera_event_type type,
   2094					  prestera_event_cb_t fn)
   2095{
   2096	struct prestera_fw_event_handler *eh;
   2097
   2098	eh = __find_event_handler(sw, type);
   2099	if (!eh)
   2100		return;
   2101
   2102	list_del_rcu(&eh->list);
   2103	kfree_rcu(eh, rcu);
   2104}
   2105
   2106int prestera_hw_counter_trigger(struct prestera_switch *sw, u32 block_id)
   2107{
   2108	struct prestera_msg_counter_req req = {
   2109		.block_id = __cpu_to_le32(block_id)
   2110	};
   2111
   2112	return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_TRIGGER,
   2113			    &req.cmd, sizeof(req));
   2114}
   2115
   2116int prestera_hw_counter_abort(struct prestera_switch *sw)
   2117{
   2118	struct prestera_msg_counter_req req;
   2119
   2120	return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_ABORT,
   2121			    &req.cmd, sizeof(req));
   2122}
   2123
   2124int prestera_hw_counters_get(struct prestera_switch *sw, u32 idx,
   2125			     u32 *len, bool *done,
   2126			     struct prestera_counter_stats *stats)
   2127{
   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),
   2132	};
   2133	size_t size = struct_size(resp, stats, *len);
   2134	int err, i;
   2135
   2136	resp = kmalloc(size, GFP_KERNEL);
   2137	if (!resp)
   2138		return -ENOMEM;
   2139
   2140	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_GET,
   2141			       &req.cmd, sizeof(req), &resp->ret, size);
   2142	if (err)
   2143		goto free_buff;
   2144
   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);
   2148	}
   2149
   2150	*len = __le32_to_cpu(resp->num_counters);
   2151	*done = __le32_to_cpu(resp->done);
   2152
   2153free_buff:
   2154	kfree(resp);
   2155	return err;
   2156}
   2157
   2158int prestera_hw_counter_block_get(struct prestera_switch *sw,
   2159				  u32 client, u32 *block_id, u32 *offset,
   2160				  u32 *num_counters)
   2161{
   2162	struct prestera_msg_counter_resp resp;
   2163	struct prestera_msg_counter_req req = {
   2164		.client = __cpu_to_le32(client)
   2165	};
   2166	int err;
   2167
   2168	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_GET,
   2169			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   2170	if (err)
   2171		return err;
   2172
   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);
   2176
   2177	return 0;
   2178}
   2179
   2180int prestera_hw_counter_block_release(struct prestera_switch *sw,
   2181				      u32 block_id)
   2182{
   2183	struct prestera_msg_counter_req req = {
   2184		.block_id = __cpu_to_le32(block_id)
   2185	};
   2186
   2187	return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_RELEASE,
   2188			    &req.cmd, sizeof(req));
   2189}
   2190
   2191int prestera_hw_counter_clear(struct prestera_switch *sw, u32 block_id,
   2192			      u32 counter_id)
   2193{
   2194	struct prestera_msg_counter_req req = {
   2195		.block_id = __cpu_to_le32(block_id),
   2196		.num_counters = __cpu_to_le32(counter_id)
   2197	};
   2198
   2199	return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_CLEAR,
   2200			    &req.cmd, sizeof(req));
   2201}
   2202
   2203int prestera_hw_policer_create(struct prestera_switch *sw, u8 type,
   2204			       u32 *policer_id)
   2205{
   2206	struct prestera_msg_policer_resp resp;
   2207	struct prestera_msg_policer_req req = {
   2208		.type = type
   2209	};
   2210	int err;
   2211
   2212	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_POLICER_CREATE,
   2213			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
   2214	if (err)
   2215		return err;
   2216
   2217	*policer_id = __le32_to_cpu(resp.id);
   2218	return 0;
   2219}
   2220
   2221int prestera_hw_policer_release(struct prestera_switch *sw,
   2222				u32 policer_id)
   2223{
   2224	struct prestera_msg_policer_req req = {
   2225		.id = __cpu_to_le32(policer_id)
   2226	};
   2227
   2228	return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_RELEASE,
   2229			    &req.cmd, sizeof(req));
   2230}
   2231
   2232int prestera_hw_policer_sr_tcm_set(struct prestera_switch *sw,
   2233				   u32 policer_id, u64 cir, u32 cbs)
   2234{
   2235	struct prestera_msg_policer_req req = {
   2236		.mode = PRESTERA_POLICER_MODE_SR_TCM,
   2237		.id = __cpu_to_le32(policer_id),
   2238		.sr_tcm = {
   2239			.cir = __cpu_to_le64(cir),
   2240			.cbs = __cpu_to_le32(cbs)
   2241		}
   2242	};
   2243
   2244	return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_SET,
   2245			    &req.cmd, sizeof(req));
   2246}