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