Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
0003 
0004 #include <linux/etherdevice.h>
0005 #include <linux/if_bridge.h>
0006 #include <linux/ethtool.h>
0007 #include <linux/list.h>
0008 
0009 #include "prestera.h"
0010 #include "prestera_hw.h"
0011 #include "prestera_acl.h"
0012 #include "prestera_counter.h"
0013 
0014 #define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
0015 
0016 #define PRESTERA_MIN_MTU 64
0017 
0018 enum prestera_cmd_type_t {
0019     PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1,
0020     PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2,
0021 
0022     PRESTERA_CMD_TYPE_PORT_ATTR_SET = 0x100,
0023     PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101,
0024     PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110,
0025 
0026     PRESTERA_CMD_TYPE_VLAN_CREATE = 0x200,
0027     PRESTERA_CMD_TYPE_VLAN_DELETE = 0x201,
0028     PRESTERA_CMD_TYPE_VLAN_PORT_SET = 0x202,
0029     PRESTERA_CMD_TYPE_VLAN_PVID_SET = 0x203,
0030 
0031     PRESTERA_CMD_TYPE_FDB_ADD = 0x300,
0032     PRESTERA_CMD_TYPE_FDB_DELETE = 0x301,
0033     PRESTERA_CMD_TYPE_FDB_FLUSH_PORT = 0x310,
0034     PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN = 0x311,
0035     PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN = 0x312,
0036 
0037     PRESTERA_CMD_TYPE_BRIDGE_CREATE = 0x400,
0038     PRESTERA_CMD_TYPE_BRIDGE_DELETE = 0x401,
0039     PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD = 0x402,
0040     PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE = 0x403,
0041 
0042     PRESTERA_CMD_TYPE_COUNTER_GET = 0x510,
0043     PRESTERA_CMD_TYPE_COUNTER_ABORT = 0x511,
0044     PRESTERA_CMD_TYPE_COUNTER_TRIGGER = 0x512,
0045     PRESTERA_CMD_TYPE_COUNTER_BLOCK_GET = 0x513,
0046     PRESTERA_CMD_TYPE_COUNTER_BLOCK_RELEASE = 0x514,
0047     PRESTERA_CMD_TYPE_COUNTER_CLEAR = 0x515,
0048 
0049     PRESTERA_CMD_TYPE_VTCAM_CREATE = 0x540,
0050     PRESTERA_CMD_TYPE_VTCAM_DESTROY = 0x541,
0051     PRESTERA_CMD_TYPE_VTCAM_RULE_ADD = 0x550,
0052     PRESTERA_CMD_TYPE_VTCAM_RULE_DELETE = 0x551,
0053     PRESTERA_CMD_TYPE_VTCAM_IFACE_BIND = 0x560,
0054     PRESTERA_CMD_TYPE_VTCAM_IFACE_UNBIND = 0x561,
0055 
0056     PRESTERA_CMD_TYPE_ROUTER_RIF_CREATE = 0x600,
0057     PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE = 0x601,
0058     PRESTERA_CMD_TYPE_ROUTER_LPM_ADD = 0x610,
0059     PRESTERA_CMD_TYPE_ROUTER_LPM_DELETE = 0x611,
0060     PRESTERA_CMD_TYPE_ROUTER_VR_CREATE = 0x630,
0061     PRESTERA_CMD_TYPE_ROUTER_VR_DELETE = 0x631,
0062 
0063     PRESTERA_CMD_TYPE_FLOOD_DOMAIN_CREATE = 0x700,
0064     PRESTERA_CMD_TYPE_FLOOD_DOMAIN_DESTROY = 0x701,
0065     PRESTERA_CMD_TYPE_FLOOD_DOMAIN_PORTS_SET = 0x702,
0066     PRESTERA_CMD_TYPE_FLOOD_DOMAIN_PORTS_RESET = 0x703,
0067 
0068     PRESTERA_CMD_TYPE_MDB_CREATE = 0x704,
0069     PRESTERA_CMD_TYPE_MDB_DESTROY = 0x705,
0070 
0071     PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
0072 
0073     PRESTERA_CMD_TYPE_LAG_MEMBER_ADD = 0x900,
0074     PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE = 0x901,
0075     PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE = 0x902,
0076     PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE = 0x903,
0077 
0078     PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
0079 
0080     PRESTERA_CMD_TYPE_SPAN_GET = 0x1100,
0081     PRESTERA_CMD_TYPE_SPAN_BIND = 0x1101,
0082     PRESTERA_CMD_TYPE_SPAN_UNBIND = 0x1102,
0083     PRESTERA_CMD_TYPE_SPAN_RELEASE = 0x1103,
0084 
0085     PRESTERA_CMD_TYPE_POLICER_CREATE = 0x1500,
0086     PRESTERA_CMD_TYPE_POLICER_RELEASE = 0x1501,
0087     PRESTERA_CMD_TYPE_POLICER_SET = 0x1502,
0088 
0089     PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET = 0x2000,
0090 
0091     PRESTERA_CMD_TYPE_ACK = 0x10000,
0092     PRESTERA_CMD_TYPE_MAX
0093 };
0094 
0095 enum {
0096     PRESTERA_CMD_PORT_ATTR_ADMIN_STATE = 1,
0097     PRESTERA_CMD_PORT_ATTR_MTU = 3,
0098     PRESTERA_CMD_PORT_ATTR_MAC = 4,
0099     PRESTERA_CMD_PORT_ATTR_SPEED = 5,
0100     PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6,
0101     PRESTERA_CMD_PORT_ATTR_LEARNING = 7,
0102     PRESTERA_CMD_PORT_ATTR_FLOOD = 8,
0103     PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9,
0104     PRESTERA_CMD_PORT_ATTR_PHY_MODE = 12,
0105     PRESTERA_CMD_PORT_ATTR_TYPE = 13,
0106     PRESTERA_CMD_PORT_ATTR_STATS = 17,
0107     PRESTERA_CMD_PORT_ATTR_MAC_AUTONEG_RESTART = 18,
0108     PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART = 19,
0109     PRESTERA_CMD_PORT_ATTR_MAC_MODE = 22,
0110 };
0111 
0112 enum {
0113     PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
0114     PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
0115 };
0116 
0117 enum {
0118     PRESTERA_CMD_ACK_OK,
0119     PRESTERA_CMD_ACK_FAILED,
0120 
0121     PRESTERA_CMD_ACK_MAX
0122 };
0123 
0124 enum {
0125     PRESTERA_PORT_TP_NA,
0126     PRESTERA_PORT_TP_MDI,
0127     PRESTERA_PORT_TP_MDIX,
0128     PRESTERA_PORT_TP_AUTO,
0129 };
0130 
0131 enum {
0132     PRESTERA_PORT_FLOOD_TYPE_UC = 0,
0133     PRESTERA_PORT_FLOOD_TYPE_MC = 1,
0134 };
0135 
0136 enum {
0137     PRESTERA_PORT_GOOD_OCTETS_RCV_CNT,
0138     PRESTERA_PORT_BAD_OCTETS_RCV_CNT,
0139     PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT,
0140     PRESTERA_PORT_BRDC_PKTS_RCV_CNT,
0141     PRESTERA_PORT_MC_PKTS_RCV_CNT,
0142     PRESTERA_PORT_PKTS_64L_CNT,
0143     PRESTERA_PORT_PKTS_65TO127L_CNT,
0144     PRESTERA_PORT_PKTS_128TO255L_CNT,
0145     PRESTERA_PORT_PKTS_256TO511L_CNT,
0146     PRESTERA_PORT_PKTS_512TO1023L_CNT,
0147     PRESTERA_PORT_PKTS_1024TOMAXL_CNT,
0148     PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT,
0149     PRESTERA_PORT_MC_PKTS_SENT_CNT,
0150     PRESTERA_PORT_BRDC_PKTS_SENT_CNT,
0151     PRESTERA_PORT_FC_SENT_CNT,
0152     PRESTERA_PORT_GOOD_FC_RCV_CNT,
0153     PRESTERA_PORT_DROP_EVENTS_CNT,
0154     PRESTERA_PORT_UNDERSIZE_PKTS_CNT,
0155     PRESTERA_PORT_FRAGMENTS_PKTS_CNT,
0156     PRESTERA_PORT_OVERSIZE_PKTS_CNT,
0157     PRESTERA_PORT_JABBER_PKTS_CNT,
0158     PRESTERA_PORT_MAC_RCV_ERROR_CNT,
0159     PRESTERA_PORT_BAD_CRC_CNT,
0160     PRESTERA_PORT_COLLISIONS_CNT,
0161     PRESTERA_PORT_LATE_COLLISIONS_CNT,
0162     PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT,
0163     PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT,
0164     PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT,
0165     PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT,
0166     PRESTERA_PORT_GOOD_OCTETS_SENT_CNT,
0167 
0168     PRESTERA_PORT_CNT_MAX
0169 };
0170 
0171 enum {
0172     PRESTERA_FC_NONE,
0173     PRESTERA_FC_SYMMETRIC,
0174     PRESTERA_FC_ASYMMETRIC,
0175     PRESTERA_FC_SYMM_ASYMM,
0176 };
0177 
0178 enum {
0179     PRESTERA_POLICER_MODE_SR_TCM
0180 };
0181 
0182 enum {
0183     PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT = 0,
0184     PRESTERA_HW_FDB_ENTRY_TYPE_LAG = 1,
0185     PRESTERA_HW_FDB_ENTRY_TYPE_MAX = 2,
0186 };
0187 
0188 struct prestera_fw_event_handler {
0189     struct list_head list;
0190     struct rcu_head rcu;
0191     enum prestera_event_type type;
0192     prestera_event_cb_t func;
0193     void *arg;
0194 };
0195 
0196 enum {
0197     PRESTERA_HW_FLOOD_DOMAIN_PORT_TYPE_REG_PORT = 0,
0198     PRESTERA_HW_FLOOD_DOMAIN_PORT_TYPE_LAG = 1,
0199     PRESTERA_HW_FLOOD_DOMAIN_PORT_TYPE_MAX = 2,
0200 };
0201 
0202 struct prestera_msg_cmd {
0203     __le32 type;
0204 };
0205 
0206 struct prestera_msg_ret {
0207     struct prestera_msg_cmd cmd;
0208     __le32 status;
0209 };
0210 
0211 struct prestera_msg_common_req {
0212     struct prestera_msg_cmd cmd;
0213 };
0214 
0215 struct prestera_msg_common_resp {
0216     struct prestera_msg_ret ret;
0217 };
0218 
0219 struct prestera_msg_switch_attr_req {
0220     struct prestera_msg_cmd cmd;
0221     __le32 attr;
0222     union {
0223         __le32 ageing_timeout_ms;
0224         struct {
0225             u8 mac[ETH_ALEN];
0226             u8 __pad[2];
0227         };
0228     } param;
0229 };
0230 
0231 struct prestera_msg_switch_init_resp {
0232     struct prestera_msg_ret ret;
0233     __le32 port_count;
0234     __le32 mtu_max;
0235     __le32 size_tbl_router_nexthop;
0236     u8 switch_id;
0237     u8 lag_max;
0238     u8 lag_member_max;
0239 };
0240 
0241 struct prestera_msg_event_port_param {
0242     union {
0243         struct {
0244             __le32 mode;
0245             __le32 speed;
0246             u8 oper;
0247             u8 duplex;
0248             u8 fc;
0249             u8 fec;
0250         } mac;
0251         struct {
0252             __le64 lmode_bmap;
0253             u8 mdix;
0254             u8 fc;
0255             u8 __pad[2];
0256         } __packed phy; /* make sure always 12 bytes size */
0257     };
0258 };
0259 
0260 struct prestera_msg_port_cap_param {
0261     __le64 link_mode;
0262     u8 type;
0263     u8 fec;
0264     u8 fc;
0265     u8 transceiver;
0266 };
0267 
0268 struct prestera_msg_port_flood_param {
0269     u8 type;
0270     u8 enable;
0271     u8 __pad[2];
0272 };
0273 
0274 union prestera_msg_port_param {
0275     __le32 mtu;
0276     __le32 speed;
0277     __le32 link_mode;
0278     u8 admin_state;
0279     u8 oper_state;
0280     u8 mac[ETH_ALEN];
0281     u8 accept_frm_type;
0282     u8 learning;
0283     u8 flood;
0284     u8 type;
0285     u8 duplex;
0286     u8 fec;
0287     u8 fc;
0288     union {
0289         struct {
0290             u8 admin;
0291             u8 fc;
0292             u8 ap_enable;
0293             u8 __reserved[5];
0294             union {
0295                 struct {
0296                     __le32 mode;
0297                     __le32 speed;
0298                     u8 inband;
0299                     u8 duplex;
0300                     u8 fec;
0301                     u8 fec_supp;
0302                 } reg_mode;
0303                 struct {
0304                     __le32 mode;
0305                     __le32 speed;
0306                     u8 fec;
0307                     u8 fec_supp;
0308                     u8 __pad[2];
0309                 } ap_modes[PRESTERA_AP_PORT_MAX];
0310             };
0311         } mac;
0312         struct {
0313             __le64 modes;
0314             __le32 mode;
0315             u8 admin;
0316             u8 adv_enable;
0317             u8 mdix;
0318             u8 __pad;
0319         } phy;
0320     } link;
0321 
0322     struct prestera_msg_port_cap_param cap;
0323     struct prestera_msg_port_flood_param flood_ext;
0324     struct prestera_msg_event_port_param link_evt;
0325 };
0326 
0327 struct prestera_msg_port_attr_req {
0328     struct prestera_msg_cmd cmd;
0329     __le32 attr;
0330     __le32 port;
0331     __le32 dev;
0332     union prestera_msg_port_param param;
0333 };
0334 
0335 struct prestera_msg_port_attr_resp {
0336     struct prestera_msg_ret ret;
0337     union prestera_msg_port_param param;
0338 };
0339 
0340 struct prestera_msg_port_stats_resp {
0341     struct prestera_msg_ret ret;
0342     __le64 stats[PRESTERA_PORT_CNT_MAX];
0343 };
0344 
0345 struct prestera_msg_port_info_req {
0346     struct prestera_msg_cmd cmd;
0347     __le32 port;
0348 };
0349 
0350 struct prestera_msg_port_info_resp {
0351     struct prestera_msg_ret ret;
0352     __le32 hw_id;
0353     __le32 dev_id;
0354     __le16 fp_id;
0355     u8 pad[2];
0356 };
0357 
0358 struct prestera_msg_vlan_req {
0359     struct prestera_msg_cmd cmd;
0360     __le32 port;
0361     __le32 dev;
0362     __le16 vid;
0363     u8 is_member;
0364     u8 is_tagged;
0365 };
0366 
0367 struct prestera_msg_fdb_req {
0368     struct prestera_msg_cmd cmd;
0369     __le32 flush_mode;
0370     union {
0371         struct {
0372             __le32 port;
0373             __le32 dev;
0374         };
0375         __le16 lag_id;
0376     } dest;
0377     __le16 vid;
0378     u8 dest_type;
0379     u8 dynamic;
0380     u8 mac[ETH_ALEN];
0381     u8 __pad[2];
0382 };
0383 
0384 struct prestera_msg_bridge_req {
0385     struct prestera_msg_cmd cmd;
0386     __le32 port;
0387     __le32 dev;
0388     __le16 bridge;
0389     u8 pad[2];
0390 };
0391 
0392 struct prestera_msg_bridge_resp {
0393     struct prestera_msg_ret ret;
0394     __le16 bridge;
0395     u8 pad[2];
0396 };
0397 
0398 struct prestera_msg_vtcam_create_req {
0399     struct prestera_msg_cmd cmd;
0400     __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
0401     u8 direction;
0402     u8 lookup;
0403     u8 pad[2];
0404 };
0405 
0406 struct prestera_msg_vtcam_destroy_req {
0407     struct prestera_msg_cmd cmd;
0408     __le32 vtcam_id;
0409 };
0410 
0411 struct prestera_msg_vtcam_rule_add_req {
0412     struct prestera_msg_cmd cmd;
0413     __le32 key[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
0414     __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX];
0415     __le32 vtcam_id;
0416     __le32 prio;
0417     __le32 n_act;
0418 };
0419 
0420 struct prestera_msg_vtcam_rule_del_req {
0421     struct prestera_msg_cmd cmd;
0422     __le32 vtcam_id;
0423     __le32 id;
0424 };
0425 
0426 struct prestera_msg_vtcam_bind_req {
0427     struct prestera_msg_cmd cmd;
0428     union {
0429         struct {
0430             __le32 hw_id;
0431             __le32 dev_id;
0432         } port;
0433         __le32 index;
0434     };
0435     __le32 vtcam_id;
0436     __le16 pcl_id;
0437     __le16 type;
0438 };
0439 
0440 struct prestera_msg_vtcam_resp {
0441     struct prestera_msg_ret ret;
0442     __le32 vtcam_id;
0443     __le32 rule_id;
0444 };
0445 
0446 struct prestera_msg_acl_action {
0447     __le32 id;
0448     __le32 __reserved;
0449     union {
0450         struct {
0451             __le32 index;
0452         } jump;
0453         struct {
0454             __le32 id;
0455         } police;
0456         struct {
0457             __le32 id;
0458         } count;
0459         __le32 reserved[6];
0460     };
0461 };
0462 
0463 struct prestera_msg_counter_req {
0464     struct prestera_msg_cmd cmd;
0465     __le32 client;
0466     __le32 block_id;
0467     __le32 num_counters;
0468 };
0469 
0470 struct prestera_msg_counter_stats {
0471     __le64 packets;
0472     __le64 bytes;
0473 };
0474 
0475 struct prestera_msg_counter_resp {
0476     struct prestera_msg_ret ret;
0477     __le32 block_id;
0478     __le32 offset;
0479     __le32 num_counters;
0480     __le32 done;
0481     struct prestera_msg_counter_stats stats[];
0482 };
0483 
0484 struct prestera_msg_span_req {
0485     struct prestera_msg_cmd cmd;
0486     __le32 port;
0487     __le32 dev;
0488     u8 id;
0489     u8 pad[3];
0490 };
0491 
0492 struct prestera_msg_span_resp {
0493     struct prestera_msg_ret ret;
0494     u8 id;
0495     u8 pad[3];
0496 };
0497 
0498 struct prestera_msg_stp_req {
0499     struct prestera_msg_cmd cmd;
0500     __le32 port;
0501     __le32 dev;
0502     __le16 vid;
0503     u8 state;
0504     u8 __pad;
0505 };
0506 
0507 struct prestera_msg_rxtx_req {
0508     struct prestera_msg_cmd cmd;
0509     u8 use_sdma;
0510     u8 pad[3];
0511 };
0512 
0513 struct prestera_msg_rxtx_resp {
0514     struct prestera_msg_ret ret;
0515     __le32 map_addr;
0516 };
0517 
0518 struct prestera_msg_iface {
0519     union {
0520         struct {
0521             __le32 dev;
0522             __le32 port;
0523         };
0524         __le16 lag_id;
0525     };
0526     __le16 vr_id;
0527     __le16 vid;
0528     u8 type;
0529     u8 __pad[3];
0530 };
0531 
0532 struct prestera_msg_ip_addr {
0533     union {
0534         __be32 ipv4;
0535         __be32 ipv6[4];
0536     } u;
0537     u8 v; /* e.g. PRESTERA_IPV4 */
0538     u8 __pad[3];
0539 };
0540 
0541 struct prestera_msg_rif_req {
0542     struct prestera_msg_cmd cmd;
0543     struct prestera_msg_iface iif;
0544     __le32 mtu;
0545     __le16 rif_id;
0546     __le16 __reserved;
0547     u8 mac[ETH_ALEN];
0548     u8 __pad[2];
0549 };
0550 
0551 struct prestera_msg_rif_resp {
0552     struct prestera_msg_ret ret;
0553     __le16 rif_id;
0554     u8 __pad[2];
0555 };
0556 
0557 struct prestera_msg_lpm_req {
0558     struct prestera_msg_cmd cmd;
0559     struct prestera_msg_ip_addr dst;
0560     __le32 grp_id;
0561     __le32 dst_len;
0562     __le16 vr_id;
0563     u8 __pad[2];
0564 };
0565 
0566 struct prestera_msg_vr_req {
0567     struct prestera_msg_cmd cmd;
0568     __le16 vr_id;
0569     u8 __pad[2];
0570 };
0571 
0572 struct prestera_msg_vr_resp {
0573     struct prestera_msg_ret ret;
0574     __le16 vr_id;
0575     u8 __pad[2];
0576 };
0577 
0578 struct prestera_msg_lag_req {
0579     struct prestera_msg_cmd cmd;
0580     __le32 port;
0581     __le32 dev;
0582     __le16 lag_id;
0583     u8 pad[2];
0584 };
0585 
0586 struct prestera_msg_cpu_code_counter_req {
0587     struct prestera_msg_cmd cmd;
0588     u8 counter_type;
0589     u8 code;
0590     u8 pad[2];
0591 };
0592 
0593 struct mvsw_msg_cpu_code_counter_ret {
0594     struct prestera_msg_ret ret;
0595     __le64 packet_count;
0596 };
0597 
0598 struct prestera_msg_policer_req {
0599     struct prestera_msg_cmd cmd;
0600     __le32 id;
0601     union {
0602         struct {
0603             __le64 cir;
0604             __le32 cbs;
0605         } __packed sr_tcm; /* make sure always 12 bytes size */
0606         __le32 reserved[6];
0607     };
0608     u8 mode;
0609     u8 type;
0610     u8 pad[2];
0611 };
0612 
0613 struct prestera_msg_policer_resp {
0614     struct prestera_msg_ret ret;
0615     __le32 id;
0616 };
0617 
0618 struct prestera_msg_event {
0619     __le16 type;
0620     __le16 id;
0621 };
0622 
0623 struct prestera_msg_event_port {
0624     struct prestera_msg_event id;
0625     __le32 port_id;
0626     struct prestera_msg_event_port_param param;
0627 };
0628 
0629 union prestera_msg_event_fdb_param {
0630     u8 mac[ETH_ALEN];
0631 };
0632 
0633 struct prestera_msg_event_fdb {
0634     struct prestera_msg_event id;
0635     __le32 vid;
0636     union {
0637         __le32 port_id;
0638         __le16 lag_id;
0639     } dest;
0640     union prestera_msg_event_fdb_param param;
0641     u8 dest_type;
0642 };
0643 
0644 struct prestera_msg_flood_domain_create_req {
0645     struct prestera_msg_cmd cmd;
0646 };
0647 
0648 struct prestera_msg_flood_domain_create_resp {
0649     struct prestera_msg_ret ret;
0650     __le32 flood_domain_idx;
0651 };
0652 
0653 struct prestera_msg_flood_domain_destroy_req {
0654     struct prestera_msg_cmd cmd;
0655     __le32 flood_domain_idx;
0656 };
0657 
0658 struct prestera_msg_flood_domain_ports_set_req {
0659     struct prestera_msg_cmd cmd;
0660     __le32 flood_domain_idx;
0661     __le32 ports_num;
0662 };
0663 
0664 struct prestera_msg_flood_domain_ports_reset_req {
0665     struct prestera_msg_cmd cmd;
0666     __le32 flood_domain_idx;
0667 };
0668 
0669 struct prestera_msg_flood_domain_port {
0670     union {
0671         struct {
0672             __le32 port_num;
0673             __le32 dev_num;
0674         };
0675         __le16 lag_id;
0676     };
0677     __le16 vid;
0678     __le16 port_type;
0679 };
0680 
0681 struct prestera_msg_mdb_create_req {
0682     struct prestera_msg_cmd cmd;
0683     __le32 flood_domain_idx;
0684     __le16 vid;
0685     u8 mac[ETH_ALEN];
0686 };
0687 
0688 struct prestera_msg_mdb_destroy_req {
0689     struct prestera_msg_cmd cmd;
0690     __le32 flood_domain_idx;
0691     __le16 vid;
0692     u8 mac[ETH_ALEN];
0693 };
0694 
0695 static void prestera_hw_build_tests(void)
0696 {
0697     /* check requests */
0698     BUILD_BUG_ON(sizeof(struct prestera_msg_common_req) != 4);
0699     BUILD_BUG_ON(sizeof(struct prestera_msg_switch_attr_req) != 16);
0700     BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_req) != 144);
0701     BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_req) != 8);
0702     BUILD_BUG_ON(sizeof(struct prestera_msg_vlan_req) != 16);
0703     BUILD_BUG_ON(sizeof(struct prestera_msg_fdb_req) != 28);
0704     BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_req) != 16);
0705     BUILD_BUG_ON(sizeof(struct prestera_msg_span_req) != 16);
0706     BUILD_BUG_ON(sizeof(struct prestera_msg_stp_req) != 16);
0707     BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_req) != 8);
0708     BUILD_BUG_ON(sizeof(struct prestera_msg_lag_req) != 16);
0709     BUILD_BUG_ON(sizeof(struct prestera_msg_cpu_code_counter_req) != 8);
0710     BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_create_req) != 84);
0711     BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_destroy_req) != 8);
0712     BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_rule_add_req) != 168);
0713     BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_rule_del_req) != 12);
0714     BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_bind_req) != 20);
0715     BUILD_BUG_ON(sizeof(struct prestera_msg_acl_action) != 32);
0716     BUILD_BUG_ON(sizeof(struct prestera_msg_counter_req) != 16);
0717     BUILD_BUG_ON(sizeof(struct prestera_msg_counter_stats) != 16);
0718     BUILD_BUG_ON(sizeof(struct prestera_msg_rif_req) != 36);
0719     BUILD_BUG_ON(sizeof(struct prestera_msg_vr_req) != 8);
0720     BUILD_BUG_ON(sizeof(struct prestera_msg_lpm_req) != 36);
0721     BUILD_BUG_ON(sizeof(struct prestera_msg_policer_req) != 36);
0722     BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_create_req) != 4);
0723     BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_destroy_req) != 8);
0724     BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_ports_set_req) != 12);
0725     BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_ports_reset_req) != 8);
0726     BUILD_BUG_ON(sizeof(struct prestera_msg_mdb_create_req) != 16);
0727     BUILD_BUG_ON(sizeof(struct prestera_msg_mdb_destroy_req) != 16);
0728 
0729     /*  structure that are part of req/resp fw messages */
0730     BUILD_BUG_ON(sizeof(struct prestera_msg_iface) != 16);
0731     BUILD_BUG_ON(sizeof(struct prestera_msg_ip_addr) != 20);
0732     BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_port) != 12);
0733 
0734     /* check responses */
0735     BUILD_BUG_ON(sizeof(struct prestera_msg_common_resp) != 8);
0736     BUILD_BUG_ON(sizeof(struct prestera_msg_switch_init_resp) != 24);
0737     BUILD_BUG_ON(sizeof(struct prestera_msg_port_attr_resp) != 136);
0738     BUILD_BUG_ON(sizeof(struct prestera_msg_port_stats_resp) != 248);
0739     BUILD_BUG_ON(sizeof(struct prestera_msg_port_info_resp) != 20);
0740     BUILD_BUG_ON(sizeof(struct prestera_msg_bridge_resp) != 12);
0741     BUILD_BUG_ON(sizeof(struct prestera_msg_span_resp) != 12);
0742     BUILD_BUG_ON(sizeof(struct prestera_msg_rxtx_resp) != 12);
0743     BUILD_BUG_ON(sizeof(struct prestera_msg_vtcam_resp) != 16);
0744     BUILD_BUG_ON(sizeof(struct prestera_msg_counter_resp) != 24);
0745     BUILD_BUG_ON(sizeof(struct prestera_msg_rif_resp) != 12);
0746     BUILD_BUG_ON(sizeof(struct prestera_msg_vr_resp) != 12);
0747     BUILD_BUG_ON(sizeof(struct prestera_msg_policer_resp) != 12);
0748 
0749     /* check events */
0750     BUILD_BUG_ON(sizeof(struct prestera_msg_event_port) != 20);
0751     BUILD_BUG_ON(sizeof(struct prestera_msg_event_fdb) != 20);
0752 }
0753 
0754 static u8 prestera_hw_mdix_to_eth(u8 mode);
0755 static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause);
0756 
0757 static int __prestera_cmd_ret(struct prestera_switch *sw,
0758                   enum prestera_cmd_type_t type,
0759                   struct prestera_msg_cmd *cmd, size_t clen,
0760                   struct prestera_msg_ret *ret, size_t rlen,
0761                   int waitms)
0762 {
0763     struct prestera_device *dev = sw->dev;
0764     int err;
0765 
0766     cmd->type = __cpu_to_le32(type);
0767 
0768     err = dev->send_req(dev, 0, cmd, clen, ret, rlen, waitms);
0769     if (err)
0770         return err;
0771 
0772     if (ret->cmd.type != __cpu_to_le32(PRESTERA_CMD_TYPE_ACK))
0773         return -EBADE;
0774     if (ret->status != __cpu_to_le32(PRESTERA_CMD_ACK_OK))
0775         return -EINVAL;
0776 
0777     return 0;
0778 }
0779 
0780 static int prestera_cmd_ret(struct prestera_switch *sw,
0781                 enum prestera_cmd_type_t type,
0782                 struct prestera_msg_cmd *cmd, size_t clen,
0783                 struct prestera_msg_ret *ret, size_t rlen)
0784 {
0785     return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0);
0786 }
0787 
0788 static int prestera_cmd_ret_wait(struct prestera_switch *sw,
0789                  enum prestera_cmd_type_t type,
0790                  struct prestera_msg_cmd *cmd, size_t clen,
0791                  struct prestera_msg_ret *ret, size_t rlen,
0792                  int waitms)
0793 {
0794     return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms);
0795 }
0796 
0797 static int prestera_cmd(struct prestera_switch *sw,
0798             enum prestera_cmd_type_t type,
0799             struct prestera_msg_cmd *cmd, size_t clen)
0800 {
0801     struct prestera_msg_common_resp resp;
0802 
0803     return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp));
0804 }
0805 
0806 static int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt)
0807 {
0808     struct prestera_msg_event_port *hw_evt;
0809 
0810     hw_evt = (struct prestera_msg_event_port *)msg;
0811 
0812     evt->port_evt.port_id = __le32_to_cpu(hw_evt->port_id);
0813 
0814     if (evt->id == PRESTERA_PORT_EVENT_MAC_STATE_CHANGED) {
0815         evt->port_evt.data.mac.oper = hw_evt->param.mac.oper;
0816         evt->port_evt.data.mac.mode =
0817             __le32_to_cpu(hw_evt->param.mac.mode);
0818         evt->port_evt.data.mac.speed =
0819             __le32_to_cpu(hw_evt->param.mac.speed);
0820         evt->port_evt.data.mac.duplex = hw_evt->param.mac.duplex;
0821         evt->port_evt.data.mac.fc = hw_evt->param.mac.fc;
0822         evt->port_evt.data.mac.fec = hw_evt->param.mac.fec;
0823     } else {
0824         return -EINVAL;
0825     }
0826 
0827     return 0;
0828 }
0829 
0830 static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt)
0831 {
0832     struct prestera_msg_event_fdb *hw_evt = msg;
0833 
0834     switch (hw_evt->dest_type) {
0835     case PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT:
0836         evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_REG_PORT;
0837         evt->fdb_evt.dest.port_id = __le32_to_cpu(hw_evt->dest.port_id);
0838         break;
0839     case PRESTERA_HW_FDB_ENTRY_TYPE_LAG:
0840         evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_LAG;
0841         evt->fdb_evt.dest.lag_id = __le16_to_cpu(hw_evt->dest.lag_id);
0842         break;
0843     default:
0844         return -EINVAL;
0845     }
0846 
0847     evt->fdb_evt.vid = __le32_to_cpu(hw_evt->vid);
0848 
0849     ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac);
0850 
0851     return 0;
0852 }
0853 
0854 static struct prestera_fw_evt_parser {
0855     int (*func)(void *msg, struct prestera_event *evt);
0856 } fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = {
0857     [PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt },
0858     [PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt },
0859 };
0860 
0861 static struct prestera_fw_event_handler *
0862 __find_event_handler(const struct prestera_switch *sw,
0863              enum prestera_event_type type)
0864 {
0865     struct prestera_fw_event_handler *eh;
0866 
0867     list_for_each_entry_rcu(eh, &sw->event_handlers, list) {
0868         if (eh->type == type)
0869             return eh;
0870     }
0871 
0872     return NULL;
0873 }
0874 
0875 static int prestera_find_event_handler(const struct prestera_switch *sw,
0876                        enum prestera_event_type type,
0877                        struct prestera_fw_event_handler *eh)
0878 {
0879     struct prestera_fw_event_handler *tmp;
0880     int err = 0;
0881 
0882     rcu_read_lock();
0883     tmp = __find_event_handler(sw, type);
0884     if (tmp)
0885         *eh = *tmp;
0886     else
0887         err = -ENOENT;
0888     rcu_read_unlock();
0889 
0890     return err;
0891 }
0892 
0893 static int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size)
0894 {
0895     struct prestera_switch *sw = dev->priv;
0896     struct prestera_msg_event *msg = buf;
0897     struct prestera_fw_event_handler eh;
0898     struct prestera_event evt;
0899     u16 msg_type;
0900     int err;
0901 
0902     msg_type = __le16_to_cpu(msg->type);
0903     if (msg_type >= PRESTERA_EVENT_TYPE_MAX)
0904         return -EINVAL;
0905     if (!fw_event_parsers[msg_type].func)
0906         return -ENOENT;
0907 
0908     err = prestera_find_event_handler(sw, msg_type, &eh);
0909     if (err)
0910         return err;
0911 
0912     evt.id = __le16_to_cpu(msg->id);
0913 
0914     err = fw_event_parsers[msg_type].func(buf, &evt);
0915     if (err)
0916         return err;
0917 
0918     eh.func(sw, &evt, eh.arg);
0919 
0920     return 0;
0921 }
0922 
0923 static void prestera_pkt_recv(struct prestera_device *dev)
0924 {
0925     struct prestera_switch *sw = dev->priv;
0926     struct prestera_fw_event_handler eh;
0927     struct prestera_event ev;
0928     int err;
0929 
0930     ev.id = PRESTERA_RXTX_EVENT_RCV_PKT;
0931 
0932     err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh);
0933     if (err)
0934         return;
0935 
0936     eh.func(sw, &ev, eh.arg);
0937 }
0938 
0939 static u8 prestera_hw_mdix_to_eth(u8 mode)
0940 {
0941     switch (mode) {
0942     case PRESTERA_PORT_TP_MDI:
0943         return ETH_TP_MDI;
0944     case PRESTERA_PORT_TP_MDIX:
0945         return ETH_TP_MDI_X;
0946     case PRESTERA_PORT_TP_AUTO:
0947         return ETH_TP_MDI_AUTO;
0948     default:
0949         return ETH_TP_MDI_INVALID;
0950     }
0951 }
0952 
0953 static u8 prestera_hw_mdix_from_eth(u8 mode)
0954 {
0955     switch (mode) {
0956     case ETH_TP_MDI:
0957         return PRESTERA_PORT_TP_MDI;
0958     case ETH_TP_MDI_X:
0959         return PRESTERA_PORT_TP_MDIX;
0960     case ETH_TP_MDI_AUTO:
0961         return PRESTERA_PORT_TP_AUTO;
0962     default:
0963         return PRESTERA_PORT_TP_NA;
0964     }
0965 }
0966 
0967 int prestera_hw_port_info_get(const struct prestera_port *port,
0968                   u32 *dev_id, u32 *hw_id, u16 *fp_id)
0969 {
0970     struct prestera_msg_port_info_req req = {
0971         .port = __cpu_to_le32(port->id),
0972     };
0973     struct prestera_msg_port_info_resp resp;
0974     int err;
0975 
0976     err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET,
0977                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
0978     if (err)
0979         return err;
0980 
0981     *dev_id = __le32_to_cpu(resp.dev_id);
0982     *hw_id = __le32_to_cpu(resp.hw_id);
0983     *fp_id = __le16_to_cpu(resp.fp_id);
0984 
0985     return 0;
0986 }
0987 
0988 int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac)
0989 {
0990     struct prestera_msg_switch_attr_req req = {
0991         .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_MAC),
0992     };
0993 
0994     ether_addr_copy(req.param.mac, mac);
0995 
0996     return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
0997                 &req.cmd, sizeof(req));
0998 }
0999 
1000 int prestera_hw_switch_init(struct prestera_switch *sw)
1001 {
1002     struct prestera_msg_switch_init_resp resp;
1003     struct prestera_msg_common_req req;
1004     int err;
1005 
1006     INIT_LIST_HEAD(&sw->event_handlers);
1007 
1008     prestera_hw_build_tests();
1009 
1010     err = prestera_cmd_ret_wait(sw, PRESTERA_CMD_TYPE_SWITCH_INIT,
1011                     &req.cmd, sizeof(req),
1012                     &resp.ret, sizeof(resp),
1013                     PRESTERA_SWITCH_INIT_TIMEOUT_MS);
1014     if (err)
1015         return err;
1016 
1017     sw->dev->recv_msg = prestera_evt_recv;
1018     sw->dev->recv_pkt = prestera_pkt_recv;
1019     sw->port_count = __le32_to_cpu(resp.port_count);
1020     sw->mtu_min = PRESTERA_MIN_MTU;
1021     sw->mtu_max = __le32_to_cpu(resp.mtu_max);
1022     sw->id = resp.switch_id;
1023     sw->lag_member_max = resp.lag_member_max;
1024     sw->lag_max = resp.lag_max;
1025 
1026     return 0;
1027 }
1028 
1029 void prestera_hw_switch_fini(struct prestera_switch *sw)
1030 {
1031     WARN_ON(!list_empty(&sw->event_handlers));
1032 }
1033 
1034 int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms)
1035 {
1036     struct prestera_msg_switch_attr_req req = {
1037         .attr = __cpu_to_le32(PRESTERA_CMD_SWITCH_ATTR_AGEING),
1038         .param = {
1039             .ageing_timeout_ms = __cpu_to_le32(ageing_ms),
1040         },
1041     };
1042 
1043     return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
1044                 &req.cmd, sizeof(req));
1045 }
1046 
1047 int prestera_hw_port_mac_mode_get(const struct prestera_port *port,
1048                   u32 *mode, u32 *speed, u8 *duplex, u8 *fec)
1049 {
1050     struct prestera_msg_port_attr_resp resp;
1051     struct prestera_msg_port_attr_req req = {
1052         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
1053         .port = __cpu_to_le32(port->hw_id),
1054         .dev = __cpu_to_le32(port->dev_id)
1055     };
1056     int err;
1057 
1058     err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1059                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1060     if (err)
1061         return err;
1062 
1063     if (mode)
1064         *mode = __le32_to_cpu(resp.param.link_evt.mac.mode);
1065 
1066     if (speed)
1067         *speed = __le32_to_cpu(resp.param.link_evt.mac.speed);
1068 
1069     if (duplex)
1070         *duplex = resp.param.link_evt.mac.duplex;
1071 
1072     if (fec)
1073         *fec = resp.param.link_evt.mac.fec;
1074 
1075     return err;
1076 }
1077 
1078 int prestera_hw_port_mac_mode_set(const struct prestera_port *port,
1079                   bool admin, u32 mode, u8 inband,
1080                   u32 speed, u8 duplex, u8 fec)
1081 {
1082     struct prestera_msg_port_attr_req req = {
1083         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC_MODE),
1084         .port = __cpu_to_le32(port->hw_id),
1085         .dev = __cpu_to_le32(port->dev_id),
1086         .param = {
1087             .link = {
1088                 .mac = {
1089                     .admin = admin,
1090                     .reg_mode.mode = __cpu_to_le32(mode),
1091                     .reg_mode.inband = inband,
1092                     .reg_mode.speed = __cpu_to_le32(speed),
1093                     .reg_mode.duplex = duplex,
1094                     .reg_mode.fec = fec
1095                 }
1096             }
1097         }
1098     };
1099 
1100     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1101                 &req.cmd, sizeof(req));
1102 }
1103 
1104 int prestera_hw_port_phy_mode_get(const struct prestera_port *port,
1105                   u8 *mdix, u64 *lmode_bmap,
1106                   bool *fc_pause, bool *fc_asym)
1107 {
1108     struct prestera_msg_port_attr_resp resp;
1109     struct prestera_msg_port_attr_req req = {
1110         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_MODE),
1111         .port = __cpu_to_le32(port->hw_id),
1112         .dev = __cpu_to_le32(port->dev_id)
1113     };
1114     int err;
1115 
1116     err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1117                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1118     if (err)
1119         return err;
1120 
1121     if (mdix)
1122         *mdix = prestera_hw_mdix_to_eth(resp.param.link_evt.phy.mdix);
1123 
1124     if (lmode_bmap)
1125         *lmode_bmap = __le64_to_cpu(resp.param.link_evt.phy.lmode_bmap);
1126 
1127     if (fc_pause && fc_asym)
1128         prestera_hw_remote_fc_to_eth(resp.param.link_evt.phy.fc,
1129                          fc_pause, fc_asym);
1130 
1131     return err;
1132 }
1133 
1134 int prestera_hw_port_phy_mode_set(const struct prestera_port *port,
1135                   bool admin, bool adv, u32 mode, u64 modes,
1136                   u8 mdix)
1137 {
1138     struct prestera_msg_port_attr_req req = {
1139         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_MODE),
1140         .port = __cpu_to_le32(port->hw_id),
1141         .dev = __cpu_to_le32(port->dev_id),
1142         .param = {
1143             .link = {
1144                 .phy = {
1145                     .admin = admin,
1146                     .adv_enable = adv ? 1 : 0,
1147                     .mode = __cpu_to_le32(mode),
1148                     .modes = __cpu_to_le64(modes),
1149                 }
1150             }
1151         }
1152     };
1153 
1154     req.param.link.phy.mdix = prestera_hw_mdix_from_eth(mdix);
1155 
1156     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1157                 &req.cmd, sizeof(req));
1158 }
1159 
1160 int prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu)
1161 {
1162     struct prestera_msg_port_attr_req req = {
1163         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MTU),
1164         .port = __cpu_to_le32(port->hw_id),
1165         .dev = __cpu_to_le32(port->dev_id),
1166         .param = {
1167             .mtu = __cpu_to_le32(mtu),
1168         }
1169     };
1170 
1171     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1172                 &req.cmd, sizeof(req));
1173 }
1174 
1175 int prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac)
1176 {
1177     struct prestera_msg_port_attr_req req = {
1178         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_MAC),
1179         .port = __cpu_to_le32(port->hw_id),
1180         .dev = __cpu_to_le32(port->dev_id),
1181     };
1182 
1183     ether_addr_copy(req.param.mac, mac);
1184 
1185     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1186                 &req.cmd, sizeof(req));
1187 }
1188 
1189 int prestera_hw_port_accept_frm_type(struct prestera_port *port,
1190                      enum prestera_accept_frm_type type)
1191 {
1192     struct prestera_msg_port_attr_req req = {
1193         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE),
1194         .port = __cpu_to_le32(port->hw_id),
1195         .dev = __cpu_to_le32(port->dev_id),
1196         .param = {
1197             .accept_frm_type = type,
1198         }
1199     };
1200 
1201     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1202                 &req.cmd, sizeof(req));
1203 }
1204 
1205 int prestera_hw_port_cap_get(const struct prestera_port *port,
1206                  struct prestera_port_caps *caps)
1207 {
1208     struct prestera_msg_port_attr_req req = {
1209         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_CAPABILITY),
1210         .port = __cpu_to_le32(port->hw_id),
1211         .dev = __cpu_to_le32(port->dev_id),
1212     };
1213     struct prestera_msg_port_attr_resp resp;
1214     int err;
1215 
1216     err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1217                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1218     if (err)
1219         return err;
1220 
1221     caps->supp_link_modes = __le64_to_cpu(resp.param.cap.link_mode);
1222     caps->transceiver = resp.param.cap.transceiver;
1223     caps->supp_fec = resp.param.cap.fec;
1224     caps->type = resp.param.cap.type;
1225 
1226     return err;
1227 }
1228 
1229 static void prestera_hw_remote_fc_to_eth(u8 fc, bool *pause, bool *asym_pause)
1230 {
1231     switch (fc) {
1232     case PRESTERA_FC_SYMMETRIC:
1233         *pause = true;
1234         *asym_pause = false;
1235         break;
1236     case PRESTERA_FC_ASYMMETRIC:
1237         *pause = false;
1238         *asym_pause = true;
1239         break;
1240     case PRESTERA_FC_SYMM_ASYMM:
1241         *pause = true;
1242         *asym_pause = true;
1243         break;
1244     default:
1245         *pause = false;
1246         *asym_pause = false;
1247     }
1248 }
1249 
1250 int prestera_hw_vtcam_create(struct prestera_switch *sw,
1251                  u8 lookup, const u32 *keymask, u32 *vtcam_id,
1252                  enum prestera_hw_vtcam_direction_t dir)
1253 {
1254     int err;
1255     struct prestera_msg_vtcam_resp resp;
1256     struct prestera_msg_vtcam_create_req req = {
1257         .lookup = lookup,
1258         .direction = dir,
1259     };
1260 
1261     if (keymask)
1262         memcpy(req.keymask, keymask, sizeof(req.keymask));
1263     else
1264         memset(req.keymask, 0, sizeof(req.keymask));
1265 
1266     err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_CREATE,
1267                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1268     if (err)
1269         return err;
1270 
1271     *vtcam_id = __le32_to_cpu(resp.vtcam_id);
1272     return 0;
1273 }
1274 
1275 int prestera_hw_vtcam_destroy(struct prestera_switch *sw, u32 vtcam_id)
1276 {
1277     struct prestera_msg_vtcam_destroy_req req = {
1278         .vtcam_id = __cpu_to_le32(vtcam_id),
1279     };
1280 
1281     return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_DESTROY,
1282                 &req.cmd, sizeof(req));
1283 }
1284 
1285 static int
1286 prestera_acl_rule_add_put_action(struct prestera_msg_acl_action *action,
1287                  struct prestera_acl_hw_action_info *info)
1288 {
1289     action->id = __cpu_to_le32(info->id);
1290 
1291     switch (info->id) {
1292     case PRESTERA_ACL_RULE_ACTION_ACCEPT:
1293     case PRESTERA_ACL_RULE_ACTION_DROP:
1294     case PRESTERA_ACL_RULE_ACTION_TRAP:
1295         /* just rule action id, no specific data */
1296         break;
1297     case PRESTERA_ACL_RULE_ACTION_JUMP:
1298         action->jump.index = __cpu_to_le32(info->jump.index);
1299         break;
1300     case PRESTERA_ACL_RULE_ACTION_POLICE:
1301         action->police.id = __cpu_to_le32(info->police.id);
1302         break;
1303     case PRESTERA_ACL_RULE_ACTION_COUNT:
1304         action->count.id = __cpu_to_le32(info->count.id);
1305         break;
1306     default:
1307         return -EINVAL;
1308     }
1309 
1310     return 0;
1311 }
1312 
1313 int prestera_hw_vtcam_rule_add(struct prestera_switch *sw,
1314                    u32 vtcam_id, u32 prio, void *key, void *keymask,
1315                    struct prestera_acl_hw_action_info *act,
1316                    u8 n_act, u32 *rule_id)
1317 {
1318     struct prestera_msg_acl_action *actions_msg;
1319     struct prestera_msg_vtcam_rule_add_req *req;
1320     struct prestera_msg_vtcam_resp resp;
1321     void *buff;
1322     u32 size;
1323     int err;
1324     u8 i;
1325 
1326     size = sizeof(*req) + sizeof(*actions_msg) * n_act;
1327 
1328     buff = kzalloc(size, GFP_KERNEL);
1329     if (!buff)
1330         return -ENOMEM;
1331 
1332     req = buff;
1333     req->n_act = __cpu_to_le32(n_act);
1334     actions_msg = buff + sizeof(*req);
1335 
1336     /* put acl matches into the message */
1337     memcpy(req->key, key, sizeof(req->key));
1338     memcpy(req->keymask, keymask, sizeof(req->keymask));
1339 
1340     /* put acl actions into the message */
1341     for (i = 0; i < n_act; i++) {
1342         err = prestera_acl_rule_add_put_action(&actions_msg[i],
1343                                &act[i]);
1344         if (err)
1345             goto free_buff;
1346     }
1347 
1348     req->vtcam_id = __cpu_to_le32(vtcam_id);
1349     req->prio = __cpu_to_le32(prio);
1350 
1351     err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_ADD,
1352                    &req->cmd, size, &resp.ret, sizeof(resp));
1353     if (err)
1354         goto free_buff;
1355 
1356     *rule_id = __le32_to_cpu(resp.rule_id);
1357 free_buff:
1358     kfree(buff);
1359     return err;
1360 }
1361 
1362 int prestera_hw_vtcam_rule_del(struct prestera_switch *sw,
1363                    u32 vtcam_id, u32 rule_id)
1364 {
1365     struct prestera_msg_vtcam_rule_del_req req = {
1366         .vtcam_id = __cpu_to_le32(vtcam_id),
1367         .id = __cpu_to_le32(rule_id)
1368     };
1369 
1370     return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_RULE_DELETE,
1371                 &req.cmd, sizeof(req));
1372 }
1373 
1374 int prestera_hw_vtcam_iface_bind(struct prestera_switch *sw,
1375                  struct prestera_acl_iface *iface,
1376                  u32 vtcam_id, u16 pcl_id)
1377 {
1378     struct prestera_msg_vtcam_bind_req req = {
1379         .vtcam_id = __cpu_to_le32(vtcam_id),
1380         .type = __cpu_to_le16(iface->type),
1381         .pcl_id = __cpu_to_le16(pcl_id)
1382     };
1383 
1384     if (iface->type == PRESTERA_ACL_IFACE_TYPE_PORT) {
1385         req.port.dev_id = __cpu_to_le32(iface->port->dev_id);
1386         req.port.hw_id = __cpu_to_le32(iface->port->hw_id);
1387     } else {
1388         req.index = __cpu_to_le32(iface->index);
1389     }
1390 
1391     return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_BIND,
1392                 &req.cmd, sizeof(req));
1393 }
1394 
1395 int prestera_hw_vtcam_iface_unbind(struct prestera_switch *sw,
1396                    struct prestera_acl_iface *iface,
1397                    u32 vtcam_id)
1398 {
1399     struct prestera_msg_vtcam_bind_req req = {
1400         .vtcam_id = __cpu_to_le32(vtcam_id),
1401         .type = __cpu_to_le16(iface->type)
1402     };
1403 
1404     if (iface->type == PRESTERA_ACL_IFACE_TYPE_PORT) {
1405         req.port.dev_id = __cpu_to_le32(iface->port->dev_id);
1406         req.port.hw_id = __cpu_to_le32(iface->port->hw_id);
1407     } else {
1408         req.index = __cpu_to_le32(iface->index);
1409     }
1410 
1411     return prestera_cmd(sw, PRESTERA_CMD_TYPE_VTCAM_IFACE_UNBIND,
1412                 &req.cmd, sizeof(req));
1413 }
1414 
1415 int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id)
1416 {
1417     struct prestera_msg_span_resp resp;
1418     struct prestera_msg_span_req req = {
1419         .port = __cpu_to_le32(port->hw_id),
1420         .dev = __cpu_to_le32(port->dev_id),
1421     };
1422     int err;
1423 
1424     err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_SPAN_GET,
1425                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1426     if (err)
1427         return err;
1428 
1429     *span_id = resp.id;
1430 
1431     return 0;
1432 }
1433 
1434 int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id)
1435 {
1436     struct prestera_msg_span_req req = {
1437         .port = __cpu_to_le32(port->hw_id),
1438         .dev = __cpu_to_le32(port->dev_id),
1439         .id = span_id,
1440     };
1441 
1442     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_BIND,
1443                 &req.cmd, sizeof(req));
1444 }
1445 
1446 int prestera_hw_span_unbind(const struct prestera_port *port)
1447 {
1448     struct prestera_msg_span_req req = {
1449         .port = __cpu_to_le32(port->hw_id),
1450         .dev = __cpu_to_le32(port->dev_id),
1451     };
1452 
1453     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_UNBIND,
1454                 &req.cmd, sizeof(req));
1455 }
1456 
1457 int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id)
1458 {
1459     struct prestera_msg_span_req req = {
1460         .id = span_id
1461     };
1462 
1463     return prestera_cmd(sw, PRESTERA_CMD_TYPE_SPAN_RELEASE,
1464                 &req.cmd, sizeof(req));
1465 }
1466 
1467 int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
1468 {
1469     struct prestera_msg_port_attr_req req = {
1470         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_TYPE),
1471         .port = __cpu_to_le32(port->hw_id),
1472         .dev = __cpu_to_le32(port->dev_id),
1473     };
1474     struct prestera_msg_port_attr_resp resp;
1475     int err;
1476 
1477     err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1478                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1479     if (err)
1480         return err;
1481 
1482     *type = resp.param.type;
1483 
1484     return 0;
1485 }
1486 
1487 int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed)
1488 {
1489     struct prestera_msg_port_attr_req req = {
1490         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_SPEED),
1491         .port = __cpu_to_le32(port->hw_id),
1492         .dev = __cpu_to_le32(port->dev_id),
1493     };
1494     struct prestera_msg_port_attr_resp resp;
1495     int err;
1496 
1497     err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1498                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1499     if (err)
1500         return err;
1501 
1502     *speed = __le32_to_cpu(resp.param.speed);
1503 
1504     return 0;
1505 }
1506 
1507 int prestera_hw_port_autoneg_restart(struct prestera_port *port)
1508 {
1509     struct prestera_msg_port_attr_req req = {
1510         .attr =
1511             __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_PHY_AUTONEG_RESTART),
1512         .port = __cpu_to_le32(port->hw_id),
1513         .dev = __cpu_to_le32(port->dev_id),
1514     };
1515 
1516     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1517                 &req.cmd, sizeof(req));
1518 }
1519 
1520 int prestera_hw_port_stats_get(const struct prestera_port *port,
1521                    struct prestera_port_stats *st)
1522 {
1523     struct prestera_msg_port_attr_req req = {
1524         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_STATS),
1525         .port = __cpu_to_le32(port->hw_id),
1526         .dev = __cpu_to_le32(port->dev_id),
1527     };
1528     struct prestera_msg_port_stats_resp resp;
1529     __le64 *hw = resp.stats;
1530     int err;
1531 
1532     err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
1533                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1534     if (err)
1535         return err;
1536 
1537     st->good_octets_received =
1538         __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_RCV_CNT]);
1539     st->bad_octets_received =
1540         __le64_to_cpu(hw[PRESTERA_PORT_BAD_OCTETS_RCV_CNT]);
1541     st->mac_trans_error =
1542         __le64_to_cpu(hw[PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT]);
1543     st->broadcast_frames_received =
1544         __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_RCV_CNT]);
1545     st->multicast_frames_received =
1546         __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_RCV_CNT]);
1547     st->frames_64_octets = __le64_to_cpu(hw[PRESTERA_PORT_PKTS_64L_CNT]);
1548     st->frames_65_to_127_octets =
1549         __le64_to_cpu(hw[PRESTERA_PORT_PKTS_65TO127L_CNT]);
1550     st->frames_128_to_255_octets =
1551         __le64_to_cpu(hw[PRESTERA_PORT_PKTS_128TO255L_CNT]);
1552     st->frames_256_to_511_octets =
1553         __le64_to_cpu(hw[PRESTERA_PORT_PKTS_256TO511L_CNT]);
1554     st->frames_512_to_1023_octets =
1555         __le64_to_cpu(hw[PRESTERA_PORT_PKTS_512TO1023L_CNT]);
1556     st->frames_1024_to_max_octets =
1557         __le64_to_cpu(hw[PRESTERA_PORT_PKTS_1024TOMAXL_CNT]);
1558     st->excessive_collision =
1559         __le64_to_cpu(hw[PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT]);
1560     st->multicast_frames_sent =
1561         __le64_to_cpu(hw[PRESTERA_PORT_MC_PKTS_SENT_CNT]);
1562     st->broadcast_frames_sent =
1563         __le64_to_cpu(hw[PRESTERA_PORT_BRDC_PKTS_SENT_CNT]);
1564     st->fc_sent = __le64_to_cpu(hw[PRESTERA_PORT_FC_SENT_CNT]);
1565     st->fc_received = __le64_to_cpu(hw[PRESTERA_PORT_GOOD_FC_RCV_CNT]);
1566     st->buffer_overrun = __le64_to_cpu(hw[PRESTERA_PORT_DROP_EVENTS_CNT]);
1567     st->undersize = __le64_to_cpu(hw[PRESTERA_PORT_UNDERSIZE_PKTS_CNT]);
1568     st->fragments = __le64_to_cpu(hw[PRESTERA_PORT_FRAGMENTS_PKTS_CNT]);
1569     st->oversize = __le64_to_cpu(hw[PRESTERA_PORT_OVERSIZE_PKTS_CNT]);
1570     st->jabber = __le64_to_cpu(hw[PRESTERA_PORT_JABBER_PKTS_CNT]);
1571     st->rx_error_frame_received =
1572         __le64_to_cpu(hw[PRESTERA_PORT_MAC_RCV_ERROR_CNT]);
1573     st->bad_crc = __le64_to_cpu(hw[PRESTERA_PORT_BAD_CRC_CNT]);
1574     st->collisions = __le64_to_cpu(hw[PRESTERA_PORT_COLLISIONS_CNT]);
1575     st->late_collision =
1576         __le64_to_cpu(hw[PRESTERA_PORT_LATE_COLLISIONS_CNT]);
1577     st->unicast_frames_received =
1578         __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT]);
1579     st->unicast_frames_sent =
1580         __le64_to_cpu(hw[PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT]);
1581     st->sent_multiple =
1582         __le64_to_cpu(hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT]);
1583     st->sent_deferred =
1584         __le64_to_cpu(hw[PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT]);
1585     st->good_octets_sent =
1586         __le64_to_cpu(hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT]);
1587 
1588     return 0;
1589 }
1590 
1591 int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
1592 {
1593     struct prestera_msg_port_attr_req req = {
1594         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_LEARNING),
1595         .port = __cpu_to_le32(port->hw_id),
1596         .dev = __cpu_to_le32(port->dev_id),
1597         .param = {
1598             .learning = enable,
1599         }
1600     };
1601 
1602     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1603                 &req.cmd, sizeof(req));
1604 }
1605 
1606 int prestera_hw_port_uc_flood_set(const struct prestera_port *port, bool flood)
1607 {
1608     struct prestera_msg_port_attr_req req = {
1609         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1610         .port = __cpu_to_le32(port->hw_id),
1611         .dev = __cpu_to_le32(port->dev_id),
1612         .param = {
1613             .flood_ext = {
1614                 .type = PRESTERA_PORT_FLOOD_TYPE_UC,
1615                 .enable = flood,
1616             }
1617         }
1618     };
1619 
1620     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1621                 &req.cmd, sizeof(req));
1622 }
1623 
1624 int prestera_hw_port_mc_flood_set(const struct prestera_port *port, bool flood)
1625 {
1626     struct prestera_msg_port_attr_req req = {
1627         .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
1628         .port = __cpu_to_le32(port->hw_id),
1629         .dev = __cpu_to_le32(port->dev_id),
1630         .param = {
1631             .flood_ext = {
1632                 .type = PRESTERA_PORT_FLOOD_TYPE_MC,
1633                 .enable = flood,
1634             }
1635         }
1636     };
1637 
1638     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
1639                 &req.cmd, sizeof(req));
1640 }
1641 
1642 int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
1643 {
1644     struct prestera_msg_vlan_req req = {
1645         .vid = __cpu_to_le16(vid),
1646     };
1647 
1648     return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE,
1649                 &req.cmd, sizeof(req));
1650 }
1651 
1652 int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid)
1653 {
1654     struct prestera_msg_vlan_req req = {
1655         .vid = __cpu_to_le16(vid),
1656     };
1657 
1658     return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE,
1659                 &req.cmd, sizeof(req));
1660 }
1661 
1662 int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid,
1663                   bool is_member, bool untagged)
1664 {
1665     struct prestera_msg_vlan_req req = {
1666         .port = __cpu_to_le32(port->hw_id),
1667         .dev = __cpu_to_le32(port->dev_id),
1668         .vid = __cpu_to_le16(vid),
1669         .is_member = is_member,
1670         .is_tagged = !untagged,
1671     };
1672 
1673     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET,
1674                 &req.cmd, sizeof(req));
1675 }
1676 
1677 int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid)
1678 {
1679     struct prestera_msg_vlan_req req = {
1680         .port = __cpu_to_le32(port->hw_id),
1681         .dev = __cpu_to_le32(port->dev_id),
1682         .vid = __cpu_to_le16(vid),
1683     };
1684 
1685     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET,
1686                 &req.cmd, sizeof(req));
1687 }
1688 
1689 int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state)
1690 {
1691     struct prestera_msg_stp_req req = {
1692         .port = __cpu_to_le32(port->hw_id),
1693         .dev = __cpu_to_le32(port->dev_id),
1694         .vid = __cpu_to_le16(vid),
1695         .state = state,
1696     };
1697 
1698     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET,
1699                 &req.cmd, sizeof(req));
1700 }
1701 
1702 int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac,
1703             u16 vid, bool dynamic)
1704 {
1705     struct prestera_msg_fdb_req req = {
1706         .dest = {
1707             .dev = __cpu_to_le32(port->dev_id),
1708             .port = __cpu_to_le32(port->hw_id),
1709         },
1710         .vid = __cpu_to_le16(vid),
1711         .dynamic = dynamic,
1712     };
1713 
1714     ether_addr_copy(req.mac, mac);
1715 
1716     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD,
1717                 &req.cmd, sizeof(req));
1718 }
1719 
1720 int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac,
1721             u16 vid)
1722 {
1723     struct prestera_msg_fdb_req req = {
1724         .dest = {
1725             .dev = __cpu_to_le32(port->dev_id),
1726             .port = __cpu_to_le32(port->hw_id),
1727         },
1728         .vid = __cpu_to_le16(vid),
1729     };
1730 
1731     ether_addr_copy(req.mac, mac);
1732 
1733     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1734                 &req.cmd, sizeof(req));
1735 }
1736 
1737 int prestera_hw_lag_fdb_add(struct prestera_switch *sw, u16 lag_id,
1738                 const unsigned char *mac, u16 vid, bool dynamic)
1739 {
1740     struct prestera_msg_fdb_req req = {
1741         .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1742         .dest = {
1743             .lag_id = __cpu_to_le16(lag_id),
1744         },
1745         .vid = __cpu_to_le16(vid),
1746         .dynamic = dynamic,
1747     };
1748 
1749     ether_addr_copy(req.mac, mac);
1750 
1751     return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_ADD,
1752                 &req.cmd, sizeof(req));
1753 }
1754 
1755 int prestera_hw_lag_fdb_del(struct prestera_switch *sw, u16 lag_id,
1756                 const unsigned char *mac, u16 vid)
1757 {
1758     struct prestera_msg_fdb_req req = {
1759         .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1760         .dest = {
1761             .lag_id = __cpu_to_le16(lag_id),
1762         },
1763         .vid = __cpu_to_le16(vid),
1764     };
1765 
1766     ether_addr_copy(req.mac, mac);
1767 
1768     return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_DELETE,
1769                 &req.cmd, sizeof(req));
1770 }
1771 
1772 int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode)
1773 {
1774     struct prestera_msg_fdb_req req = {
1775         .dest = {
1776             .dev = __cpu_to_le32(port->dev_id),
1777             .port = __cpu_to_le32(port->hw_id),
1778         },
1779         .flush_mode = __cpu_to_le32(mode),
1780     };
1781 
1782     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1783                 &req.cmd, sizeof(req));
1784 }
1785 
1786 int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode)
1787 {
1788     struct prestera_msg_fdb_req req = {
1789         .vid = __cpu_to_le16(vid),
1790         .flush_mode = __cpu_to_le32(mode),
1791     };
1792 
1793     return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN,
1794                 &req.cmd, sizeof(req));
1795 }
1796 
1797 int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
1798                     u32 mode)
1799 {
1800     struct prestera_msg_fdb_req req = {
1801         .dest = {
1802             .dev = __cpu_to_le32(port->dev_id),
1803             .port = __cpu_to_le32(port->hw_id),
1804         },
1805         .vid = __cpu_to_le16(vid),
1806         .flush_mode = __cpu_to_le32(mode),
1807     };
1808 
1809     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1810                 &req.cmd, sizeof(req));
1811 }
1812 
1813 int prestera_hw_fdb_flush_lag(struct prestera_switch *sw, u16 lag_id,
1814                   u32 mode)
1815 {
1816     struct prestera_msg_fdb_req req = {
1817         .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1818         .dest = {
1819             .lag_id = __cpu_to_le16(lag_id),
1820         },
1821         .flush_mode = __cpu_to_le32(mode),
1822     };
1823 
1824     return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
1825                 &req.cmd, sizeof(req));
1826 }
1827 
1828 int prestera_hw_fdb_flush_lag_vlan(struct prestera_switch *sw,
1829                    u16 lag_id, u16 vid, u32 mode)
1830 {
1831     struct prestera_msg_fdb_req req = {
1832         .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG,
1833         .dest = {
1834             .lag_id = __cpu_to_le16(lag_id),
1835         },
1836         .vid = __cpu_to_le16(vid),
1837         .flush_mode = __cpu_to_le32(mode),
1838     };
1839 
1840     return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
1841                 &req.cmd, sizeof(req));
1842 }
1843 
1844 int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id)
1845 {
1846     struct prestera_msg_bridge_resp resp;
1847     struct prestera_msg_bridge_req req;
1848     int err;
1849 
1850     err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE,
1851                    &req.cmd, sizeof(req),
1852                    &resp.ret, sizeof(resp));
1853     if (err)
1854         return err;
1855 
1856     *bridge_id = __le16_to_cpu(resp.bridge);
1857 
1858     return 0;
1859 }
1860 
1861 int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id)
1862 {
1863     struct prestera_msg_bridge_req req = {
1864         .bridge = __cpu_to_le16(bridge_id),
1865     };
1866 
1867     return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE,
1868                 &req.cmd, sizeof(req));
1869 }
1870 
1871 int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id)
1872 {
1873     struct prestera_msg_bridge_req req = {
1874         .bridge = __cpu_to_le16(bridge_id),
1875         .port = __cpu_to_le32(port->hw_id),
1876         .dev = __cpu_to_le32(port->dev_id),
1877     };
1878 
1879     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD,
1880                 &req.cmd, sizeof(req));
1881 }
1882 
1883 int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)
1884 {
1885     struct prestera_msg_bridge_req req = {
1886         .bridge = __cpu_to_le16(bridge_id),
1887         .port = __cpu_to_le32(port->hw_id),
1888         .dev = __cpu_to_le32(port->dev_id),
1889     };
1890 
1891     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE,
1892                 &req.cmd, sizeof(req));
1893 }
1894 
1895 static int prestera_iface_to_msg(struct prestera_iface *iface,
1896                  struct prestera_msg_iface *msg_if)
1897 {
1898     switch (iface->type) {
1899     case PRESTERA_IF_PORT_E:
1900     case PRESTERA_IF_VID_E:
1901         msg_if->port = __cpu_to_le32(iface->dev_port.port_num);
1902         msg_if->dev = __cpu_to_le32(iface->dev_port.hw_dev_num);
1903         break;
1904     case PRESTERA_IF_LAG_E:
1905         msg_if->lag_id = __cpu_to_le16(iface->lag_id);
1906         break;
1907     default:
1908         return -EOPNOTSUPP;
1909     }
1910 
1911     msg_if->vr_id = __cpu_to_le16(iface->vr_id);
1912     msg_if->vid = __cpu_to_le16(iface->vlan_id);
1913     msg_if->type = iface->type;
1914     return 0;
1915 }
1916 
1917 int prestera_hw_rif_create(struct prestera_switch *sw,
1918                struct prestera_iface *iif, u8 *mac, u16 *rif_id)
1919 {
1920     struct prestera_msg_rif_resp resp;
1921     struct prestera_msg_rif_req req;
1922     int err;
1923 
1924     memcpy(req.mac, mac, ETH_ALEN);
1925 
1926     err = prestera_iface_to_msg(iif, &req.iif);
1927     if (err)
1928         return err;
1929 
1930     err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_CREATE,
1931                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1932     if (err)
1933         return err;
1934 
1935     *rif_id = __le16_to_cpu(resp.rif_id);
1936     return err;
1937 }
1938 
1939 int prestera_hw_rif_delete(struct prestera_switch *sw, u16 rif_id,
1940                struct prestera_iface *iif)
1941 {
1942     struct prestera_msg_rif_req req = {
1943         .rif_id = __cpu_to_le16(rif_id),
1944     };
1945     int err;
1946 
1947     err = prestera_iface_to_msg(iif, &req.iif);
1948     if (err)
1949         return err;
1950 
1951     return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE, &req.cmd,
1952                 sizeof(req));
1953 }
1954 
1955 int prestera_hw_vr_create(struct prestera_switch *sw, u16 *vr_id)
1956 {
1957     struct prestera_msg_vr_resp resp;
1958     struct prestera_msg_vr_req req;
1959     int err;
1960 
1961     err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_VR_CREATE,
1962                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
1963     if (err)
1964         return err;
1965 
1966     *vr_id = __le16_to_cpu(resp.vr_id);
1967     return err;
1968 }
1969 
1970 int prestera_hw_vr_delete(struct prestera_switch *sw, u16 vr_id)
1971 {
1972     struct prestera_msg_vr_req req = {
1973         .vr_id = __cpu_to_le16(vr_id),
1974     };
1975 
1976     return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_VR_DELETE, &req.cmd,
1977                 sizeof(req));
1978 }
1979 
1980 int prestera_hw_lpm_add(struct prestera_switch *sw, u16 vr_id,
1981             __be32 dst, u32 dst_len, u32 grp_id)
1982 {
1983     struct prestera_msg_lpm_req req = {
1984         .dst_len = __cpu_to_le32(dst_len),
1985         .vr_id = __cpu_to_le16(vr_id),
1986         .grp_id = __cpu_to_le32(grp_id),
1987         .dst.u.ipv4 = dst
1988     };
1989 
1990     return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_ADD, &req.cmd,
1991                 sizeof(req));
1992 }
1993 
1994 int prestera_hw_lpm_del(struct prestera_switch *sw, u16 vr_id,
1995             __be32 dst, u32 dst_len)
1996 {
1997     struct prestera_msg_lpm_req req = {
1998         .dst_len = __cpu_to_le32(dst_len),
1999         .vr_id = __cpu_to_le16(vr_id),
2000         .dst.u.ipv4 = dst
2001     };
2002 
2003     return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_DELETE, &req.cmd,
2004                 sizeof(req));
2005 }
2006 
2007 int prestera_hw_rxtx_init(struct prestera_switch *sw,
2008               struct prestera_rxtx_params *params)
2009 {
2010     struct prestera_msg_rxtx_resp resp;
2011     struct prestera_msg_rxtx_req req;
2012     int err;
2013 
2014     req.use_sdma = params->use_sdma;
2015 
2016     err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT,
2017                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2018     if (err)
2019         return err;
2020 
2021     params->map_addr = __le32_to_cpu(resp.map_addr);
2022 
2023     return 0;
2024 }
2025 
2026 int prestera_hw_lag_member_add(struct prestera_port *port, u16 lag_id)
2027 {
2028     struct prestera_msg_lag_req req = {
2029         .port = __cpu_to_le32(port->hw_id),
2030         .dev = __cpu_to_le32(port->dev_id),
2031         .lag_id = __cpu_to_le16(lag_id),
2032     };
2033 
2034     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_ADD,
2035                 &req.cmd, sizeof(req));
2036 }
2037 
2038 int prestera_hw_lag_member_del(struct prestera_port *port, u16 lag_id)
2039 {
2040     struct prestera_msg_lag_req req = {
2041         .port = __cpu_to_le32(port->hw_id),
2042         .dev = __cpu_to_le32(port->dev_id),
2043         .lag_id = __cpu_to_le16(lag_id),
2044     };
2045 
2046     return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE,
2047                 &req.cmd, sizeof(req));
2048 }
2049 
2050 int prestera_hw_lag_member_enable(struct prestera_port *port, u16 lag_id,
2051                   bool enable)
2052 {
2053     struct prestera_msg_lag_req req = {
2054         .port = __cpu_to_le32(port->hw_id),
2055         .dev = __cpu_to_le32(port->dev_id),
2056         .lag_id = __cpu_to_le16(lag_id),
2057     };
2058     u32 cmd;
2059 
2060     cmd = enable ? PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE :
2061             PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE;
2062 
2063     return prestera_cmd(port->sw, cmd, &req.cmd, sizeof(req));
2064 }
2065 
2066 int
2067 prestera_hw_cpu_code_counters_get(struct prestera_switch *sw, u8 code,
2068                   enum prestera_hw_cpu_code_cnt_t counter_type,
2069                   u64 *packet_count)
2070 {
2071     struct prestera_msg_cpu_code_counter_req req = {
2072         .counter_type = counter_type,
2073         .code = code,
2074     };
2075     struct mvsw_msg_cpu_code_counter_ret resp;
2076     int err;
2077 
2078     err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET,
2079                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2080     if (err)
2081         return err;
2082 
2083     *packet_count = __le64_to_cpu(resp.packet_count);
2084 
2085     return 0;
2086 }
2087 
2088 int prestera_hw_event_handler_register(struct prestera_switch *sw,
2089                        enum prestera_event_type type,
2090                        prestera_event_cb_t fn,
2091                        void *arg)
2092 {
2093     struct prestera_fw_event_handler *eh;
2094 
2095     eh = __find_event_handler(sw, type);
2096     if (eh)
2097         return -EEXIST;
2098 
2099     eh = kmalloc(sizeof(*eh), GFP_KERNEL);
2100     if (!eh)
2101         return -ENOMEM;
2102 
2103     eh->type = type;
2104     eh->func = fn;
2105     eh->arg = arg;
2106 
2107     INIT_LIST_HEAD(&eh->list);
2108 
2109     list_add_rcu(&eh->list, &sw->event_handlers);
2110 
2111     return 0;
2112 }
2113 
2114 void prestera_hw_event_handler_unregister(struct prestera_switch *sw,
2115                       enum prestera_event_type type,
2116                       prestera_event_cb_t fn)
2117 {
2118     struct prestera_fw_event_handler *eh;
2119 
2120     eh = __find_event_handler(sw, type);
2121     if (!eh)
2122         return;
2123 
2124     list_del_rcu(&eh->list);
2125     kfree_rcu(eh, rcu);
2126 }
2127 
2128 int prestera_hw_counter_trigger(struct prestera_switch *sw, u32 block_id)
2129 {
2130     struct prestera_msg_counter_req req = {
2131         .block_id = __cpu_to_le32(block_id)
2132     };
2133 
2134     return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_TRIGGER,
2135                 &req.cmd, sizeof(req));
2136 }
2137 
2138 int prestera_hw_counter_abort(struct prestera_switch *sw)
2139 {
2140     struct prestera_msg_counter_req req;
2141 
2142     return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_ABORT,
2143                 &req.cmd, sizeof(req));
2144 }
2145 
2146 int prestera_hw_counters_get(struct prestera_switch *sw, u32 idx,
2147                  u32 *len, bool *done,
2148                  struct prestera_counter_stats *stats)
2149 {
2150     struct prestera_msg_counter_resp *resp;
2151     struct prestera_msg_counter_req req = {
2152         .block_id = __cpu_to_le32(idx),
2153         .num_counters = __cpu_to_le32(*len),
2154     };
2155     size_t size = struct_size(resp, stats, *len);
2156     int err, i;
2157 
2158     resp = kmalloc(size, GFP_KERNEL);
2159     if (!resp)
2160         return -ENOMEM;
2161 
2162     err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_GET,
2163                    &req.cmd, sizeof(req), &resp->ret, size);
2164     if (err)
2165         goto free_buff;
2166 
2167     for (i = 0; i < __le32_to_cpu(resp->num_counters); i++) {
2168         stats[i].packets += __le64_to_cpu(resp->stats[i].packets);
2169         stats[i].bytes += __le64_to_cpu(resp->stats[i].bytes);
2170     }
2171 
2172     *len = __le32_to_cpu(resp->num_counters);
2173     *done = __le32_to_cpu(resp->done);
2174 
2175 free_buff:
2176     kfree(resp);
2177     return err;
2178 }
2179 
2180 int prestera_hw_counter_block_get(struct prestera_switch *sw,
2181                   u32 client, u32 *block_id, u32 *offset,
2182                   u32 *num_counters)
2183 {
2184     struct prestera_msg_counter_resp resp;
2185     struct prestera_msg_counter_req req = {
2186         .client = __cpu_to_le32(client)
2187     };
2188     int err;
2189 
2190     err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_GET,
2191                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2192     if (err)
2193         return err;
2194 
2195     *block_id = __le32_to_cpu(resp.block_id);
2196     *offset = __le32_to_cpu(resp.offset);
2197     *num_counters = __le32_to_cpu(resp.num_counters);
2198 
2199     return 0;
2200 }
2201 
2202 int prestera_hw_counter_block_release(struct prestera_switch *sw,
2203                       u32 block_id)
2204 {
2205     struct prestera_msg_counter_req req = {
2206         .block_id = __cpu_to_le32(block_id)
2207     };
2208 
2209     return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_BLOCK_RELEASE,
2210                 &req.cmd, sizeof(req));
2211 }
2212 
2213 int prestera_hw_counter_clear(struct prestera_switch *sw, u32 block_id,
2214                   u32 counter_id)
2215 {
2216     struct prestera_msg_counter_req req = {
2217         .block_id = __cpu_to_le32(block_id),
2218         .num_counters = __cpu_to_le32(counter_id)
2219     };
2220 
2221     return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_CLEAR,
2222                 &req.cmd, sizeof(req));
2223 }
2224 
2225 int prestera_hw_policer_create(struct prestera_switch *sw, u8 type,
2226                    u32 *policer_id)
2227 {
2228     struct prestera_msg_policer_resp resp;
2229     struct prestera_msg_policer_req req = {
2230         .type = type
2231     };
2232     int err;
2233 
2234     err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_POLICER_CREATE,
2235                    &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2236     if (err)
2237         return err;
2238 
2239     *policer_id = __le32_to_cpu(resp.id);
2240     return 0;
2241 }
2242 
2243 int prestera_hw_policer_release(struct prestera_switch *sw,
2244                 u32 policer_id)
2245 {
2246     struct prestera_msg_policer_req req = {
2247         .id = __cpu_to_le32(policer_id)
2248     };
2249 
2250     return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_RELEASE,
2251                 &req.cmd, sizeof(req));
2252 }
2253 
2254 int prestera_hw_policer_sr_tcm_set(struct prestera_switch *sw,
2255                    u32 policer_id, u64 cir, u32 cbs)
2256 {
2257     struct prestera_msg_policer_req req = {
2258         .mode = PRESTERA_POLICER_MODE_SR_TCM,
2259         .id = __cpu_to_le32(policer_id),
2260         .sr_tcm = {
2261             .cir = __cpu_to_le64(cir),
2262             .cbs = __cpu_to_le32(cbs)
2263         }
2264     };
2265 
2266     return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_SET,
2267                 &req.cmd, sizeof(req));
2268 }
2269 
2270 int prestera_hw_flood_domain_create(struct prestera_flood_domain *domain)
2271 {
2272     struct prestera_msg_flood_domain_create_resp resp;
2273     struct prestera_msg_flood_domain_create_req req;
2274     int err;
2275 
2276     err = prestera_cmd_ret(domain->sw,
2277                    PRESTERA_CMD_TYPE_FLOOD_DOMAIN_CREATE, &req.cmd,
2278                    sizeof(req), &resp.ret, sizeof(resp));
2279     if (err)
2280         return err;
2281 
2282     domain->idx = __le32_to_cpu(resp.flood_domain_idx);
2283 
2284     return 0;
2285 }
2286 
2287 int prestera_hw_flood_domain_destroy(struct prestera_flood_domain *domain)
2288 {
2289     struct prestera_msg_flood_domain_destroy_req req = {
2290         .flood_domain_idx = __cpu_to_le32(domain->idx),
2291     };
2292 
2293     return prestera_cmd(domain->sw, PRESTERA_CMD_TYPE_FLOOD_DOMAIN_DESTROY,
2294                &req.cmd, sizeof(req));
2295 }
2296 
2297 int prestera_hw_flood_domain_ports_set(struct prestera_flood_domain *domain)
2298 {
2299     struct prestera_flood_domain_port *flood_domain_port;
2300     struct prestera_msg_flood_domain_ports_set_req *req;
2301     struct prestera_msg_flood_domain_port *ports;
2302     struct prestera_switch *sw = domain->sw;
2303     struct prestera_port *port;
2304     u32 ports_num = 0;
2305     int buf_size;
2306     void *buff;
2307     u16 lag_id;
2308     int err;
2309 
2310     list_for_each_entry(flood_domain_port, &domain->flood_domain_port_list,
2311                 flood_domain_port_node)
2312         ports_num++;
2313 
2314     if (!ports_num)
2315         return -EINVAL;
2316 
2317     buf_size = sizeof(*req) + sizeof(*ports) * ports_num;
2318 
2319     buff = kmalloc(buf_size, GFP_KERNEL);
2320     if (!buff)
2321         return -ENOMEM;
2322 
2323     req = buff;
2324     ports = buff + sizeof(*req);
2325 
2326     req->flood_domain_idx = __cpu_to_le32(domain->idx);
2327     req->ports_num = __cpu_to_le32(ports_num);
2328 
2329     list_for_each_entry(flood_domain_port, &domain->flood_domain_port_list,
2330                 flood_domain_port_node) {
2331         if (netif_is_lag_master(flood_domain_port->dev)) {
2332             if (prestera_lag_id(sw, flood_domain_port->dev,
2333                         &lag_id)) {
2334                 kfree(buff);
2335                 return -EINVAL;
2336             }
2337 
2338             ports->port_type =
2339                 __cpu_to_le16(PRESTERA_HW_FLOOD_DOMAIN_PORT_TYPE_LAG);
2340             ports->lag_id = __cpu_to_le16(lag_id);
2341         } else {
2342             port = prestera_port_dev_lower_find(flood_domain_port->dev);
2343 
2344             ports->port_type =
2345                 __cpu_to_le16(PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT);
2346             ports->dev_num = __cpu_to_le32(port->dev_id);
2347             ports->port_num = __cpu_to_le32(port->hw_id);
2348         }
2349 
2350         ports->vid = __cpu_to_le16(flood_domain_port->vid);
2351 
2352         ports++;
2353     }
2354 
2355     err = prestera_cmd(sw, PRESTERA_CMD_TYPE_FLOOD_DOMAIN_PORTS_SET,
2356                &req->cmd, buf_size);
2357 
2358     kfree(buff);
2359 
2360     return err;
2361 }
2362 
2363 int prestera_hw_flood_domain_ports_reset(struct prestera_flood_domain *domain)
2364 {
2365     struct prestera_msg_flood_domain_ports_reset_req req = {
2366         .flood_domain_idx = __cpu_to_le32(domain->idx),
2367     };
2368 
2369     return prestera_cmd(domain->sw,
2370                PRESTERA_CMD_TYPE_FLOOD_DOMAIN_PORTS_RESET, &req.cmd,
2371                sizeof(req));
2372 }
2373 
2374 int prestera_hw_mdb_create(struct prestera_mdb_entry *mdb)
2375 {
2376     struct prestera_msg_mdb_create_req req = {
2377         .flood_domain_idx = __cpu_to_le32(mdb->flood_domain->idx),
2378         .vid = __cpu_to_le16(mdb->vid),
2379     };
2380 
2381     memcpy(req.mac, mdb->addr, ETH_ALEN);
2382 
2383     return prestera_cmd(mdb->sw, PRESTERA_CMD_TYPE_MDB_CREATE, &req.cmd,
2384                 sizeof(req));
2385 }
2386 
2387 int prestera_hw_mdb_destroy(struct prestera_mdb_entry *mdb)
2388 {
2389     struct prestera_msg_mdb_destroy_req req = {
2390         .flood_domain_idx = __cpu_to_le32(mdb->flood_domain->idx),
2391         .vid = __cpu_to_le16(mdb->vid),
2392     };
2393 
2394     memcpy(req.mac, mdb->addr, ETH_ALEN);
2395 
2396     return prestera_cmd(mdb->sw, PRESTERA_CMD_TYPE_MDB_DESTROY, &req.cmd,
2397                 sizeof(req));
2398 }