linux/drivers/net/ethernet/marvell/prestera/prestera_hw.c
<<
>>
Prefs
   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_VR_CREATE = 0x630,
  59        PRESTERA_CMD_TYPE_ROUTER_VR_DELETE = 0x631,
  60
  61        PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
  62
  63        PRESTERA_CMD_TYPE_LAG_MEMBER_ADD = 0x900,
  64        PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE = 0x901,
  65        PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE = 0x902,
  66        PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE = 0x903,
  67
  68        PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
  69
  70        PRESTERA_CMD_TYPE_SPAN_GET = 0x1100,
  71        PRESTERA_CMD_TYPE_SPAN_BIND = 0x1101,
  72        PRESTERA_CMD_TYPE_SPAN_UNBIND = 0x1102,
  73        PRESTERA_CMD_TYPE_SPAN_RELEASE = 0x1103,
  74
  75        PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET = 0x2000,
  76
  77        PRESTERA_CMD_TYPE_ACK = 0x10000,
  78        PRESTERA_CMD_TYPE_MAX
  79};
  80
  81enum {
  82        PRESTERA_CMD_PORT_ATTR_ADMIN_STATE = 1,
  83        PRESTERA_CMD_PORT_ATTR_MTU = 3,
  84        PRESTERA_CMD_PORT_ATTR_MAC = 4,
  85        PRESTERA_CMD_PORT_ATTR_SPEED = 5,
  86        PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6,
  87        PRESTERA_CMD_PORT_ATTR_LEARNING = 7,
  88        PRESTERA_CMD_PORT_ATTR_FLOOD = 8,
  89        PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9,
  90        PRESTERA_CMD_PORT_ATTR_PHY_MODE = 12,
  91        PRESTERA_CMD_PORT_ATTR_TYPE = 13,
  92        PRESTERA_CMD_PORT_ATTR_STATS = 17,
  93        PRESTERA_CMD_PORT_ATTR_MAC_AUTONEG_RESTART = 18,
  94        PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART = 19,
  95        PRESTERA_CMD_PORT_ATTR_MAC_MODE = 22,
  96};
  97
  98enum {
  99        PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
 100        PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
 101};
 102
 103enum {
 104        PRESTERA_CMD_ACK_OK,
 105        PRESTERA_CMD_ACK_FAILED,
 106
 107        PRESTERA_CMD_ACK_MAX
 108};
 109
 110enum {
 111        PRESTERA_PORT_TP_NA,
 112        PRESTERA_PORT_TP_MDI,
 113        PRESTERA_PORT_TP_MDIX,
 114        PRESTERA_PORT_TP_AUTO,
 115};
 116
 117enum {
 118        PRESTERA_PORT_FLOOD_TYPE_UC = 0,
 119        PRESTERA_PORT_FLOOD_TYPE_MC = 1,
 120};
 121
 122enum {
 123        PRESTERA_PORT_GOOD_OCTETS_RCV_CNT,
 124        PRESTERA_PORT_BAD_OCTETS_RCV_CNT,
 125        PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT,
 126        PRESTERA_PORT_BRDC_PKTS_RCV_CNT,
 127        PRESTERA_PORT_MC_PKTS_RCV_CNT,
 128        PRESTERA_PORT_PKTS_64L_CNT,
 129        PRESTERA_PORT_PKTS_65TO127L_CNT,
 130        PRESTERA_PORT_PKTS_128TO255L_CNT,
 131        PRESTERA_PORT_PKTS_256TO511L_CNT,
 132        PRESTERA_PORT_PKTS_512TO1023L_CNT,
 133        PRESTERA_PORT_PKTS_1024TOMAXL_CNT,
 134        PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT,
 135        PRESTERA_PORT_MC_PKTS_SENT_CNT,
 136        PRESTERA_PORT_BRDC_PKTS_SENT_CNT,
 137        PRESTERA_PORT_FC_SENT_CNT,
 138        PRESTERA_PORT_GOOD_FC_RCV_CNT,
 139        PRESTERA_PORT_DROP_EVENTS_CNT,
 140        PRESTERA_PORT_UNDERSIZE_PKTS_CNT,
 141        PRESTERA_PORT_FRAGMENTS_PKTS_CNT,
 142        PRESTERA_PORT_OVERSIZE_PKTS_CNT,
 143        PRESTERA_PORT_JABBER_PKTS_CNT,
 144        PRESTERA_PORT_MAC_RCV_ERROR_CNT,
 145        PRESTERA_PORT_BAD_CRC_CNT,
 146        PRESTERA_PORT_COLLISIONS_CNT,
 147        PRESTERA_PORT_LATE_COLLISIONS_CNT,
 148        PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT,
 149        PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT,
 150        PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT,
 151        PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT,
 152        PRESTERA_PORT_GOOD_OCTETS_SENT_CNT,
 153
 154        PRESTERA_PORT_CNT_MAX
 155};
 156
 157enum {
 158        PRESTERA_FC_NONE,
 159        PRESTERA_FC_SYMMETRIC,
 160        PRESTERA_FC_ASYMMETRIC,
 161        PRESTERA_FC_SYMM_ASYMM,
 162};
 163
 164enum {
 165        PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT = 0,
 166        PRESTERA_HW_FDB_ENTRY_TYPE_LAG = 1,
 167        PRESTERA_HW_FDB_ENTRY_TYPE_MAX = 2,
 168};
 169
 170struct prestera_fw_event_handler {
 171        struct list_head list;
 172        struct rcu_head rcu;
 173        enum prestera_event_type type;
 174        prestera_event_cb_t func;
 175        void *arg;
 176};
 177
 178struct prestera_msg_cmd {
 179        __le32 type;
 180};
 181
 182struct prestera_msg_ret {
 183        struct prestera_msg_cmd cmd;
 184        __le32 status;
 185};
 186
 187struct prestera_msg_common_req {
 188        struct prestera_msg_cmd cmd;
 189};
 190
 191struct prestera_msg_common_resp {
 192        struct prestera_msg_ret ret;
 193};
 194
 195struct prestera_msg_switch_attr_req {
 196        struct prestera_msg_cmd cmd;
 197        __le32 attr;
 198        union {
 199                __le32 ageing_timeout_ms;
 200                struct {
 201                        u8 mac[ETH_ALEN];
 202                        u8 __pad[2];
 203                };
 204        } param;
 205};
 206
 207struct prestera_msg_switch_init_resp {
 208        struct prestera_msg_ret ret;
 209        __le32 port_count;
 210        __le32 mtu_max;
 211        __le32 size_tbl_router_nexthop;
 212        u8 switch_id;
 213        u8 lag_max;
 214        u8 lag_member_max;
 215};
 216
 217struct prestera_msg_event_port_param {
 218        union {
 219                struct {
 220                        __le32 mode;
 221                        __le32 speed;
 222                        u8 oper;
 223                        u8 duplex;
 224                        u8 fc;
 225                        u8 fec;
 226                } mac;
 227                struct {
 228                        __le64 lmode_bmap;
 229                        u8 mdix;
 230                        u8 fc;
 231                        u8 __pad[2];
 232                } __packed phy; /* make sure always 12 bytes size */
 233        };
 234};
 235
 236struct prestera_msg_port_cap_param {
 237        __le64 link_mode;
 238        u8 type;
 239        u8 fec;
 240        u8 fc;
 241        u8 transceiver;
 242};
 243
 244struct prestera_msg_port_flood_param {
 245        u8 type;
 246        u8 enable;
 247        u8 __pad[2];
 248};
 249
 250union prestera_msg_port_param {
 251        __le32 mtu;
 252        __le32 speed;
 253        __le32 link_mode;
 254        u8 admin_state;
 255        u8 oper_state;
 256        u8 mac[ETH_ALEN];
 257        u8 accept_frm_type;
 258        u8 learning;
 259        u8 flood;
 260        u8 type;
 261        u8 duplex;
 262        u8 fec;
 263        u8 fc;
 264        union {
 265                struct {
 266                        u8 admin;
 267                        u8 fc;
 268                        u8 ap_enable;
 269                        u8 __reserved[5];
 270                        union {
 271                                struct {
 272                                        __le32 mode;
 273                                        __le32 speed;
 274                                        u8 inband;
 275                                        u8 duplex;
 276                                        u8 fec;
 277                                        u8 fec_supp;
 278                                } reg_mode;
 279                                struct {
 280                                        __le32 mode;
 281                                        __le32 speed;
 282                                        u8 fec;
 283                                        u8 fec_supp;
 284                                        u8 __pad[2];
 285                                } ap_modes[PRESTERA_AP_PORT_MAX];
 286                        };
 287                } mac;
 288                struct {
 289                        __le64 modes;
 290                        __le32 mode;
 291                        u8 admin;
 292                        u8 adv_enable;
 293                        u8 mdix;
 294                        u8 __pad;
 295                } phy;
 296        } link;
 297
 298        struct prestera_msg_port_cap_param cap;
 299        struct prestera_msg_port_flood_param flood_ext;
 300        struct prestera_msg_event_port_param link_evt;
 301};
 302
 303struct prestera_msg_port_attr_req {
 304        struct prestera_msg_cmd cmd;
 305        __le32 attr;
 306        __le32 port;
 307        __le32 dev;
 308        union prestera_msg_port_param param;
 309};
 310
 311struct prestera_msg_port_attr_resp {
 312        struct prestera_msg_ret ret;
 313        union prestera_msg_port_param param;
 314};
 315
 316struct prestera_msg_port_stats_resp {
 317        struct prestera_msg_ret ret;
 318        __le64 stats[PRESTERA_PORT_CNT_MAX];
 319};
 320
 321struct prestera_msg_port_info_req {
 322        struct prestera_msg_cmd cmd;
 323        __le32 port;
 324};
 325
 326struct prestera_msg_port_info_resp {
 327        struct prestera_msg_ret ret;
 328        __le32 hw_id;
 329        __le32 dev_id;
 330        __le16 fp_id;
 331        u8 pad[2];
 332};
 333
 334struct prestera_msg_vlan_req {
 335        struct prestera_msg_cmd cmd;
 336        __le32 port;
 337        __le32 dev;
 338        __le16 vid;
 339        u8 is_member;
 340        u8 is_tagged;
 341};
 342
 343struct prestera_msg_fdb_req {
 344        struct prestera_msg_cmd cmd;
 345        __le32 flush_mode;
 346        union {
 347                struct {
 348                        __le32 port;
 349                        __le32 dev;
 350                };
 351                __le16 lag_id;
 352        } dest;
 353        __le16 vid;
 354        u8 dest_type;
 355        u8 dynamic;
 356        u8 mac[ETH_ALEN];
 357        u8 __pad[2];
 358};
 359
 360struct prestera_msg_bridge_req {
 361        struct prestera_msg_cmd cmd;
 362        __le32 port;
 363        __le32 dev;
 364        __le16 bridge;
 365        u8 pad[2];
 366};
 367
 368struct prestera_msg_bridge_resp {
 369        struct prestera_msg_ret ret;
 370        __le16 bridge;
 371        u8 pad[2];
 372};
 373
 374struct prestera_msg_vtcam_create_req {
 375        struct prestera_msg_cmd cmd;
 376        __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
 377        u8 direction;
 378        u8 lookup;
 379        u8 pad[2];
 380};
 381
 382struct prestera_msg_vtcam_destroy_req {
 383        struct prestera_msg_cmd cmd;
 384        __le32 vtcam_id;
 385};
 386
 387struct prestera_msg_vtcam_rule_add_req {
 388        struct prestera_msg_cmd cmd;
 389        __le32 key[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
 390        __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
 391        __le32 vtcam_id;
 392        __le32 prio;
 393        __le32 n_act;
 394};
 395
 396struct prestera_msg_vtcam_rule_del_req {
 397        struct prestera_msg_cmd cmd;
 398        __le32 vtcam_id;
 399        __le32 id;
 400};
 401
 402struct prestera_msg_vtcam_bind_req {
 403        struct prestera_msg_cmd cmd;
 404        union {
 405                struct {
 406                        __le32 hw_id;
 407                        __le32 dev_id;
 408                } port;
 409                __le32 index;
 410        };
 411        __le32 vtcam_id;
 412        __le16 pcl_id;
 413        __le16 type;
 414};
 415
 416struct prestera_msg_vtcam_resp {
 417        struct prestera_msg_ret ret;
 418        __le32 vtcam_id;
 419        __le32 rule_id;
 420};
 421
 422struct prestera_msg_acl_action {
 423        __le32 id;
 424        __le32 __reserved;
 425        union {
 426                struct {
 427                        __le32 id;
 428                } count;
 429                __le32 reserved[6];
 430        };
 431};
 432
 433struct prestera_msg_counter_req {
 434        struct prestera_msg_cmd cmd;
 435        __le32 client;
 436        __le32 block_id;
 437        __le32 num_counters;
 438};
 439
 440struct prestera_msg_counter_stats {
 441        __le64 packets;
 442        __le64 bytes;
 443};
 444
 445struct prestera_msg_counter_resp {
 446        struct prestera_msg_ret ret;
 447        __le32 block_id;
 448        __le32 offset;
 449        __le32 num_counters;
 450        __le32 done;
 451        struct prestera_msg_counter_stats stats[];
 452};
 453
 454struct prestera_msg_span_req {
 455        struct prestera_msg_cmd cmd;
 456        __le32 port;
 457        __le32 dev;
 458        u8 id;
 459        u8 pad[3];
 460};
 461
 462struct prestera_msg_span_resp {
 463        struct prestera_msg_ret ret;
 464        u8 id;
 465        u8 pad[3];
 466};
 467
 468struct prestera_msg_stp_req {
 469        struct prestera_msg_cmd cmd;
 470        __le32 port;
 471        __le32 dev;
 472        __le16 vid;
 473        u8 state;
 474        u8 __pad;
 475};
 476
 477struct prestera_msg_rxtx_req {
 478        struct prestera_msg_cmd cmd;
 479        u8 use_sdma;
 480        u8 pad[3];
 481};
 482
 483struct prestera_msg_rxtx_resp {
 484        struct prestera_msg_ret ret;
 485        __le32 map_addr;
 486};
 487
 488struct prestera_msg_iface {
 489        union {
 490                struct {
 491                        __le32 dev;
 492                        __le32 port;
 493                };
 494                __le16 lag_id;
 495        };
 496        __le16 vr_id;
 497        __le16 vid;
 498        u8 type;
 499        u8 __pad[3];
 500};
 501
 502struct prestera_msg_rif_req {
 503        struct prestera_msg_cmd cmd;
 504        struct prestera_msg_iface iif;
 505        __le32 mtu;
 506        __le16 rif_id;
 507        __le16 __reserved;
 508        u8 mac[ETH_ALEN];
 509        u8 __pad[2];
 510};
 511
 512struct prestera_msg_rif_resp {
 513        struct prestera_msg_ret ret;
 514        __le16 rif_id;
 515        u8 __pad[2];
 516};
 517
 518struct prestera_msg_vr_req {
 519        struct prestera_msg_cmd cmd;
 520        __le16 vr_id;
 521        u8 __pad[2];
 522};
 523
 524struct prestera_msg_vr_resp {
 525        struct prestera_msg_ret ret;
 526        __le16 vr_id;
 527        u8 __pad[2];
 528};
 529
 530struct prestera_msg_lag_req {
 531        struct prestera_msg_cmd cmd;
 532        __le32 port;
 533        __le32 dev;
 534        __le16 lag_id;
 535        u8 pad[2];
 536};
 537
 538struct prestera_msg_cpu_code_counter_req {
 539        struct prestera_msg_cmd cmd;
 540        u8 counter_type;
 541        u8 code;
 542        u8 pad[2];
 543};
 544
 545struct mvsw_msg_cpu_code_counter_ret {
 546        struct prestera_msg_ret ret;
 547        __le64 packet_count;
 548};
 549
 550struct prestera_msg_event {
 551        __le16 type;
 552        __le16 id;
 553};
 554
 555struct prestera_msg_event_port {
 556        struct prestera_msg_event id;
 557        __le32 port_id;
 558        struct prestera_msg_event_port_param param;
 559};
 560
 561union prestera_msg_event_fdb_param {
 562        u8 mac[ETH_ALEN];
 563};
 564
 565struct prestera_msg_event_fdb {
 566        struct prestera_msg_event id;
 567        __le32 vid;
 568        union {
 569                __le32 port_id;
 570                __le16 lag_id;
 571        } dest;
 572        union prestera_msg_event_fdb_param param;
 573        u8 dest_type;
 574};
 575
 576static void prestera_hw_build_tests(void)
 577{
 578        /* check requests */
 579        BUILD_BUG_ON(sizeof(struct prestera_msg_common_req) != 4);
 580        BUILD_BUG_ON(sizeof(struct prestera_msg_switch_attr_req) != 16);
 581        BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_req) != 144);
 582        BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_req) != 8);
 583        BUILD_BUG_ON(sizeof(struct prestera_msg_vlan_req) != 16);
 584        BUILD_BUG_ON(sizeof(struct prestera_msg_fdb_req) != 28);
 585        BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_req) != 16);
 586        BUILD_BUG_ON(sizeof(struct prestera_msg_span_req) != 16);
 587        BUILD_BUG_ON(sizeof(struct prestera_msg_stp_req) != 16);
 588        BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_req) != 8);
 589        BUILD_BUG_ON(sizeof(struct prestera_msg_lag_req) != 16);
 590        BUILD_BUG_ON(sizeof(struct prestera_msg_cpu_code_counter_req) != 8);
 591        BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_create_req) != 84);
 592        BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_destroy_req) != 8);
 593        BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_rule_add_req) != 168);
 594        BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_rule_del_req) != 12);
 595        BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_bind_req) != 20);
 596        BUILD_BUG_ON(sizeof(struct prestera_msg_acl_action) != 32);
 597        BUILD_BUG_ON(sizeof(struct prestera_msg_counter_req) != 16);
 598        BUILD_BUG_ON(sizeof(struct prestera_msg_counter_stats) != 16);
 599        BUILD_BUG_ON(sizeof(struct prestera_msg_rif_req) != 36);
 600        BUILD_BUG_ON(sizeof(struct prestera_msg_vr_req) != 8);
 601
 602        /*  structure that are part of req/resp fw messages */
 603        BUILD_BUG_ON(sizeof(struct prestera_msg_iface) != 16);
 604
 605        /* check responses */
 606        BUILD_BUG_ON(sizeof(struct prestera_msg_common_resp) != 8);
 607        BUILD_BUG_ON(sizeof(struct prestera_msg_switch_init_resp) != 24);
 608        BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_resp) != 136);
 609        BUILD_BUG_ON(sizeof(struct prestera_msg_port_stats_resp) != 248);
 610        BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_resp) != 20);
 611        BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_resp) != 12);
 612        BUILD_BUG_ON(sizeof(struct prestera_msg_span_resp) != 12);
 613        BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_resp) != 12);
 614        BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_resp) != 16);
 615        BUILD_BUG_ON(sizeof(struct prestera_msg_counter_resp) != 24);
 616        BUILD_BUG_ON(sizeof(struct prestera_msg_rif_resp) != 12);
 617        BUILD_BUG_ON(sizeof(struct prestera_msg_vr_resp) != 12);
 618
 619        /* check events */
 620        BUILD_BUG_ON(sizeof(struct prestera_msg_event_port) != 20);
 621        BUILD_BUG_ON(sizeof(struct prestera_msg_event_fdb) != 20);
 622}
 623
 624static u8 prestera_hw_mdix_to_eth(u8 mode);
 625static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause);
 626
 627static int __prestera_cmd_ret(struct prestera_switch *sw,
 628                              enum prestera_cmd_type_t type,
 629                              struct prestera_msg_cmd *cmd, size_t clen,
 630                              struct prestera_msg_ret *ret, size_t rlen,
 631                              int waitms)
 632{
 633        struct prestera_device *dev = sw->dev;
 634        int err;
 635
 636        cmd->type = __cpu_to_le32(type);
 637
 638        err = dev->send_req(dev, 0, cmd, clen, ret, rlen, waitms);
 639        if (err)
 640                return err;
 641
 642        if (ret->cmd.type != __cpu_to_le32(PRESTERA_CMD_TYPE_ACK))
 643                return -EBADE;
 644        if (ret->status != __cpu_to_le32(PRESTERA_CMD_ACK_OK))
 645                return -EINVAL;
 646
 647        return 0;
 648}
 649
 650static int prestera_cmd_ret(struct prestera_switch *sw,
 651                            enum prestera_cmd_type_t type,
 652                            struct prestera_msg_cmd *cmd, size_t clen,
 653                            struct prestera_msg_ret *ret, size_t rlen)
 654{
 655        return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0);
 656}
 657
 658static int prestera_cmd_ret_wait(struct prestera_switch *sw,
 659                                 enum prestera_cmd_type_t type,
 660                                 struct prestera_msg_cmd *cmd, size_t clen,
 661                                 struct prestera_msg_ret *ret, size_t rlen,
 662                                 int waitms)
 663{
 664        return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms);
 665}
 666
 667static int prestera_cmd(struct prestera_switch *sw,
 668                        enum prestera_cmd_type_t type,
 669                        struct prestera_msg_cmd *cmd, size_t clen)
 670{
 671        struct prestera_msg_common_resp resp;
 672
 673        return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp));
 674}
 675
 676static int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt)
 677{
 678        struct prestera_msg_event_port *hw_evt;
 679
 680        hw_evt = (struct prestera_msg_event_port *)msg;
 681
 682        evt->port_evt.port_id = __le32_to_cpu(hw_evt->port_id);
 683
 684        if (evt->id == PRESTERA_PORT_EVENT_MAC_STATE_CHANGED) {
 685                evt->port_evt.data.mac.oper = hw_evt->param.mac.oper;
 686                evt->port_evt.data.mac.mode =
 687                        __le32_to_cpu(hw_evt->param.mac.mode);
 688                evt->port_evt.data.mac.speed =
 689                        __le32_to_cpu(hw_evt->param.mac.speed);
 690                evt->port_evt.data.mac.duplex = hw_evt->param.mac.duplex;
 691                evt->port_evt.data.mac.fc = hw_evt->param.mac.fc;
 692                evt->port_evt.data.mac.fec = hw_evt->param.mac.fec;
 693        } else {
 694                return -EINVAL;
 695        }
 696
 697        return 0;
 698}
 699
 700static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt)
 701{
 702        struct prestera_msg_event_fdb *hw_evt = msg;
 703
 704        switch (hw_evt->dest_type) {
 705        case PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT:
 706                evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_REG_PORT;
 707                evt->fdb_evt.dest.port_id = __le32_to_cpu(hw_evt->dest.port_id);
 708                break;
 709        case PRESTERA_HW_FDB_ENTRY_TYPE_LAG:
 710                evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_LAG;
 711                evt->fdb_evt.dest.lag_id = __le16_to_cpu(hw_evt->dest.lag_id);
 712                break;
 713        default:
 714                return -EINVAL;
 715        }
 716
 717        evt->fdb_evt.vid = __le32_to_cpu(hw_evt->vid);
 718
 719        ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac);
 720
 721        return 0;
 722}
 723
 724static struct prestera_fw_evt_parser {
 725        int (*func)(void *msg, struct prestera_event *evt);
 726} fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = {
 727        [PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt },
 728        [PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt },
 729};
 730
 731static struct prestera_fw_event_handler *
 732__find_event_handler(const struct prestera_switch *sw,
 733                     enum prestera_event_type type)
 734{
 735        struct prestera_fw_event_handler *eh;
 736
 737        list_for_each_entry_rcu(eh, &sw->event_handlers, list) {
 738                if (eh->type == type)
 739                        return eh;
 740        }
 741
 742        return NULL;
 743}
 744
 745static int prestera_find_event_handler(const struct prestera_switch *sw,
 746                                       enum prestera_event_type type,
 747                                       struct prestera_fw_event_handler *eh)
 748{
 749        struct prestera_fw_event_handler *tmp;
 750        int err = 0;
 751
 752        rcu_read_lock();
 753        tmp = __find_event_handler(sw, type);
 754        if (tmp)
 755                *eh = *tmp;
 756        else
 757                err = -ENOENT;
 758        rcu_read_unlock();
 759
 760        return err;
 761}
 762
 763static int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size)
 764{
 765        struct prestera_switch *sw = dev->priv;
 766        struct prestera_msg_event *msg = buf;
 767        struct prestera_fw_event_handler eh;
 768        struct prestera_event evt;
 769        u16 msg_type;
 770        int err;
 771
 772        msg_type = __le16_to_cpu(msg->type);
 773        if (msg_type >= PRESTERA_EVENT_TYPE_MAX)
 774                return -EINVAL;
 775        if (!fw_event_parsers[msg_type].func)
 776                return -ENOENT;
 777
 778        err = prestera_find_event_handler(sw, msg_type, &eh);
 779        if (err)
 780                return err;
 781
 782        evt.id = __le16_to_cpu(msg->id);
 783
 784        err = fw_event_parsers[msg_type].func(buf, &evt);
 785        if (err)
 786                return err;
 787
 788        eh.func(sw, &evt, eh.arg);
 789
 790        return 0;
 791}
 792
 793static void prestera_pkt_recv(struct prestera_device *dev)
 794{
 795        struct prestera_switch *sw = dev->priv;
 796        struct prestera_fw_event_handler eh;
 797        struct prestera_event ev;
 798        int err;
 799
 800        ev.id = PRESTERA_RXTX_EVENT_RCV_PKT;
 801
 802        err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh);
 803        if (err)
 804                return;
 805
 806        eh.func(sw, &ev, eh.arg);
 807}
 808
 809static u8 prestera_hw_mdix_to_eth(u8 mode)
 810{
 811        switch (mode) {
 812        case PRESTERA_PORT_TP_MDI:
 813                return ETH_TP_MDI;
 814        case PRESTERA_PORT_TP_MDIX:
 815                return ETH_TP_MDI_X;
 816        case PRESTERA_PORT_TP_AUTO:
 817                return ETH_TP_MDI_AUTO;
 818        default:
 819                return ETH_TP_MDI_INVALID;
 820        }
 821}
 822
 823static u8 prestera_hw_mdix_from_eth(u8 mode)
 824{
 825        switch (mode) {
 826        case ETH_TP_MDI:
 827                return PRESTERA_PORT_TP_MDI;
 828        case ETH_TP_MDI_X:
 829                return PRESTERA_PORT_TP_MDIX;
 830        case ETH_TP_MDI_AUTO:
 831                return PRESTERA_PORT_TP_AUTO;
 832        default:
 833                return PRESTERA_PORT_TP_NA;
 834        }
 835}
 836
 837int prestera_hw_port_info_get(const struct prestera_port *port,
 838                              u32 *dev_id, u32 *hw_id, u16 *fp_id)
 839{
 840        struct prestera_msg_port_info_req req = {
 841                .port = __cpu_to_le32(port->id),
 842        };
 843        struct prestera_msg_port_info_resp resp;
 844        int err;
 845
 846        err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET,
 847                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
 848        if (err)
 849                return err;
 850
 851        *dev_id = __le32_to_cpu(resp.dev_id);
 852        *hw_id = __le32_to_cpu(resp.hw_id);
 853        *fp_id = __le16_to_cpu(resp.fp_id);
 854
 855        return 0;
 856}
 857
 858int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac)
 859{
 860        struct prestera_msg_switch_attr_req req = {
 861                .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_MAC),
 862        };
 863
 864        ether_addr_copy(req.param.mac, mac);
 865
 866        return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
 867                            &req.cmd, sizeof(req));
 868}
 869
 870int prestera_hw_switch_init(struct prestera_switch *sw)
 871{
 872        struct prestera_msg_switch_init_resp resp;
 873        struct prestera_msg_common_req req;
 874        int err;
 875
 876        INIT_LIST_HEAD(&sw->event_handlers);
 877
 878        prestera_hw_build_tests();
 879
 880        err = prestera_cmd_ret_wait(sw, PRESTERA_CMD_TYPE_SWITCH_INIT,
 881                                    &req.cmd, sizeof(req),
 882                                    &resp.ret, sizeof(resp),
 883                                    PRESTERA_SWITCH_INIT_TIMEOUT_MS);
 884        if (err)
 885                return err;
 886
 887        sw->dev->recv_msg = prestera_evt_recv;
 888        sw->dev->recv_pkt = prestera_pkt_recv;
 889        sw->port_count = __le32_to_cpu(resp.port_count);
 890        sw->mtu_min = PRESTERA_MIN_MTU;
 891        sw->mtu_max = __le32_to_cpu(resp.mtu_max);
 892        sw->id = resp.switch_id;
 893        sw->lag_member_max = resp.lag_member_max;
 894        sw->lag_max = resp.lag_max;
 895
 896        return 0;
 897}
 898
 899void prestera_hw_switch_fini(struct prestera_switch *sw)
 900{
 901        WARN_ON(!list_empty(&sw->event_handlers));
 902}
 903
 904int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms)
 905{
 906        struct prestera_msg_switch_attr_req req = {
 907                .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_AGEING),
 908                .param = {
 909                        .ageing_timeout_ms = __cpu_to_le32(ageing_ms),
 910                },
 911        };
 912
 913        return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
 914                            &req.cmd, sizeof(req));
 915}
 916
 917int prestera_hw_port_mac_mode_get(const struct prestera_port *port,
 918                                  u32 *mode, u32 *speed, u8 *duplex, u8 *fec)
 919{
 920        struct prestera_msg_port_attr_resp resp;
 921        struct prestera_msg_port_attr_req req = {
 922                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
 923                .port = __cpu_to_le32(port->hw_id),
 924                .dev = __cpu_to_le32(port->dev_id)
 925        };
 926        int err;
 927
 928        err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
 929                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
 930        if (err)
 931                return err;
 932
 933        if (mode)
 934                *mode = __le32_to_cpu(resp.param.link_evt.mac.mode);
 935
 936        if (speed)
 937                *speed = __le32_to_cpu(resp.param.link_evt.mac.speed);
 938
 939        if (duplex)
 940                *duplex = resp.param.link_evt.mac.duplex;
 941
 942        if (fec)
 943                *fec = resp.param.link_evt.mac.fec;
 944
 945        return err;
 946}
 947
 948int prestera_hw_port_mac_mode_set(const struct prestera_port *port,
 949                                  bool admin, u32 mode, u8 inband,
 950                                  u32 speed, u8 duplex, u8 fec)
 951{
 952        struct prestera_msg_port_attr_req req = {
 953                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
 954                .port = __cpu_to_le32(port->hw_id),
 955                .dev = __cpu_to_le32(port->dev_id),
 956                .param = {
 957                        .link = {
 958                                .mac = {
 959                                        .admin = admin,
 960                                        .reg_mode.mode = __cpu_to_le32(mode),
 961                                        .reg_mode.inband = inband,
 962                                        .reg_mode.speed = __cpu_to_le32(speed),
 963                                        .reg_mode.duplex = duplex,
 964                                        .reg_mode.fec = fec
 965                                }
 966                        }
 967                }
 968        };
 969
 970        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
 971                            &req.cmd, sizeof(req));
 972}
 973
 974int prestera_hw_port_phy_mode_get(const struct prestera_port *port,
 975                                  u8 *mdix, u64 *lmode_bmap,
 976                                  bool *fc_pause, bool *fc_asym)
 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_PHY_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 (mdix)
 992                *mdix = prestera_hw_mdix_to_eth(resp.param.link_evt.phy.mdix);
 993
 994        if (lmode_bmap)
 995                *lmode_bmap = __le64_to_cpu(resp.param.link_evt.phy.lmode_bmap);
 996
 997        if (fc_pause && fc_asym)
 998                prestera_hw_remote_fc_to_eth(resp.param.link_evt.phy.fc,
 999                                             fc_pause, fc_asym);
