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