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