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