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