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