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 12 #define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000) 13 14 #define PRESTERA_MIN_MTU 64 15 16 enum prestera_cmd_type_t { 17 PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1, 18 PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2, 19 20 PRESTERA_CMD_TYPE_PORT_ATTR_SET = 0x100, 21 PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101, 22 PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110, 23 24 PRESTERA_CMD_TYPE_VLAN_CREATE = 0x200, 25 PRESTERA_CMD_TYPE_VLAN_DELETE = 0x201, 26 PRESTERA_CMD_TYPE_VLAN_PORT_SET = 0x202, 27 PRESTERA_CMD_TYPE_VLAN_PVID_SET = 0x203, 28 29 PRESTERA_CMD_TYPE_FDB_ADD = 0x300, 30 PRESTERA_CMD_TYPE_FDB_DELETE = 0x301, 31 PRESTERA_CMD_TYPE_FDB_FLUSH_PORT = 0x310, 32 PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN = 0x311, 33 PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN = 0x312, 34 35 PRESTERA_CMD_TYPE_BRIDGE_CREATE = 0x400, 36 PRESTERA_CMD_TYPE_BRIDGE_DELETE = 0x401, 37 PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD = 0x402, 38 PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE = 0x403, 39 40 PRESTERA_CMD_TYPE_RXTX_INIT = 0x800, 41 PRESTERA_CMD_TYPE_RXTX_PORT_INIT = 0x801, 42 43 PRESTERA_CMD_TYPE_LAG_MEMBER_ADD = 0x900, 44 PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE = 0x901, 45 PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE = 0x902, 46 PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE = 0x903, 47 48 PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000, 49 50 PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET = 0x2000, 51 52 PRESTERA_CMD_TYPE_ACK = 0x10000, 53 PRESTERA_CMD_TYPE_MAX 54 }; 55 56 enum { 57 PRESTERA_CMD_PORT_ATTR_ADMIN_STATE = 1, 58 PRESTERA_CMD_PORT_ATTR_MTU = 3, 59 PRESTERA_CMD_PORT_ATTR_MAC = 4, 60 PRESTERA_CMD_PORT_ATTR_SPEED = 5, 61 PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6, 62 PRESTERA_CMD_PORT_ATTR_LEARNING = 7, 63 PRESTERA_CMD_PORT_ATTR_FLOOD = 8, 64 PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9, 65 PRESTERA_CMD_PORT_ATTR_REMOTE_CAPABILITY = 10, 66 PRESTERA_CMD_PORT_ATTR_REMOTE_FC = 11, 67 PRESTERA_CMD_PORT_ATTR_LINK_MODE = 12, 68 PRESTERA_CMD_PORT_ATTR_TYPE = 13, 69 PRESTERA_CMD_PORT_ATTR_FEC = 14, 70 PRESTERA_CMD_PORT_ATTR_AUTONEG = 15, 71 PRESTERA_CMD_PORT_ATTR_DUPLEX = 16, 72 PRESTERA_CMD_PORT_ATTR_STATS = 17, 73 PRESTERA_CMD_PORT_ATTR_MDIX = 18, 74 PRESTERA_CMD_PORT_ATTR_AUTONEG_RESTART = 19, 75 }; 76 77 enum { 78 PRESTERA_CMD_SWITCH_ATTR_MAC = 1, 79 PRESTERA_CMD_SWITCH_ATTR_AGEING = 2, 80 }; 81 82 enum { 83 PRESTERA_CMD_ACK_OK, 84 PRESTERA_CMD_ACK_FAILED, 85 86 PRESTERA_CMD_ACK_MAX 87 }; 88 89 enum { 90 PRESTERA_PORT_TP_NA, 91 PRESTERA_PORT_TP_MDI, 92 PRESTERA_PORT_TP_MDIX, 93 PRESTERA_PORT_TP_AUTO, 94 }; 95 96 enum { 97 PRESTERA_PORT_FLOOD_TYPE_UC = 0, 98 PRESTERA_PORT_FLOOD_TYPE_MC = 1, 99 }; 100 101 enum { 102 PRESTERA_PORT_GOOD_OCTETS_RCV_CNT, 103 PRESTERA_PORT_BAD_OCTETS_RCV_CNT, 104 PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT, 105 PRESTERA_PORT_BRDC_PKTS_RCV_CNT, 106 PRESTERA_PORT_MC_PKTS_RCV_CNT, 107 PRESTERA_PORT_PKTS_64L_CNT, 108 PRESTERA_PORT_PKTS_65TO127L_CNT, 109 PRESTERA_PORT_PKTS_128TO255L_CNT, 110 PRESTERA_PORT_PKTS_256TO511L_CNT, 111 PRESTERA_PORT_PKTS_512TO1023L_CNT, 112 PRESTERA_PORT_PKTS_1024TOMAXL_CNT, 113 PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT, 114 PRESTERA_PORT_MC_PKTS_SENT_CNT, 115 PRESTERA_PORT_BRDC_PKTS_SENT_CNT, 116 PRESTERA_PORT_FC_SENT_CNT, 117 PRESTERA_PORT_GOOD_FC_RCV_CNT, 118 PRESTERA_PORT_DROP_EVENTS_CNT, 119 PRESTERA_PORT_UNDERSIZE_PKTS_CNT, 120 PRESTERA_PORT_FRAGMENTS_PKTS_CNT, 121 PRESTERA_PORT_OVERSIZE_PKTS_CNT, 122 PRESTERA_PORT_JABBER_PKTS_CNT, 123 PRESTERA_PORT_MAC_RCV_ERROR_CNT, 124 PRESTERA_PORT_BAD_CRC_CNT, 125 PRESTERA_PORT_COLLISIONS_CNT, 126 PRESTERA_PORT_LATE_COLLISIONS_CNT, 127 PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT, 128 PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT, 129 PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT, 130 PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT, 131 PRESTERA_PORT_GOOD_OCTETS_SENT_CNT, 132 133 PRESTERA_PORT_CNT_MAX 134 }; 135 136 enum { 137 PRESTERA_FC_NONE, 138 PRESTERA_FC_SYMMETRIC, 139 PRESTERA_FC_ASYMMETRIC, 140 PRESTERA_FC_SYMM_ASYMM, 141 }; 142 143 enum { 144 PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT = 0, 145 PRESTERA_HW_FDB_ENTRY_TYPE_LAG = 1, 146 PRESTERA_HW_FDB_ENTRY_TYPE_MAX = 2, 147 }; 148 149 struct prestera_fw_event_handler { 150 struct list_head list; 151 struct rcu_head rcu; 152 enum prestera_event_type type; 153 prestera_event_cb_t func; 154 void *arg; 155 }; 156 157 struct prestera_msg_cmd { 158 u32 type; 159 }; 160 161 struct prestera_msg_ret { 162 struct prestera_msg_cmd cmd; 163 u32 status; 164 }; 165 166 struct prestera_msg_common_req { 167 struct prestera_msg_cmd cmd; 168 }; 169 170 struct prestera_msg_common_resp { 171 struct prestera_msg_ret ret; 172 }; 173 174 union prestera_msg_switch_param { 175 u8 mac[ETH_ALEN]; 176 u32 ageing_timeout_ms; 177 }; 178 179 struct prestera_msg_switch_attr_req { 180 struct prestera_msg_cmd cmd; 181 u32 attr; 182 union prestera_msg_switch_param param; 183 }; 184 185 struct prestera_msg_switch_init_resp { 186 struct prestera_msg_ret ret; 187 u32 port_count; 188 u32 mtu_max; 189 u8 switch_id; 190 u8 lag_max; 191 u8 lag_member_max; 192 }; 193 194 struct prestera_msg_port_autoneg_param { 195 u64 link_mode; 196 u8 enable; 197 u8 fec; 198 }; 199 200 struct prestera_msg_port_cap_param { 201 u64 link_mode; 202 u8 type; 203 u8 fec; 204 u8 transceiver; 205 }; 206 207 struct prestera_msg_port_mdix_param { 208 u8 status; 209 u8 admin_mode; 210 }; 211 212 struct prestera_msg_port_flood_param { 213 u8 type; 214 u8 enable; 215 }; 216 217 union prestera_msg_port_param { 218 u8 admin_state; 219 u8 oper_state; 220 u32 mtu; 221 u8 mac[ETH_ALEN]; 222 u8 accept_frm_type; 223 u32 speed; 224 u8 learning; 225 u8 flood; 226 u32 link_mode; 227 u8 type; 228 u8 duplex; 229 u8 fec; 230 u8 fc; 231 struct prestera_msg_port_mdix_param mdix; 232 struct prestera_msg_port_autoneg_param autoneg; 233 struct prestera_msg_port_cap_param cap; 234 struct prestera_msg_port_flood_param flood_ext; 235 }; 236 237 struct prestera_msg_port_attr_req { 238 struct prestera_msg_cmd cmd; 239 u32 attr; 240 u32 port; 241 u32 dev; 242 union prestera_msg_port_param param; 243 }; 244 245 struct prestera_msg_port_attr_resp { 246 struct prestera_msg_ret ret; 247 union prestera_msg_port_param param; 248 }; 249 250 struct prestera_msg_port_stats_resp { 251 struct prestera_msg_ret ret; 252 u64 stats[PRESTERA_PORT_CNT_MAX]; 253 }; 254 255 struct prestera_msg_port_info_req { 256 struct prestera_msg_cmd cmd; 257 u32 port; 258 }; 259 260 struct prestera_msg_port_info_resp { 261 struct prestera_msg_ret ret; 262 u32 hw_id; 263 u32 dev_id; 264 u16 fp_id; 265 }; 266 267 struct prestera_msg_vlan_req { 268 struct prestera_msg_cmd cmd; 269 u32 port; 270 u32 dev; 271 u16 vid; 272 u8 is_member; 273 u8 is_tagged; 274 }; 275 276 struct prestera_msg_fdb_req { 277 struct prestera_msg_cmd cmd; 278 u8 dest_type; 279 union { 280 struct { 281 u32 port; 282 u32 dev; 283 }; 284 u16 lag_id; 285 } dest; 286 u8 mac[ETH_ALEN]; 287 u16 vid; 288 u8 dynamic; 289 u32 flush_mode; 290 }; 291 292 struct prestera_msg_bridge_req { 293 struct prestera_msg_cmd cmd; 294 u32 port; 295 u32 dev; 296 u16 bridge; 297 }; 298 299 struct prestera_msg_bridge_resp { 300 struct prestera_msg_ret ret; 301 u16 bridge; 302 }; 303 304 struct prestera_msg_stp_req { 305 struct prestera_msg_cmd cmd; 306 u32 port; 307 u32 dev; 308 u16 vid; 309 u8 state; 310 }; 311 312 struct prestera_msg_rxtx_req { 313 struct prestera_msg_cmd cmd; 314 u8 use_sdma; 315 }; 316 317 struct prestera_msg_rxtx_resp { 318 struct prestera_msg_ret ret; 319 u32 map_addr; 320 }; 321 322 struct prestera_msg_rxtx_port_req { 323 struct prestera_msg_cmd cmd; 324 u32 port; 325 u32 dev; 326 }; 327 328 struct prestera_msg_lag_req { 329 struct prestera_msg_cmd cmd; 330 u32 port; 331 u32 dev; 332 u16 lag_id; 333 }; 334 335 struct prestera_msg_cpu_code_counter_req { 336 struct prestera_msg_cmd cmd; 337 u8 counter_type; 338 u8 code; 339 }; 340 341 struct mvsw_msg_cpu_code_counter_ret { 342 struct prestera_msg_ret ret; 343 u64 packet_count; 344 }; 345 346 struct prestera_msg_event { 347 u16 type; 348 u16 id; 349 }; 350 351 union prestera_msg_event_port_param { 352 u32 oper_state; 353 }; 354 355 struct prestera_msg_event_port { 356 struct prestera_msg_event id; 357 u32 port_id; 358 union prestera_msg_event_port_param param; 359 }; 360 361 union prestera_msg_event_fdb_param { 362 u8 mac[ETH_ALEN]; 363 }; 364 365 struct prestera_msg_event_fdb { 366 struct prestera_msg_event id; 367 u8 dest_type; 368 union { 369 u32 port_id; 370 u16 lag_id; 371 } dest; 372 u32 vid; 373 union prestera_msg_event_fdb_param param; 374 }; 375 376 static int __prestera_cmd_ret(struct prestera_switch *sw, 377 enum prestera_cmd_type_t type, 378 struct prestera_msg_cmd *cmd, size_t clen, 379 struct prestera_msg_ret *ret, size_t rlen, 380 int waitms) 381 { 382 struct prestera_device *dev = sw->dev; 383 int err; 384 385 cmd->type = type; 386 387 err = dev->send_req(dev, cmd, clen, ret, rlen, waitms); 388 if (err) 389 return err; 390 391 if (ret->cmd.type != PRESTERA_CMD_TYPE_ACK) 392 return -EBADE; 393 if (ret->status != PRESTERA_CMD_ACK_OK) 394 return -EINVAL; 395 396 return 0; 397 } 398 399 static int prestera_cmd_ret(struct prestera_switch *sw, 400 enum prestera_cmd_type_t type, 401 struct prestera_msg_cmd *cmd, size_t clen, 402 struct prestera_msg_ret *ret, size_t rlen) 403 { 404 return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0); 405 } 406 407 static int prestera_cmd_ret_wait(struct prestera_switch *sw, 408 enum prestera_cmd_type_t type, 409 struct prestera_msg_cmd *cmd, size_t clen, 410 struct prestera_msg_ret *ret, size_t rlen, 411 int waitms) 412 { 413 return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms); 414 } 415 416 static int prestera_cmd(struct prestera_switch *sw, 417 enum prestera_cmd_type_t type, 418 struct prestera_msg_cmd *cmd, size_t clen) 419 { 420 struct prestera_msg_common_resp resp; 421 422 return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp)); 423 } 424 425 static int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt) 426 { 427 struct prestera_msg_event_port *hw_evt = msg; 428 429 if (evt->id != PRESTERA_PORT_EVENT_STATE_CHANGED) 430 return -EINVAL; 431 432 evt->port_evt.data.oper_state = hw_evt->param.oper_state; 433 evt->port_evt.port_id = hw_evt->port_id; 434 435 return 0; 436 } 437 438 static int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt) 439 { 440 struct prestera_msg_event_fdb *hw_evt = msg; 441 442 switch (hw_evt->dest_type) { 443 case PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT: 444 evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_REG_PORT; 445 evt->fdb_evt.dest.port_id = hw_evt->dest.port_id; 446 break; 447 case PRESTERA_HW_FDB_ENTRY_TYPE_LAG: 448 evt->fdb_evt.type = PRESTERA_FDB_ENTRY_TYPE_LAG; 449 evt->fdb_evt.dest.lag_id = hw_evt->dest.lag_id; 450 break; 451 default: 452 return -EINVAL; 453 } 454 455 evt->fdb_evt.vid = hw_evt->vid; 456 457 ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac); 458 459 return 0; 460 } 461 462 static struct prestera_fw_evt_parser { 463 int (*func)(void *msg, struct prestera_event *evt); 464 } fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = { 465 [PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt }, 466 [PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt }, 467 }; 468 469 static struct prestera_fw_event_handler * 470 __find_event_handler(const struct prestera_switch *sw, 471 enum prestera_event_type type) 472 { 473 struct prestera_fw_event_handler *eh; 474 475 list_for_each_entry_rcu(eh, &sw->event_handlers, list) { 476 if (eh->type == type) 477 return eh; 478 } 479 480 return NULL; 481 } 482 483 static int prestera_find_event_handler(const struct prestera_switch *sw, 484 enum prestera_event_type type, 485 struct prestera_fw_event_handler *eh) 486 { 487 struct prestera_fw_event_handler *tmp; 488 int err = 0; 489 490 rcu_read_lock(); 491 tmp = __find_event_handler(sw, type); 492 if (tmp) 493 *eh = *tmp; 494 else 495 err = -ENOENT; 496 rcu_read_unlock(); 497 498 return err; 499 } 500 501 static int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size) 502 { 503 struct prestera_switch *sw = dev->priv; 504 struct prestera_msg_event *msg = buf; 505 struct prestera_fw_event_handler eh; 506 struct prestera_event evt; 507 int err; 508 509 if (msg->type >= PRESTERA_EVENT_TYPE_MAX) 510 return -EINVAL; 511 if (!fw_event_parsers[msg->type].func) 512 return -ENOENT; 513 514 err = prestera_find_event_handler(sw, msg->type, &eh); 515 if (err) 516 return err; 517 518 evt.id = msg->id; 519 520 err = fw_event_parsers[msg->type].func(buf, &evt); 521 if (err) 522 return err; 523 524 eh.func(sw, &evt, eh.arg); 525 526 return 0; 527 } 528 529 static void prestera_pkt_recv(struct prestera_device *dev) 530 { 531 struct prestera_switch *sw = dev->priv; 532 struct prestera_fw_event_handler eh; 533 struct prestera_event ev; 534 int err; 535 536 ev.id = PRESTERA_RXTX_EVENT_RCV_PKT; 537 538 err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh); 539 if (err) 540 return; 541 542 eh.func(sw, &ev, eh.arg); 543 } 544 545 int prestera_hw_port_info_get(const struct prestera_port *port, 546 u32 *dev_id, u32 *hw_id, u16 *fp_id) 547 { 548 struct prestera_msg_port_info_req req = { 549 .port = port->id, 550 }; 551 struct prestera_msg_port_info_resp resp; 552 int err; 553 554 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET, 555 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 556 if (err) 557 return err; 558 559 *dev_id = resp.dev_id; 560 *hw_id = resp.hw_id; 561 *fp_id = resp.fp_id; 562 563 return 0; 564 } 565 566 int prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac) 567 { 568 struct prestera_msg_switch_attr_req req = { 569 .attr = PRESTERA_CMD_SWITCH_ATTR_MAC, 570 }; 571 572 ether_addr_copy(req.param.mac, mac); 573 574 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET, 575 &req.cmd, sizeof(req)); 576 } 577 578 int prestera_hw_switch_init(struct prestera_switch *sw) 579 { 580 struct prestera_msg_switch_init_resp resp; 581 struct prestera_msg_common_req req; 582 int err; 583 584 INIT_LIST_HEAD(&sw->event_handlers); 585 586 err = prestera_cmd_ret_wait(sw, PRESTERA_CMD_TYPE_SWITCH_INIT, 587 &req.cmd, sizeof(req), 588 &resp.ret, sizeof(resp), 589 PRESTERA_SWITCH_INIT_TIMEOUT_MS); 590 if (err) 591 return err; 592 593 sw->dev->recv_msg = prestera_evt_recv; 594 sw->dev->recv_pkt = prestera_pkt_recv; 595 sw->port_count = resp.port_count; 596 sw->mtu_min = PRESTERA_MIN_MTU; 597 sw->mtu_max = resp.mtu_max; 598 sw->id = resp.switch_id; 599 sw->lag_member_max = resp.lag_member_max; 600 sw->lag_max = resp.lag_max; 601 602 return 0; 603 } 604 605 void prestera_hw_switch_fini(struct prestera_switch *sw) 606 { 607 WARN_ON(!list_empty(&sw->event_handlers)); 608 } 609 610 int prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms) 611 { 612 struct prestera_msg_switch_attr_req req = { 613 .attr = PRESTERA_CMD_SWITCH_ATTR_AGEING, 614 .param = { 615 .ageing_timeout_ms = ageing_ms, 616 }, 617 }; 618 619 return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET, 620 &req.cmd, sizeof(req)); 621 } 622 623 int prestera_hw_port_state_set(const struct prestera_port *port, 624 bool admin_state) 625 { 626 struct prestera_msg_port_attr_req req = { 627 .attr = PRESTERA_CMD_PORT_ATTR_ADMIN_STATE, 628 .port = port->hw_id, 629 .dev = port->dev_id, 630 .param = { 631 .admin_state = admin_state, 632 } 633 }; 634 635 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 636 &req.cmd, sizeof(req)); 637 } 638 639 int prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu) 640 { 641 struct prestera_msg_port_attr_req req = { 642 .attr = PRESTERA_CMD_PORT_ATTR_MTU, 643 .port = port->hw_id, 644 .dev = port->dev_id, 645 .param = { 646 .mtu = mtu, 647 } 648 }; 649 650 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 651 &req.cmd, sizeof(req)); 652 } 653 654 int prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac) 655 { 656 struct prestera_msg_port_attr_req req = { 657 .attr = PRESTERA_CMD_PORT_ATTR_MAC, 658 .port = port->hw_id, 659 .dev = port->dev_id, 660 }; 661 662 ether_addr_copy(req.param.mac, mac); 663 664 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 665 &req.cmd, sizeof(req)); 666 } 667 668 int prestera_hw_port_accept_frm_type(struct prestera_port *port, 669 enum prestera_accept_frm_type type) 670 { 671 struct prestera_msg_port_attr_req req = { 672 .attr = PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE, 673 .port = port->hw_id, 674 .dev = port->dev_id, 675 .param = { 676 .accept_frm_type = type, 677 } 678 }; 679 680 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 681 &req.cmd, sizeof(req)); 682 } 683 684 int prestera_hw_port_cap_get(const struct prestera_port *port, 685 struct prestera_port_caps *caps) 686 { 687 struct prestera_msg_port_attr_req req = { 688 .attr = PRESTERA_CMD_PORT_ATTR_CAPABILITY, 689 .port = port->hw_id, 690 .dev = port->dev_id, 691 }; 692 struct prestera_msg_port_attr_resp resp; 693 int err; 694 695 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET, 696 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 697 if (err) 698 return err; 699 700 caps->supp_link_modes = resp.param.cap.link_mode; 701 caps->transceiver = resp.param.cap.transceiver; 702 caps->supp_fec = resp.param.cap.fec; 703 caps->type = resp.param.cap.type; 704 705 return err; 706 } 707 708 int prestera_hw_port_remote_cap_get(const struct prestera_port *port, 709 u64 *link_mode_bitmap) 710 { 711 struct prestera_msg_port_attr_req req = { 712 .attr = PRESTERA_CMD_PORT_ATTR_REMOTE_CAPABILITY, 713 .port = port->hw_id, 714 .dev = port->dev_id, 715 }; 716 struct prestera_msg_port_attr_resp resp; 717 int err; 718 719 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET, 720 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 721 if (err) 722 return err; 723 724 *link_mode_bitmap = resp.param.cap.link_mode; 725 726 return 0; 727 } 728 729 int prestera_hw_port_remote_fc_get(const struct prestera_port *port, 730 bool *pause, bool *asym_pause) 731 { 732 struct prestera_msg_port_attr_req req = { 733 .attr = PRESTERA_CMD_PORT_ATTR_REMOTE_FC, 734 .port = port->hw_id, 735 .dev = port->dev_id, 736 }; 737 struct prestera_msg_port_attr_resp resp; 738 int err; 739 740 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET, 741 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 742 if (err) 743 return err; 744 745 switch (resp.param.fc) { 746 case PRESTERA_FC_SYMMETRIC: 747 *pause = true; 748 *asym_pause = false; 749 break; 750 case PRESTERA_FC_ASYMMETRIC: 751 *pause = false; 752 *asym_pause = true; 753 break; 754 case PRESTERA_FC_SYMM_ASYMM: 755 *pause = true; 756 *asym_pause = true; 757 break; 758 default: 759 *pause = false; 760 *asym_pause = false; 761 } 762 763 return 0; 764 } 765 766 int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type) 767 { 768 struct prestera_msg_port_attr_req req = { 769 .attr = PRESTERA_CMD_PORT_ATTR_TYPE, 770 .port = port->hw_id, 771 .dev = port->dev_id, 772 }; 773 struct prestera_msg_port_attr_resp resp; 774 int err; 775 776 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET, 777 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 778 if (err) 779 return err; 780 781 *type = resp.param.type; 782 783 return 0; 784 } 785 786 int prestera_hw_port_fec_get(const struct prestera_port *port, u8 *fec) 787 { 788 struct prestera_msg_port_attr_req req = { 789 .attr = PRESTERA_CMD_PORT_ATTR_FEC, 790 .port = port->hw_id, 791 .dev = port->dev_id, 792 }; 793 struct prestera_msg_port_attr_resp resp; 794 int err; 795 796 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET, 797 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 798 if (err) 799 return err; 800 801 *fec = resp.param.fec; 802 803 return 0; 804 } 805 806 int prestera_hw_port_fec_set(const struct prestera_port *port, u8 fec) 807 { 808 struct prestera_msg_port_attr_req req = { 809 .attr = PRESTERA_CMD_PORT_ATTR_FEC, 810 .port = port->hw_id, 811 .dev = port->dev_id, 812 .param = { 813 .fec = fec, 814 } 815 }; 816 817 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 818 &req.cmd, sizeof(req)); 819 } 820 821 static u8 prestera_hw_mdix_to_eth(u8 mode) 822 { 823 switch (mode) { 824 case PRESTERA_PORT_TP_MDI: 825 return ETH_TP_MDI; 826 case PRESTERA_PORT_TP_MDIX: 827 return ETH_TP_MDI_X; 828 case PRESTERA_PORT_TP_AUTO: 829 return ETH_TP_MDI_AUTO; 830 default: 831 return ETH_TP_MDI_INVALID; 832 } 833 } 834 835 static u8 prestera_hw_mdix_from_eth(u8 mode) 836 { 837 switch (mode) { 838 case ETH_TP_MDI: 839 return PRESTERA_PORT_TP_MDI; 840 case ETH_TP_MDI_X: 841 return PRESTERA_PORT_TP_MDIX; 842 case ETH_TP_MDI_AUTO: 843 return PRESTERA_PORT_TP_AUTO; 844 default: 845 return PRESTERA_PORT_TP_NA; 846 } 847 } 848 849 int prestera_hw_port_mdix_get(const struct prestera_port *port, u8 *status, 850 u8 *admin_mode) 851 { 852 struct prestera_msg_port_attr_req req = { 853 .attr = PRESTERA_CMD_PORT_ATTR_MDIX, 854 .port = port->hw_id, 855 .dev = port->dev_id, 856 }; 857 struct prestera_msg_port_attr_resp resp; 858 int err; 859 860 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET, 861 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 862 if (err) 863 return err; 864 865 *status = prestera_hw_mdix_to_eth(resp.param.mdix.status); 866 *admin_mode = prestera_hw_mdix_to_eth(resp.param.mdix.admin_mode); 867 868 return 0; 869 } 870 871 int prestera_hw_port_mdix_set(const struct prestera_port *port, u8 mode) 872 { 873 struct prestera_msg_port_attr_req req = { 874 .attr = PRESTERA_CMD_PORT_ATTR_MDIX, 875 .port = port->hw_id, 876 .dev = port->dev_id, 877 }; 878 879 req.param.mdix.admin_mode = prestera_hw_mdix_from_eth(mode); 880 881 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 882 &req.cmd, sizeof(req)); 883 } 884 885 int prestera_hw_port_link_mode_set(const struct prestera_port *port, u32 mode) 886 { 887 struct prestera_msg_port_attr_req req = { 888 .attr = PRESTERA_CMD_PORT_ATTR_LINK_MODE, 889 .port = port->hw_id, 890 .dev = port->dev_id, 891 .param = { 892 .link_mode = mode, 893 } 894 }; 895 896 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 897 &req.cmd, sizeof(req)); 898 } 899 900 int prestera_hw_port_link_mode_get(const struct prestera_port *port, u32 *mode) 901 { 902 struct prestera_msg_port_attr_req req = { 903 .attr = PRESTERA_CMD_PORT_ATTR_LINK_MODE, 904 .port = port->hw_id, 905 .dev = port->dev_id, 906 }; 907 struct prestera_msg_port_attr_resp resp; 908 int err; 909 910 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET, 911 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 912 if (err) 913 return err; 914 915 *mode = resp.param.link_mode; 916 917 return 0; 918 } 919 920 int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed) 921 { 922 struct prestera_msg_port_attr_req req = { 923 .attr = PRESTERA_CMD_PORT_ATTR_SPEED, 924 .port = port->hw_id, 925 .dev = port->dev_id, 926 }; 927 struct prestera_msg_port_attr_resp resp; 928 int err; 929 930 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET, 931 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 932 if (err) 933 return err; 934 935 *speed = resp.param.speed; 936 937 return 0; 938 } 939 940 int prestera_hw_port_autoneg_set(const struct prestera_port *port, 941 bool autoneg, u64 link_modes, u8 fec) 942 { 943 struct prestera_msg_port_attr_req req = { 944 .attr = PRESTERA_CMD_PORT_ATTR_AUTONEG, 945 .port = port->hw_id, 946 .dev = port->dev_id, 947 .param = { 948 .autoneg = { 949 .link_mode = link_modes, 950 .enable = autoneg, 951 .fec = fec, 952 } 953 } 954 }; 955 956 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 957 &req.cmd, sizeof(req)); 958 } 959 960 int prestera_hw_port_autoneg_restart(struct prestera_port *port) 961 { 962 struct prestera_msg_port_attr_req req = { 963 .attr = PRESTERA_CMD_PORT_ATTR_AUTONEG_RESTART, 964 .port = port->hw_id, 965 .dev = port->dev_id, 966 }; 967 968 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 969 &req.cmd, sizeof(req)); 970 } 971 972 int prestera_hw_port_duplex_get(const struct prestera_port *port, u8 *duplex) 973 { 974 struct prestera_msg_port_attr_req req = { 975 .attr = PRESTERA_CMD_PORT_ATTR_DUPLEX, 976 .port = port->hw_id, 977 .dev = port->dev_id, 978 }; 979 struct prestera_msg_port_attr_resp resp; 980 int err; 981 982 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET, 983 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 984 if (err) 985 return err; 986 987 *duplex = resp.param.duplex; 988 989 return 0; 990 } 991 992 int prestera_hw_port_stats_get(const struct prestera_port *port, 993 struct prestera_port_stats *st) 994 { 995 struct prestera_msg_port_attr_req req = { 996 .attr = PRESTERA_CMD_PORT_ATTR_STATS, 997 .port = port->hw_id, 998 .dev = port->dev_id, 999 }; 1000 struct prestera_msg_port_stats_resp resp; 1001 u64 *hw = resp.stats; 1002 int err; 1003 1004 err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET, 1005 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 1006 if (err) 1007 return err; 1008 1009 st->good_octets_received = hw[PRESTERA_PORT_GOOD_OCTETS_RCV_CNT]; 1010 st->bad_octets_received = hw[PRESTERA_PORT_BAD_OCTETS_RCV_CNT]; 1011 st->mac_trans_error = hw[PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT]; 1012 st->broadcast_frames_received = hw[PRESTERA_PORT_BRDC_PKTS_RCV_CNT]; 1013 st->multicast_frames_received = hw[PRESTERA_PORT_MC_PKTS_RCV_CNT]; 1014 st->frames_64_octets = hw[PRESTERA_PORT_PKTS_64L_CNT]; 1015 st->frames_65_to_127_octets = hw[PRESTERA_PORT_PKTS_65TO127L_CNT]; 1016 st->frames_128_to_255_octets = hw[PRESTERA_PORT_PKTS_128TO255L_CNT]; 1017 st->frames_256_to_511_octets = hw[PRESTERA_PORT_PKTS_256TO511L_CNT]; 1018 st->frames_512_to_1023_octets = hw[PRESTERA_PORT_PKTS_512TO1023L_CNT]; 1019 st->frames_1024_to_max_octets = hw[PRESTERA_PORT_PKTS_1024TOMAXL_CNT]; 1020 st->excessive_collision = hw[PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT]; 1021 st->multicast_frames_sent = hw[PRESTERA_PORT_MC_PKTS_SENT_CNT]; 1022 st->broadcast_frames_sent = hw[PRESTERA_PORT_BRDC_PKTS_SENT_CNT]; 1023 st->fc_sent = hw[PRESTERA_PORT_FC_SENT_CNT]; 1024 st->fc_received = hw[PRESTERA_PORT_GOOD_FC_RCV_CNT]; 1025 st->buffer_overrun = hw[PRESTERA_PORT_DROP_EVENTS_CNT]; 1026 st->undersize = hw[PRESTERA_PORT_UNDERSIZE_PKTS_CNT]; 1027 st->fragments = hw[PRESTERA_PORT_FRAGMENTS_PKTS_CNT]; 1028 st->oversize = hw[PRESTERA_PORT_OVERSIZE_PKTS_CNT]; 1029 st->jabber = hw[PRESTERA_PORT_JABBER_PKTS_CNT]; 1030 st->rx_error_frame_received = hw[PRESTERA_PORT_MAC_RCV_ERROR_CNT]; 1031 st->bad_crc = hw[PRESTERA_PORT_BAD_CRC_CNT]; 1032 st->collisions = hw[PRESTERA_PORT_COLLISIONS_CNT]; 1033 st->late_collision = hw[PRESTERA_PORT_LATE_COLLISIONS_CNT]; 1034 st->unicast_frames_received = hw[PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT]; 1035 st->unicast_frames_sent = hw[PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT]; 1036 st->sent_multiple = hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT]; 1037 st->sent_deferred = hw[PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT]; 1038 st->good_octets_sent = hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT]; 1039 1040 return 0; 1041 } 1042 1043 int prestera_hw_port_learning_set(struct prestera_port *port, bool enable) 1044 { 1045 struct prestera_msg_port_attr_req req = { 1046 .attr = PRESTERA_CMD_PORT_ATTR_LEARNING, 1047 .port = port->hw_id, 1048 .dev = port->dev_id, 1049 .param = { 1050 .learning = enable, 1051 } 1052 }; 1053 1054 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 1055 &req.cmd, sizeof(req)); 1056 } 1057 1058 static int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood) 1059 { 1060 struct prestera_msg_port_attr_req req = { 1061 .attr = PRESTERA_CMD_PORT_ATTR_FLOOD, 1062 .port = port->hw_id, 1063 .dev = port->dev_id, 1064 .param = { 1065 .flood_ext = { 1066 .type = PRESTERA_PORT_FLOOD_TYPE_UC, 1067 .enable = flood, 1068 } 1069 } 1070 }; 1071 1072 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 1073 &req.cmd, sizeof(req)); 1074 } 1075 1076 static int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood) 1077 { 1078 struct prestera_msg_port_attr_req req = { 1079 .attr = PRESTERA_CMD_PORT_ATTR_FLOOD, 1080 .port = port->hw_id, 1081 .dev = port->dev_id, 1082 .param = { 1083 .flood_ext = { 1084 .type = PRESTERA_PORT_FLOOD_TYPE_MC, 1085 .enable = flood, 1086 } 1087 } 1088 }; 1089 1090 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 1091 &req.cmd, sizeof(req)); 1092 } 1093 1094 static int prestera_hw_port_flood_set_v2(struct prestera_port *port, bool flood) 1095 { 1096 struct prestera_msg_port_attr_req req = { 1097 .attr = PRESTERA_CMD_PORT_ATTR_FLOOD, 1098 .port = port->hw_id, 1099 .dev = port->dev_id, 1100 .param = { 1101 .flood = flood, 1102 } 1103 }; 1104 1105 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET, 1106 &req.cmd, sizeof(req)); 1107 } 1108 1109 int prestera_hw_port_flood_set(struct prestera_port *port, unsigned long mask, 1110 unsigned long val) 1111 { 1112 int err; 1113 1114 if (port->sw->dev->fw_rev.maj <= 2) { 1115 if (!(mask & BR_FLOOD)) 1116 return 0; 1117 1118 return prestera_hw_port_flood_set_v2(port, val & BR_FLOOD); 1119 } 1120 1121 if (mask & BR_FLOOD) { 1122 err = prestera_hw_port_uc_flood_set(port, val & BR_FLOOD); 1123 if (err) 1124 goto err_uc_flood; 1125 } 1126 1127 if (mask & BR_MCAST_FLOOD) { 1128 err = prestera_hw_port_mc_flood_set(port, val & BR_MCAST_FLOOD); 1129 if (err) 1130 goto err_mc_flood; 1131 } 1132 1133 return 0; 1134 1135 err_mc_flood: 1136 prestera_hw_port_mc_flood_set(port, 0); 1137 err_uc_flood: 1138 if (mask & BR_FLOOD) 1139 prestera_hw_port_uc_flood_set(port, 0); 1140 1141 return err; 1142 } 1143 1144 int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid) 1145 { 1146 struct prestera_msg_vlan_req req = { 1147 .vid = vid, 1148 }; 1149 1150 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE, 1151 &req.cmd, sizeof(req)); 1152 } 1153 1154 int prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid) 1155 { 1156 struct prestera_msg_vlan_req req = { 1157 .vid = vid, 1158 }; 1159 1160 return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE, 1161 &req.cmd, sizeof(req)); 1162 } 1163 1164 int prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid, 1165 bool is_member, bool untagged) 1166 { 1167 struct prestera_msg_vlan_req req = { 1168 .port = port->hw_id, 1169 .dev = port->dev_id, 1170 .vid = vid, 1171 .is_member = is_member, 1172 .is_tagged = !untagged, 1173 }; 1174 1175 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET, 1176 &req.cmd, sizeof(req)); 1177 } 1178 1179 int prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid) 1180 { 1181 struct prestera_msg_vlan_req req = { 1182 .port = port->hw_id, 1183 .dev = port->dev_id, 1184 .vid = vid, 1185 }; 1186 1187 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET, 1188 &req.cmd, sizeof(req)); 1189 } 1190 1191 int prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state) 1192 { 1193 struct prestera_msg_stp_req req = { 1194 .port = port->hw_id, 1195 .dev = port->dev_id, 1196 .vid = vid, 1197 .state = state, 1198 }; 1199 1200 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET, 1201 &req.cmd, sizeof(req)); 1202 } 1203 1204 int prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac, 1205 u16 vid, bool dynamic) 1206 { 1207 struct prestera_msg_fdb_req req = { 1208 .dest = { 1209 .dev = port->dev_id, 1210 .port = port->hw_id, 1211 }, 1212 .vid = vid, 1213 .dynamic = dynamic, 1214 }; 1215 1216 ether_addr_copy(req.mac, mac); 1217 1218 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD, 1219 &req.cmd, sizeof(req)); 1220 } 1221 1222 int prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac, 1223 u16 vid) 1224 { 1225 struct prestera_msg_fdb_req req = { 1226 .dest = { 1227 .dev = port->dev_id, 1228 .port = port->hw_id, 1229 }, 1230 .vid = vid, 1231 }; 1232 1233 ether_addr_copy(req.mac, mac); 1234 1235 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE, 1236 &req.cmd, sizeof(req)); 1237 } 1238 1239 int prestera_hw_lag_fdb_add(struct prestera_switch *sw, u16 lag_id, 1240 const unsigned char *mac, u16 vid, bool dynamic) 1241 { 1242 struct prestera_msg_fdb_req req = { 1243 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG, 1244 .dest = { 1245 .lag_id = lag_id, 1246 }, 1247 .vid = vid, 1248 .dynamic = dynamic, 1249 }; 1250 1251 ether_addr_copy(req.mac, mac); 1252 1253 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_ADD, 1254 &req.cmd, sizeof(req)); 1255 } 1256 1257 int prestera_hw_lag_fdb_del(struct prestera_switch *sw, u16 lag_id, 1258 const unsigned char *mac, u16 vid) 1259 { 1260 struct prestera_msg_fdb_req req = { 1261 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG, 1262 .dest = { 1263 .lag_id = lag_id, 1264 }, 1265 .vid = vid, 1266 }; 1267 1268 ether_addr_copy(req.mac, mac); 1269 1270 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_DELETE, 1271 &req.cmd, sizeof(req)); 1272 } 1273 1274 int prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode) 1275 { 1276 struct prestera_msg_fdb_req req = { 1277 .dest = { 1278 .dev = port->dev_id, 1279 .port = port->hw_id, 1280 }, 1281 .flush_mode = mode, 1282 }; 1283 1284 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT, 1285 &req.cmd, sizeof(req)); 1286 } 1287 1288 int prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode) 1289 { 1290 struct prestera_msg_fdb_req req = { 1291 .vid = vid, 1292 .flush_mode = mode, 1293 }; 1294 1295 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN, 1296 &req.cmd, sizeof(req)); 1297 } 1298 1299 int prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid, 1300 u32 mode) 1301 { 1302 struct prestera_msg_fdb_req req = { 1303 .dest = { 1304 .dev = port->dev_id, 1305 .port = port->hw_id, 1306 }, 1307 .vid = vid, 1308 .flush_mode = mode, 1309 }; 1310 1311 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN, 1312 &req.cmd, sizeof(req)); 1313 } 1314 1315 int prestera_hw_fdb_flush_lag(struct prestera_switch *sw, u16 lag_id, 1316 u32 mode) 1317 { 1318 struct prestera_msg_fdb_req req = { 1319 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG, 1320 .dest = { 1321 .lag_id = lag_id, 1322 }, 1323 .flush_mode = mode, 1324 }; 1325 1326 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT, 1327 &req.cmd, sizeof(req)); 1328 } 1329 1330 int prestera_hw_fdb_flush_lag_vlan(struct prestera_switch *sw, 1331 u16 lag_id, u16 vid, u32 mode) 1332 { 1333 struct prestera_msg_fdb_req req = { 1334 .dest_type = PRESTERA_HW_FDB_ENTRY_TYPE_LAG, 1335 .dest = { 1336 .lag_id = lag_id, 1337 }, 1338 .vid = vid, 1339 .flush_mode = mode, 1340 }; 1341 1342 return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN, 1343 &req.cmd, sizeof(req)); 1344 } 1345 1346 int prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id) 1347 { 1348 struct prestera_msg_bridge_resp resp; 1349 struct prestera_msg_bridge_req req; 1350 int err; 1351 1352 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE, 1353 &req.cmd, sizeof(req), 1354 &resp.ret, sizeof(resp)); 1355 if (err) 1356 return err; 1357 1358 *bridge_id = resp.bridge; 1359 1360 return 0; 1361 } 1362 1363 int prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id) 1364 { 1365 struct prestera_msg_bridge_req req = { 1366 .bridge = bridge_id, 1367 }; 1368 1369 return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE, 1370 &req.cmd, sizeof(req)); 1371 } 1372 1373 int prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id) 1374 { 1375 struct prestera_msg_bridge_req req = { 1376 .bridge = bridge_id, 1377 .port = port->hw_id, 1378 .dev = port->dev_id, 1379 }; 1380 1381 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD, 1382 &req.cmd, sizeof(req)); 1383 } 1384 1385 int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id) 1386 { 1387 struct prestera_msg_bridge_req req = { 1388 .bridge = bridge_id, 1389 .port = port->hw_id, 1390 .dev = port->dev_id, 1391 }; 1392 1393 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE, 1394 &req.cmd, sizeof(req)); 1395 } 1396 1397 int prestera_hw_rxtx_init(struct prestera_switch *sw, 1398 struct prestera_rxtx_params *params) 1399 { 1400 struct prestera_msg_rxtx_resp resp; 1401 struct prestera_msg_rxtx_req req; 1402 int err; 1403 1404 req.use_sdma = params->use_sdma; 1405 1406 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT, 1407 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 1408 if (err) 1409 return err; 1410 1411 params->map_addr = resp.map_addr; 1412 1413 return 0; 1414 } 1415 1416 int prestera_hw_rxtx_port_init(struct prestera_port *port) 1417 { 1418 struct prestera_msg_rxtx_port_req req = { 1419 .port = port->hw_id, 1420 .dev = port->dev_id, 1421 }; 1422 1423 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_RXTX_PORT_INIT, 1424 &req.cmd, sizeof(req)); 1425 } 1426 1427 int prestera_hw_lag_member_add(struct prestera_port *port, u16 lag_id) 1428 { 1429 struct prestera_msg_lag_req req = { 1430 .port = port->hw_id, 1431 .dev = port->dev_id, 1432 .lag_id = lag_id, 1433 }; 1434 1435 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_ADD, 1436 &req.cmd, sizeof(req)); 1437 } 1438 1439 int prestera_hw_lag_member_del(struct prestera_port *port, u16 lag_id) 1440 { 1441 struct prestera_msg_lag_req req = { 1442 .port = port->hw_id, 1443 .dev = port->dev_id, 1444 .lag_id = lag_id, 1445 }; 1446 1447 return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE, 1448 &req.cmd, sizeof(req)); 1449 } 1450 1451 int prestera_hw_lag_member_enable(struct prestera_port *port, u16 lag_id, 1452 bool enable) 1453 { 1454 struct prestera_msg_lag_req req = { 1455 .port = port->hw_id, 1456 .dev = port->dev_id, 1457 .lag_id = lag_id, 1458 }; 1459 u32 cmd; 1460 1461 cmd = enable ? PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE : 1462 PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE; 1463 1464 return prestera_cmd(port->sw, cmd, &req.cmd, sizeof(req)); 1465 } 1466 1467 int 1468 prestera_hw_cpu_code_counters_get(struct prestera_switch *sw, u8 code, 1469 enum prestera_hw_cpu_code_cnt_t counter_type, 1470 u64 *packet_count) 1471 { 1472 struct prestera_msg_cpu_code_counter_req req = { 1473 .counter_type = counter_type, 1474 .code = code, 1475 }; 1476 struct mvsw_msg_cpu_code_counter_ret resp; 1477 int err; 1478 1479 err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET, 1480 &req.cmd, sizeof(req), &resp.ret, sizeof(resp)); 1481 if (err) 1482 return err; 1483 1484 *packet_count = resp.packet_count; 1485 1486 return 0; 1487 } 1488 1489 int prestera_hw_event_handler_register(struct prestera_switch *sw, 1490 enum prestera_event_type type, 1491 prestera_event_cb_t fn, 1492 void *arg) 1493 { 1494 struct prestera_fw_event_handler *eh; 1495 1496 eh = __find_event_handler(sw, type); 1497 if (eh) 1498 return -EEXIST; 1499 1500 eh = kmalloc(sizeof(*eh), GFP_KERNEL); 1501 if (!eh) 1502 return -ENOMEM; 1503 1504 eh->type = type; 1505 eh->func = fn; 1506 eh->arg = arg; 1507 1508 INIT_LIST_HEAD(&eh->list); 1509 1510 list_add_rcu(&eh->list, &sw->event_handlers); 1511 1512 return 0; 1513 } 1514 1515 void prestera_hw_event_handler_unregister(struct prestera_switch *sw, 1516 enum prestera_event_type type, 1517 prestera_event_cb_t fn) 1518 { 1519 struct prestera_fw_event_handler *eh; 1520 1521 eh = __find_event_handler(sw, type); 1522 if (!eh) 1523 return; 1524 1525 list_del_rcu(&eh->list); 1526 kfree_rcu(eh, rcu); 1527 } 1528