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