File Index
Files and directories
Sign in
FILE

prestera_hw.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/marvell/prestera/prestera_hw.c C
   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#include "prestera_router_hw.h"
  14
  15#define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
  16
  17#define PRESTERA_MIN_MTU 64
  18
  19#define PRESTERA_MSG_CHUNK_SIZE 1024
  20
  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_MAX
 102};
 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_MAX
 132};
 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_MAX
 179};
 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_TCM
 190};
 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	else
 943		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 = fec
1153				}
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	else
1322		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 int
1344prestera_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	else
1500		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	else
1517		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_id
1526	};
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 = dst
2069	};
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 = dst
2082	};
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
2226int
2227prestera_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 = type
2391	};
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}
~/ Read-only file preview.