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