0001
0002
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;
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;
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;
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
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
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
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
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
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
1337 memcpy(req->key, key, sizeof(req->key));
1338 memcpy(req->keymask, keymask, sizeof(req->keymask));
1339
1340
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 }