1000
1001        return err;
1002}
1003
1004int prestera_hw_port_phy_mode_set(const struct prestera_port *port,
1005                                  bool admin, bool adv, u32 mode, u64 modes,
1006                                  u8 mdix)
1007{
1008        struct prestera_msg_port_attr_req req = {
1009                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_MODE),
1010                .port = __cpu_to_le32(port->hw_id),
1011                .dev = __cpu_to_le32(port->dev_id),
1012                .param = {
1013                        .link = {
1014                                .phy = {
1015                                        .admin = admin,
1016                                        .adv_enable = adv ? 1 : 0,
1017                                        .mode = __cpu_to_le32(mode),
1018                                        .modes = __cpu_to_le64(modes),
1019                                }
1020                        }
1021                }
1022        };
1023
1024        req.param.link.phy.mdix = prestera_hw_mdix_from_eth(mdix);
1025
1026        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1027                            &req.cmd, sizeof(req));
1028}
1029
1030int prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu)
1031{
1032        struct prestera_msg_port_attr_req req = {
1033                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MTU),
1034                .port = __cpu_to_le32(port->hw_id),
1035                .dev = __cpu_to_le32(port->dev_id),
1036                .param = {
1037                        .mtu = __cpu_to_le32(mtu),
1038                }
1039        };
1040
1041        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1042                            &req.cmd, sizeof(req));
1043}
1044
1045int prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac)
1046{
1047        struct prestera_msg_port_attr_req req = {
1048                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC),
1049                .port = __cpu_to_le32(port->hw_id),
1050                .dev = __cpu_to_le32(port->dev_id),
1051        };
1052
1053        ether_addr_copy(req.param.mac, mac);
1054
1055        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1056                            &req.cmd, sizeof(req));
1057}
1058
1059int prestera_hw_port_accept_frm_type(struct prestera_port *port,
1060                                     enum prestera_accept_frm_type type)
1061{
1062        struct prestera_msg_port_attr_req req = {
1063                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE),
1064                .port = __cpu_to_le32(port->hw_id),
1065                .dev = __cpu_to_le32(port->dev_id),
1066                .param = {
1067                        .accept_frm_type = type,
1068                }
1069        };
1070
1071        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1072                            &req.cmd, sizeof(req));
1073}
1074
1075int prestera_hw_port_cap_get(const struct prestera_port *port,
1076                             struct prestera_port_caps *caps)
1077{
1078        struct prestera_msg_port_attr_req req = {
1079                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_CAPABILITY),
1080                .port = __cpu_to_le32(port->hw_id),
1081                .dev = __cpu_to_le32(port->dev_id),
1082        };
1083        struct prestera_msg_port_attr_resp resp;
1084        int err;
1085
1086        err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1087                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1088        if (err)
1089                return err;
1090
1091        caps->supp_link_modes = __le64_to_cpu(resp.param.cap.link_mode);
1092        caps->transceiver = resp.param.cap.transceiver;
1093        caps->supp_fec = resp.param.cap.fec;
1094        caps->type = resp.param.cap.type;
1095
1096        return err;
1097}
1098
1099static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause)
1100{
1101        switch (fc) {
1102        case PRESTERA_FC_SYMMETRIC:
1103                *pause = true;
1104                *asym_pause = false;
1105                break;
1106        case PRESTERA_FC_ASYMMETRIC:
1107                *pause = false;
1108                *asym_pause = true;
1109                break;
1110        case PRESTERA_FC_SYMM_ASYMM:
1111                *pause = true;
1112                *asym_pause = true;
1113                break;
1114        default:
1115                *pause = false;
1116                *asym_pause = false;
1117        }
1118}
1119
1120int prestera_hw_vtcam_create(struct prestera_switch *sw,
1121                             u8 lookup, const u32 *keymask, u32 *vtcam_id,
1122                             enum prestera_hw_vtcam_direction_t dir)
1123{
1124        int err;
1125        struct prestera_msg_vtcam_resp resp;
1126        struct prestera_msg_vtcam_create_req req = {
1127                .lookup = lookup,
1128                .direction = dir,
1129        };
1130
1131        if (keymask)
1132                memcpy(req.keymask, keymask, sizeof(req.keymask));
1133        else
1134                memset(req.keymask, 0, sizeof(req.keymask));
1135
1136        err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_CREATE,
1137                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1138        if (err)
1139                return err;
1140
1141        *vtcam_id = __le32_to_cpu(resp.vtcam_id);
1142        return 0;
1143}
1144
1145int prestera_hw_vtcam_destroy(struct prestera_switch *sw, u32 vtcam_id)
1146{
1147        struct prestera_msg_vtcam_destroy_req req = {
1148                .vtcam_id = __cpu_to_le32(vtcam_id),
1149        };
1150
1151        return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_DESTROY,
1152                            &req.cmd, sizeof(req));
1153}
1154
1155static int
1156prestera_acl_rule_add_put_action(struct prestera_msg_acl_action *action,
1157                                 struct prestera_acl_hw_action_info *info)
1158{
1159        action->id = __cpu_to_le32(info->id);
1160
1161        switch (info->id) {
1162        case PRESTERA_ACL_RULE_ACTION_ACCEPT:
1163        case PRESTERA_ACL_RULE_ACTION_DROP:
1164        case PRESTERA_ACL_RULE_ACTION_TRAP:
1165                /* just rule action id, no specific data */
1166                break;
1167        case PRESTERA_ACL_RULE_ACTION_COUNT:
1168                action->count.id = __cpu_to_le32(info->count.id);
1169                break;
1170        default:
1171                return -EINVAL;
1172        }
1173
1174        return 0;
1175}
1176
1177int prestera_hw_vtcam_rule_add(struct prestera_switch *sw,
1178                               u32 vtcam_id, u32 prio, void *key, void *keymask,
1179                               struct prestera_acl_hw_action_info *act,
1180                               u8 n_act, u32 *rule_id)
1181{
1182        struct prestera_msg_acl_action *actions_msg;
1183        struct prestera_msg_vtcam_rule_add_req *req;
1184        struct prestera_msg_vtcam_resp resp;
1185        void *buff;
1186        u32 size;
1187        int err;
1188        u8 i;
1189
1190        size = sizeof(*req) + sizeof(*actions_msg) * n_act;
1191
1192        buff = kzalloc(size, GFP_KERNEL);
1193        if (!buff)
1194                return -ENOMEM;
1195
1196        req = buff;
1197        req->n_act = __cpu_to_le32(n_act);
1198        actions_msg = buff + sizeof(*req);
1199
1200        /* put acl matches into the message */
1201        memcpy(req->key, key, sizeof(req->key));
1202        memcpy(req->keymask, keymask, sizeof(req->keymask));
1203
1204        /* put acl actions into the message */
1205        for (i = 0; i < n_act; i++) {
1206                err = prestera_acl_rule_add_put_action(&actions_msg[i],
1207                                                       &act[i]);
1208                if (err)
1209                        goto free_buff;
1210        }
1211
1212        req->vtcam_id = __cpu_to_le32(vtcam_id);
1213        req->prio = __cpu_to_le32(prio);
1214
1215        err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_ADD,
1216                               &req->cmd, size, &resp.ret, sizeof(resp));
1217        if (err)
1218                goto free_buff;
1219
1220        *rule_id = __le32_to_cpu(resp.rule_id);
1221free_buff:
1222        kfree(buff);
1223        return err;
1224}
1225
1226int prestera_hw_vtcam_rule_del(struct prestera_switch *sw,
1227                               u32 vtcam_id, u32 rule_id)
1228{
1229        struct prestera_msg_vtcam_rule_del_req req = {
1230                .vtcam_id = __cpu_to_le32(vtcam_id),
1231                .id = __cpu_to_le32(rule_id)
1232        };
1233
1234        return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_DELETE,
1235                            &req.cmd, sizeof(req));
1236}
1237
1238int prestera_hw_vtcam_iface_bind(struct prestera_switch *sw,
1239                                 struct prestera_acl_iface *iface,
1240                                 u32 vtcam_id, u16 pcl_id)
1241{
1242        struct prestera_msg_vtcam_bind_req req = {
1243                .vtcam_id = __cpu_to_le32(vtcam_id),
1244                .type = __cpu_to_le16(iface->type),
1245                .pcl_id = __cpu_to_le16(pcl_id)
1246        };
1247
1248        if (iface->type == PRESTERA_ACL_IFACE_TYPE_PORT) {
1249                req.port.dev_id = __cpu_to_le32(iface->port->dev_id);
1250                req.port.hw_id = __cpu_to_le32(iface->port->hw_id);
1251        } else {
1252                req.index = __cpu_to_le32(iface->index);
1253        }
1254
1255        return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_BIND,
1256                            &req.cmd, sizeof(req));
1257}
1258
1259int prestera_hw_vtcam_iface_unbind(struct prestera_switch *sw,
1260                                   struct prestera_acl_iface *iface,
1261                                   u32 vtcam_id)
1262{
1263        struct prestera_msg_vtcam_bind_req req = {
1264                .vtcam_id = __cpu_to_le32(vtcam_id),
1265                .type = __cpu_to_le16(iface->type)
1266        };
1267
1268        if (iface->type == PRESTERA_ACL_IFACE_TYPE_PORT) {
1269                req.port.dev_id = __cpu_to_le32(iface->port->dev_id);
1270                req.port.hw_id = __cpu_to_le32(iface->port->hw_id);
1271        } else {
1272                req.index = __cpu_to_le32(iface->index);
1273        }
1274
1275        return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_UNBIND,
1276                            &req.cmd, sizeof(req));
1277}
1278
1279int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id)
1280{
1281        struct prestera_msg_span_resp resp;
1282        struct prestera_msg_span_req req = {
1283                .port = __cpu_to_le32(port->hw_id),
1284                .dev = __cpu_to_le32(port->dev_id),
1285        };
1286        int err;
1287
1288        err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_SPAN_GET,
1289                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1290        if (err)
1291                return err;
1292
1293        *span_id = resp.id;
1294
1295        return 0;
1296}
1297
1298int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id)
1299{
1300        struct prestera_msg_span_req req = {
1301                .port = __cpu_to_le32(port->hw_id),
1302                .dev = __cpu_to_le32(port->dev_id),
1303                .id = span_id,
1304        };
1305
1306        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_BIND,
1307                            &req.cmd, sizeof(req));
1308}
1309
1310int prestera_hw_span_unbind(const struct prestera_port *port)
1311{
1312        struct prestera_msg_span_req req = {
1313                .port = __cpu_to_le32(port->hw_id),
1314                .dev = __cpu_to_le32(port->dev_id),
1315        };
1316
1317        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_UNBIND,
1318                            &req.cmd, sizeof(req));
1319}
1320
1321int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id)
1322{
1323        struct prestera_msg_span_req req = {
1324                .id = span_id
1325        };
1326
1327        return prestera_cmd(sw, PRESTERA_CMD_TYPE_SPAN_RELEASE,
1328                            &req.cmd, sizeof(req));
1329}
1330
1331int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
1332{
1333        struct prestera_msg_port_attr_req req = {
1334                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_TYPE),
1335                .port = __cpu_to_le32(port->hw_id),
1336                .dev = __cpu_to_le32(port->dev_id),
1337        };
1338        struct prestera_msg_port_attr_resp resp;
1339        int err;
1340
1341        err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1342                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1343        if (err)
1344                return err;
1345
1346        *type = resp.param.type;
1347
1348        return 0;
1349}
1350
1351int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed)
1352{
1353        struct prestera_msg_port_attr_req req = {
1354                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_SPEED),
1355                .port = __cpu_to_le32(port->hw_id),
1356                .dev = __cpu_to_le32(port->dev_id),
1357        };
1358        struct prestera_msg_port_attr_resp resp;
1359        int err;
1360
1361        err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1362                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1363        if (err)
1364                return err;
1365
1366        *speed = __le32_to_cpu(resp.param.speed);
1367
1368        return 0;
1369}
1370
1371int prestera_hw_port_autoneg_restart(struct prestera_port *port)
1372{
1373        struct prestera_msg_port_attr_req req = {
1374                .attr =
1375                    __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART),
1376                .port = __cpu_to_le32(port->hw_id),
1377                .dev = __cpu_to_le32(port->dev_id),
1378        };
1379
1380        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1381                            &req.cmd, sizeof(req));
1382}
1383
1384int prestera_hw_port_stats_get(const struct prestera_port *port,
1385                               struct prestera_port_stats *st)
1386{
1387        struct prestera_msg_port_attr_req req = {
1388                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_STATS),
1389                .port = __cpu_to_le32(port->hw_id),
1390                .dev = __cpu_to_le32(port->dev_id),
1391        };
1392        struct prestera_msg_port_stats_resp resp;
1393        __le64 *hw = resp.stats;
1394        int err;
1395
1396        err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1397                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1398        if (err)
1399                return err;
1400
1401        st->good_octets_received =
1402                __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_RCV_CNT]);
1403        st->bad_octets_received =
1404                __le64_to_cpu(hw[PRESTERA_PORT_BAD_OCTETS_RCV_CNT]);
1405        st->mac_trans_error =
1406                __le64_to_cpu(hw[PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT]);
1407        st->broadcast_frames_received =
1408                __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_RCV_CNT]);
1409        st->multicast_frames_received =
1410                __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_RCV_CNT]);
1411        st->frames_64_octets = __le64_to_cpu(hw[PRESTERA_PORT_PKTS_64L_CNT]);
1412        st->frames_65_to_127_octets =
1413                __le64_to_cpu(hw[PRESTERA_PORT_PKTS_65TO127L_CNT]);
1414        st->frames_128_to_255_octets =
1415                __le64_to_cpu(hw[PRESTERA_PORT_PKTS_128TO255L_CNT]);
1416        st->frames_256_to_511_octets =
1417                __le64_to_cpu(hw[PRESTERA_PORT_PKTS_256TO511L_CNT]);
1418        st->frames_512_to_1023_octets =
1419                __le64_to_cpu(hw[PRESTERA_PORT_PKTS_512TO1023L_CNT]);
1420        st->frames_1024_to_max_octets =
1421                __le64_to_cpu(hw[PRESTERA_PORT_PKTS_1024TOMAXL_CNT]);
1422        st->excessive_collision =
1423                __le64_to_cpu(hw[PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT]);
1424        st->multicast_frames_sent =
1425                __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_SENT_CNT]);
1426        st->broadcast_frames_sent =
1427                __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_SENT_CNT]);
1428        st->fc_sent = __le64_to_cpu(hw[PRESTERA_PORT_FC_SENT_CNT]);
1429        st->fc_received = __le64_to_cpu(hw[PRESTERA_PORT_GOOD_FC_RCV_CNT]);
1430        st->buffer_overrun = __le64_to_cpu(hw[PRESTERA_PORT_DROP_EVENTS_CNT]);
1431        st->undersize = __le64_to_cpu(hw[PRESTERA_PORT_UNDERSIZE_PKTS_CNT]);
1432        st->fragments = __le64_to_cpu(hw[PRESTERA_PORT_FRAGMENTS_PKTS_CNT]);
1433        st->oversize = __le64_to_cpu(hw[PRESTERA_PORT_OVERSIZE_PKTS_CNT]);
1434        st->jabber = __le64_to_cpu(hw[PRESTERA_PORT_JABBER_PKTS_CNT]);
1435        st->rx_error_frame_received =
1436                __le64_to_cpu(hw[PRESTERA_PORT_MAC_RCV_ERROR_CNT]);
1437        st->bad_crc = __le64_to_cpu(hw[PRESTERA_PORT_BAD_CRC_CNT]);
1438        st->collisions = __le64_to_cpu(hw[PRESTERA_PORT_COLLISIONS_CNT]);
1439        st->late_collision =
1440                __le64_to_cpu(hw[PRESTERA_PORT_LATE_COLLISIONS_CNT]);
1441        st->unicast_frames_received =
1442                __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT]);
1443        st->unicast_frames_sent =
1444                __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT]);
1445        st->sent_multiple =
1446                __le64_to_cpu(hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT]);
1447        st->sent_deferred =
1448                __le64_to_cpu(hw[PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT]);
1449        st->good_octets_sent =
1450                __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT]);
1451
1452        return 0;
1453}
1454
1455int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
1456{
1457        struct prestera_msg_port_attr_req req = {
1458                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_LEARNING),
1459                .port = __cpu_to_le32(port->hw_id),
1460                .dev = __cpu_to_le32(port->dev_id),
1461                .param = {
1462                        .learning = enable,
1463                }
1464        };
1465
1466        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1467                            &req.cmd, sizeof(req));
1468}
1469
1470static int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood)
1471{
1472        struct prestera_msg_port_attr_req req = {
1473                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1474                .port = __cpu_to_le32(port->hw_id),
1475                .dev = __cpu_to_le32(port->dev_id),
1476                .param = {
1477                        .flood_ext = {
1478                                .type = PRESTERA_PORT_FLOOD_TYPE_UC,
1479                                .enable = flood,
1480                        }
1481                }
1482        };
1483
1484        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1485                            &req.cmd, sizeof(req));
1486}
1487
1488static int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood)
1489{
1490        struct prestera_msg_port_attr_req req = {
1491                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1492                .port = __cpu_to_le32(port->hw_id),
1493                .dev = __cpu_to_le32(port->dev_id),
1494                .param = {
1495                        .flood_ext = {
1496                                .type = PRESTERA_PORT_FLOOD_TYPE_MC,
1497                                .enable = flood,
1498                        }
1499                }
1500        };
1501
1502        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1503                            &req.cmd, sizeof(req));
1504}
1505
1506static int prestera_hw_port_flood_set_v2(struct prestera_port *port, bool flood)
1507{
1508        struct prestera_msg_port_attr_req req = {
1509                .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1510                .port = __cpu_to_le32(port->hw_id),
1511                .dev = __cpu_to_le32(port->dev_id),
1512                .param = {
1513                        .flood = flood,
1514                }
1515        };
1516
1517        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1518                            &req.cmd, sizeof(req));
1519}
1520
1521int prestera_hw_port_flood_set(struct prestera_port *port, unsigned long mask,
1522                               unsigned long val)
1523{
1524        int err;
1525
1526        if (port->sw->dev->fw_rev.maj <= 2) {
1527                if (!(mask & BR_FLOOD))
1528                        return 0;
1529
1530                return prestera_hw_port_flood_set_v2(port, val & BR_FLOOD);
1531        }
1532
1533        if (mask & BR_FLOOD) {
1534                err = prestera_hw_port_uc_flood_set(port, val & BR_FLOOD);
1535                if (err)
1536                        goto err_uc_flood;
1537        }
1538
1539        if (mask & BR_MCAST_FLOOD) {
1540                err = prestera_hw_port_mc_flood_set(port, val & BR_MCAST_FLOOD);
1541                if (err)
1542                        goto err_mc_flood;
1543        }
1544
1545        return 0;
1546
1547err_mc_flood:
1548        prestera_hw_port_mc_flood_set(port, 0);
1549err_uc_flood:
1550        if (mask & BR_FLOOD)
1551                prestera_hw_port_uc_flood_set(port, 0);
1552
1553        return err;
1554}
1555
1556int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
1557{
1558        struct prestera_msg_vlan_req req = {
1559                .vid = __cpu_to_le16(vid),
1560        };
1561
1562        return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE,
1563                            &req.cmd, sizeof(req));
1564}
1565
1566int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid)
1567{
1568        struct prestera_msg_vlan_req req = {
1569                .vid = __cpu_to_le16(vid),
1570        };
1571
1572        return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE,
1573                            &req.cmd, sizeof(req));
1574}
1575
1576int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid,
1577                              bool is_member, bool untagged)
1578{
1579        struct prestera_msg_vlan_req req = {
1580                .port = __cpu_to_le32(port->hw_id),
1581                .dev = __cpu_to_le32(port->dev_id),
1582                .vid = __cpu_to_le16(vid),
1583                .is_member = is_member,
1584                .is_tagged = !untagged,
1585        };
1586
1587        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET,
1588                            &req.cmd, sizeof(req));
1589}
1590
1591int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid)
1592{
1593        struct prestera_msg_vlan_req req = {
1594                .port = __cpu_to_le32(port->hw_id),
1595                .dev = __cpu_to_le32(port->dev_id),
1596                .vid = __cpu_to_le16(vid),
1597        };
1598
1599        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET,
1600                            &req.cmd, sizeof(req));
1601}
1602
1603int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state)
1604{
1605        struct prestera_msg_stp_req req = {
1606                .port = __cpu_to_le32(port->hw_id),
1607                .dev = __cpu_to_le32(port->dev_id),
1608                .vid = __cpu_to_le16(vid),
1609                .state = state,
1610        };
1611
1612        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET,
1613                            &req.cmd, sizeof(req));
1614}
1615
1616int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac,
1617                        u16 vid, bool dynamic)
1618{
1619        struct prestera_msg_fdb_req req = {
1620                .dest = {
1621                        .dev = __cpu_to_le32(port->dev_id),
1622                        .port = __cpu_to_le32(port->hw_id),
1623                },
1624                .vid = __cpu_to_le16(vid),
1625                .dynamic = dynamic,
1626        };
1627
1628        ether_addr_copy(req.mac, mac);
1629
1630        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD,
1631                            &req.cmd, sizeof(req));
1632}
1633
1634int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac,
1635                        u16 vid)
1636{
1637        struct prestera_msg_fdb_req req = {
1638                .dest = {
1639                        .dev = __cpu_to_le32(port->dev_id),
1640                        .port = __cpu_to_le32(port->hw_id),
1641                },
1642                .vid = __cpu_to_le16(vid),
1643        };
1644
1645        ether_addr_copy(req.mac, mac);
1646
1647        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1648                            &req.cmd, sizeof(req));
1649}
1650
1651int prestera_hw_lag_fdb_add(struct prestera_switch *sw, u16 lag_id,
1652                            const unsigned char *mac, u16 vid, bool dynamic)
1653{
1654        struct prestera_msg_fdb_req req = {
1655                .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1656                .dest = {
1657                        .lag_id = __cpu_to_le16(lag_id),
1658                },
1659                .vid = __cpu_to_le16(vid),
1660                .dynamic = dynamic,
1661        };
1662
1663        ether_addr_copy(req.mac, mac);
1664
1665        return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_ADD,
1666                            &req.cmd, sizeof(req));
1667}
1668
1669int prestera_hw_lag_fdb_del(struct prestera_switch *sw, u16 lag_id,
1670                            const unsigned char *mac, u16 vid)
1671{
1672        struct prestera_msg_fdb_req req = {
1673                .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1674                .dest = {
1675                        .lag_id = __cpu_to_le16(lag_id),
1676                },
1677                .vid = __cpu_to_le16(vid),
1678        };
1679
1680        ether_addr_copy(req.mac, mac);
1681
1682        return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1683                            &req.cmd, sizeof(req));
1684}
1685
1686int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode)
1687{
1688        struct prestera_msg_fdb_req req = {
1689                .dest = {
1690                        .dev = __cpu_to_le32(port->dev_id),
1691                        .port = __cpu_to_le32(port->hw_id),
1692                },
1693                .flush_mode = __cpu_to_le32(mode),
1694        };
1695
1696        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1697                            &req.cmd, sizeof(req));
1698}
1699
1700int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode)
1701{
1702        struct prestera_msg_fdb_req req = {
1703                .vid = __cpu_to_le16(vid),
1704                .flush_mode = __cpu_to_le32(mode),
1705        };
1706
1707        return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN,
1708                            &req.cmd, sizeof(req));
1709}
1710
1711int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
1712                                    u32 mode)
1713{
1714        struct prestera_msg_fdb_req req = {
1715                .dest = {
1716                        .dev = __cpu_to_le32(port->dev_id),
1717                        .port = __cpu_to_le32(port->hw_id),
1718                },
1719                .vid = __cpu_to_le16(vid),
1720                .flush_mode = __cpu_to_le32(mode),
1721        };
1722
1723        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1724                            &req.cmd, sizeof(req));
1725}
1726
1727int prestera_hw_fdb_flush_lag(struct prestera_switch *sw, u16 lag_id,
1728                              u32 mode)
1729{
1730        struct prestera_msg_fdb_req req = {
1731                .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1732                .dest = {
1733                        .lag_id = __cpu_to_le16(lag_id),
1734                },
1735                .flush_mode = __cpu_to_le32(mode),
1736        };
1737
1738        return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1739                            &req.cmd, sizeof(req));
1740}
1741
1742int prestera_hw_fdb_flush_lag_vlan(struct prestera_switch *sw,
1743                                   u16 lag_id, u16 vid, u32 mode)
1744{
1745        struct prestera_msg_fdb_req req = {
1746                .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1747                .dest = {
1748                        .lag_id = __cpu_to_le16(lag_id),
1749                },
1750                .vid = __cpu_to_le16(vid),
1751                .flush_mode = __cpu_to_le32(mode),
1752        };
1753
1754        return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1755                            &req.cmd, sizeof(req));
1756}
1757
1758int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id)
1759{
1760        struct prestera_msg_bridge_resp resp;
1761        struct prestera_msg_bridge_req req;
1762        int err;
1763
1764        err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE,
1765                               &req.cmd, sizeof(req),
1766                               &resp.ret, sizeof(resp));
1767        if (err)
1768                return err;
1769
1770        *bridge_id = __le16_to_cpu(resp.bridge);
1771
1772        return 0;
1773}
1774
1775int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id)
1776{
1777        struct prestera_msg_bridge_req req = {
1778                .bridge = __cpu_to_le16(bridge_id),
1779        };
1780
1781        return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE,
1782                            &req.cmd, sizeof(req));
1783}
1784
1785int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id)
1786{
1787        struct prestera_msg_bridge_req req = {
1788                .bridge = __cpu_to_le16(bridge_id),
1789                .port = __cpu_to_le32(port->hw_id),
1790                .dev = __cpu_to_le32(port->dev_id),
1791        };
1792
1793        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD,
1794                            &req.cmd, sizeof(req));
1795}
1796
1797int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)
1798{
1799        struct prestera_msg_bridge_req req = {
1800                .bridge = __cpu_to_le16(bridge_id),
1801                .port = __cpu_to_le32(port->hw_id),
1802                .dev = __cpu_to_le32(port->dev_id),
1803        };
1804
1805        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE,
1806                            &req.cmd, sizeof(req));
1807}
1808
1809static int prestera_iface_to_msg(struct prestera_iface *iface,
1810                                 struct prestera_msg_iface *msg_if)
1811{
1812        switch (iface->type) {
1813        case PRESTERA_IF_PORT_E:
1814        case PRESTERA_IF_VID_E:
1815                msg_if->port = __cpu_to_le32(iface->dev_port.port_num);
1816                msg_if->dev = __cpu_to_le32(iface->dev_port.hw_dev_num);
1817                break;
1818        case PRESTERA_IF_LAG_E:
1819                msg_if->lag_id = __cpu_to_le16(iface->lag_id);
1820                break;
1821        default:
1822                return -EOPNOTSUPP;
1823        }
1824
1825        msg_if->vr_id = __cpu_to_le16(iface->vr_id);
1826        msg_if->vid = __cpu_to_le16(iface->vlan_id);
1827        msg_if->type = iface->type;
1828        return 0;
1829}
1830
1831int prestera_hw_rif_create(struct prestera_switch *sw,
1832                           struct prestera_iface *iif, u8 *mac, u16 *rif_id)
1833{
1834        struct prestera_msg_rif_resp resp;
1835        struct prestera_msg_rif_req req;
1836        int err;
1837
1838        memcpy(req.mac, mac, ETH_ALEN);
1839
1840        err = prestera_iface_to_msg(iif, &req.iif);
1841        if (err)
1842                return err;
1843
1844        err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_CREATE,
1845                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1846        if (err)
1847                return err;
1848
1849        *rif_id = __le16_to_cpu(resp.rif_id);
1850        return err;
1851}
1852
1853int prestera_hw_rif_delete(struct prestera_switch *sw, u16 rif_id,
1854                           struct prestera_iface *iif)
1855{
1856        struct prestera_msg_rif_req req = {
1857                .rif_id = __cpu_to_le16(rif_id),
1858        };
1859        int err;
1860
1861        err = prestera_iface_to_msg(iif, &req.iif);
1862        if (err)
1863                return err;
1864
1865        return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE, &req.cmd,
1866                            sizeof(req));
1867}
1868
1869int prestera_hw_vr_create(struct prestera_switch *sw, u16 *vr_id)
1870{
1871        struct prestera_msg_vr_resp resp;
1872        struct prestera_msg_vr_req req;
1873        int err;
1874
1875        err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_VR_CREATE,
1876                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1877        if (err)
1878                return err;
1879
1880        *vr_id = __le16_to_cpu(resp.vr_id);
1881        return err;
1882}
1883
1884int prestera_hw_vr_delete(struct prestera_switch *sw, u16 vr_id)
1885{
1886        struct prestera_msg_vr_req req = {
1887                .vr_id = __cpu_to_le16(vr_id),
1888        };
1889
1890        return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_VR_DELETE, &req.cmd,
1891                            sizeof(req));
1892}
1893
1894int prestera_hw_rxtx_init(struct prestera_switch *sw,
1895                          struct prestera_rxtx_params *params)
1896{
1897        struct prestera_msg_rxtx_resp resp;
1898        struct prestera_msg_rxtx_req req;
1899        int err;
1900
1901        req.use_sdma = params->use_sdma;
1902
1903        err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT,
1904                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1905        if (err)
1906                return err;
1907
1908        params->map_addr = __le32_to_cpu(resp.map_addr);
1909
1910        return 0;
1911}
1912
1913int prestera_hw_lag_member_add(struct prestera_port *port, u16 lag_id)
1914{
1915        struct prestera_msg_lag_req req = {
1916                .port = __cpu_to_le32(port->hw_id),
1917                .dev = __cpu_to_le32(port->dev_id),
1918                .lag_id = __cpu_to_le16(lag_id),
1919        };
1920
1921        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_ADD,
1922                            &req.cmd, sizeof(req));
1923}
1924
1925int prestera_hw_lag_member_del(struct prestera_port *port, u16 lag_id)
1926{
1927        struct prestera_msg_lag_req req = {
1928                .port = __cpu_to_le32(port->hw_id),
1929                .dev = __cpu_to_le32(port->dev_id),
1930                .lag_id = __cpu_to_le16(lag_id),
1931        };
1932
1933        return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE,
1934                            &req.cmd, sizeof(req));
1935}
1936
1937int prestera_hw_lag_member_enable(struct prestera_port *port, u16 lag_id,
1938                                  bool enable)
1939{
1940        struct prestera_msg_lag_req req = {
1941                .port = __cpu_to_le32(port->hw_id),
1942                .dev = __cpu_to_le32(port->dev_id),
1943                .lag_id = __cpu_to_le16(lag_id),
1944        };
1945        u32 cmd;
1946
1947        cmd = enable ? PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE :
1948                        PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE;
1949
1950        return prestera_cmd(port->sw, cmd, &req.cmd, sizeof(req));
1951}
1952
1953int
1954prestera_hw_cpu_code_counters_get(struct prestera_switch *sw, u8 code,
1955                                  enum prestera_hw_cpu_code_cnt_t counter_type,
1956                                  u64 *packet_count)
1957{
1958        struct prestera_msg_cpu_code_counter_req req = {
1959                .counter_type = counter_type,
1960                .code = code,
1961        };
1962        struct mvsw_msg_cpu_code_counter_ret resp;
1963        int err;
1964
1965        err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET,
1966                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1967        if (err)
1968                return err;
1969
1970        *packet_count = __le64_to_cpu(resp.packet_count);
1971
1972        return 0;
1973}
1974
1975int prestera_hw_event_handler_register(struct prestera_switch *sw,
1976                                       enum prestera_event_type type,
1977                                       prestera_event_cb_t fn,
1978                                       void *arg)
1979{
1980        struct prestera_fw_event_handler *eh;
1981
1982        eh = __find_event_handler(sw, type);
1983        if (eh)
1984                return -EEXIST;
1985
1986        eh = kmalloc(sizeof(*eh), GFP_KERNEL);
1987        if (!eh)
1988                return -ENOMEM;
1989
1990        eh->type = type;
1991        eh->func = fn;
1992        eh->arg = arg;
1993
1994        INIT_LIST_HEAD(&eh->list);
1995
1996        list_add_rcu(&eh->list, &sw->event_handlers);
1997
1998        return 0;
1999}
2000
2001void prestera_hw_event_handler_unregister(struct prestera_switch *sw,
2002                                          enum prestera_event_type type,
2003                                          prestera_event_cb_t fn)
2004{
2005        struct prestera_fw_event_handler *eh;
2006
2007        eh = __find_event_handler(sw, type);
2008        if (!eh)
2009                return;
2010
2011        list_del_rcu(&eh->list);
2012        kfree_rcu(eh, rcu);
2013}
2014
2015int prestera_hw_counter_trigger(struct prestera_switch *sw, u32 block_id)
2016{
2017        struct prestera_msg_counter_req req = {
2018                .block_id = __cpu_to_le32(block_id)
2019        };
2020
2021        return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_TRIGGER,
2022                            &req.cmd, sizeof(req));
2023}
2024
2025int prestera_hw_counter_abort(struct prestera_switch *sw)
2026{
2027        struct prestera_msg_counter_req req;
2028
2029        return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_ABORT,
2030                            &req.cmd, sizeof(req));
2031}
2032
2033int prestera_hw_counters_get(struct prestera_switch *sw, u32 idx,
2034                             u32 *len, bool *done,
2035                             struct prestera_counter_stats *stats)
2036{
2037        struct prestera_msg_counter_resp *resp;
2038        struct prestera_msg_counter_req req = {
2039                .block_id = __cpu_to_le32(idx),
2040                .num_counters = __cpu_to_le32(*len),
2041        };
2042        size_t size = struct_size(resp, stats, *len);
2043        int err, i;
2044
2045        resp = kmalloc(size, GFP_KERNEL);
2046        if (!resp)
2047                return -ENOMEM;
2048
2049        err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_GET,
2050                               &req.cmd, sizeof(req), &resp->ret, size);
2051        if (err)
2052                goto free_buff;
2053
2054        for (i = 0; i < __le32_to_cpu(resp->num_counters); i++) {
2055                stats[i].packets += __le64_to_cpu(resp->stats[i].packets);
2056                stats[i].bytes += __le64_to_cpu(resp->stats[i].bytes);
2057        }
2058
2059        *len = __le32_to_cpu(resp->num_counters);
2060        *done = __le32_to_cpu(resp->done);
2061
2062free_buff:
2063        kfree(resp);
2064        return err;
2065}
2066
2067int prestera_hw_counter_block_get(struct prestera_switch *sw,
2068                                  u32 client, u32 *block_id, u32 *offset,
2069                                  u32 *num_counters)
2070{
2071        struct prestera_msg_counter_resp resp;
2072        struct prestera_msg_counter_req req = {
2073                .client = __cpu_to_le32(client)
2074        };
2075        int err;
2076
2077        err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_GET,
2078                               &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2079        if (err)
2080                return err;
2081
2082        *block_id = __le32_to_cpu(resp.block_id);
2083        *offset = __le32_to_cpu(resp.offset);
2084        *num_counters = __le32_to_cpu(resp.num_counters);
2085
2086        return 0;
2087}
2088
2089int prestera_hw_counter_block_release(struct prestera_switch *sw,
2090                                      u32 block_id)
2091{
2092        struct prestera_msg_counter_req req = {
2093                .block_id = __cpu_to_le32(block_id)
2094        };
2095
2096        return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_RELEASE,
2097                            &req.cmd, sizeof(req));
2098}
2099
2100int prestera_hw_counter_clear(struct prestera_switch *sw, u32 block_id,
2101                              u32 counter_id)
2102{
2103        struct prestera_msg_counter_req req = {
2104                .block_id = __cpu_to_le32(block_id),
2105                .num_counters = __cpu_to_le32(counter_id)
2106        };
2107
2108        return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_CLEAR,
2109                            &req.cmd, sizeof(req));
2110}
2111