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