eswitch.c (54100B)
1/* 2 * Copyright (c) 2015, Mellanox Technologies. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33#include <linux/etherdevice.h> 34#include <linux/mlx5/driver.h> 35#include <linux/mlx5/mlx5_ifc.h> 36#include <linux/mlx5/vport.h> 37#include <linux/mlx5/fs.h> 38#include <linux/mlx5/mpfs.h> 39#include "esw/acl/lgcy.h" 40#include "esw/legacy.h" 41#include "esw/qos.h" 42#include "mlx5_core.h" 43#include "lib/eq.h" 44#include "eswitch.h" 45#include "fs_core.h" 46#include "devlink.h" 47#include "ecpf.h" 48#include "en/mod_hdr.h" 49 50enum { 51 MLX5_ACTION_NONE = 0, 52 MLX5_ACTION_ADD = 1, 53 MLX5_ACTION_DEL = 2, 54}; 55 56/* Vport UC/MC hash node */ 57struct vport_addr { 58 struct l2addr_node node; 59 u8 action; 60 u16 vport; 61 struct mlx5_flow_handle *flow_rule; 62 bool mpfs; /* UC MAC was added to MPFs */ 63 /* A flag indicating that mac was added due to mc promiscuous vport */ 64 bool mc_promisc; 65}; 66 67static int mlx5_eswitch_check(const struct mlx5_core_dev *dev) 68{ 69 if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) 70 return -EOPNOTSUPP; 71 72 if (!MLX5_ESWITCH_MANAGER(dev)) 73 return -EOPNOTSUPP; 74 75 return 0; 76} 77 78struct mlx5_eswitch *mlx5_devlink_eswitch_get(struct devlink *devlink) 79{ 80 struct mlx5_core_dev *dev = devlink_priv(devlink); 81 int err; 82 83 err = mlx5_eswitch_check(dev); 84 if (err) 85 return ERR_PTR(err); 86 87 return dev->priv.eswitch; 88} 89 90struct mlx5_vport *__must_check 91mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num) 92{ 93 struct mlx5_vport *vport; 94 95 if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager)) 96 return ERR_PTR(-EPERM); 97 98 vport = xa_load(&esw->vports, vport_num); 99 if (!vport) { 100 esw_debug(esw->dev, "vport out of range: num(0x%x)\n", vport_num); 101 return ERR_PTR(-EINVAL); 102 } 103 return vport; 104} 105 106static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport, 107 u32 events_mask) 108{ 109 u32 in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)] = {}; 110 void *nic_vport_ctx; 111 112 MLX5_SET(modify_nic_vport_context_in, in, 113 opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 114 MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1); 115 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 116 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 117 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, 118 in, nic_vport_context); 119 120 MLX5_SET(nic_vport_context, nic_vport_ctx, arm_change_event, 1); 121 122 if (events_mask & MLX5_VPORT_UC_ADDR_CHANGE) 123 MLX5_SET(nic_vport_context, nic_vport_ctx, 124 event_on_uc_address_change, 1); 125 if (events_mask & MLX5_VPORT_MC_ADDR_CHANGE) 126 MLX5_SET(nic_vport_context, nic_vport_ctx, 127 event_on_mc_address_change, 1); 128 if (events_mask & MLX5_VPORT_PROMISC_CHANGE) 129 MLX5_SET(nic_vport_context, nic_vport_ctx, 130 event_on_promisc_change, 1); 131 132 return mlx5_cmd_exec_in(dev, modify_nic_vport_context, in); 133} 134 135/* E-Switch vport context HW commands */ 136int mlx5_eswitch_modify_esw_vport_context(struct mlx5_core_dev *dev, u16 vport, 137 bool other_vport, void *in) 138{ 139 MLX5_SET(modify_esw_vport_context_in, in, opcode, 140 MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT); 141 MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport); 142 MLX5_SET(modify_esw_vport_context_in, in, other_vport, other_vport); 143 return mlx5_cmd_exec_in(dev, modify_esw_vport_context, in); 144} 145 146static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u16 vport, 147 u16 vlan, u8 qos, u8 set_flags) 148{ 149 u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {}; 150 151 if (!MLX5_CAP_ESW(dev, vport_cvlan_strip) || 152 !MLX5_CAP_ESW(dev, vport_cvlan_insert_if_not_exist)) 153 return -EOPNOTSUPP; 154 155 esw_debug(dev, "Set Vport[%d] VLAN %d qos %d set=%x\n", 156 vport, vlan, qos, set_flags); 157 158 if (set_flags & SET_VLAN_STRIP) 159 MLX5_SET(modify_esw_vport_context_in, in, 160 esw_vport_context.vport_cvlan_strip, 1); 161 162 if (set_flags & SET_VLAN_INSERT) { 163 /* insert only if no vlan in packet */ 164 MLX5_SET(modify_esw_vport_context_in, in, 165 esw_vport_context.vport_cvlan_insert, 1); 166 167 MLX5_SET(modify_esw_vport_context_in, in, 168 esw_vport_context.cvlan_pcp, qos); 169 MLX5_SET(modify_esw_vport_context_in, in, 170 esw_vport_context.cvlan_id, vlan); 171 } 172 173 MLX5_SET(modify_esw_vport_context_in, in, 174 field_select.vport_cvlan_strip, 1); 175 MLX5_SET(modify_esw_vport_context_in, in, 176 field_select.vport_cvlan_insert, 1); 177 178 return mlx5_eswitch_modify_esw_vport_context(dev, vport, true, in); 179} 180 181/* E-Switch FDB */ 182static struct mlx5_flow_handle * 183__esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u16 vport, bool rx_rule, 184 u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN]) 185{ 186 int match_header = (is_zero_ether_addr(mac_c) ? 0 : 187 MLX5_MATCH_OUTER_HEADERS); 188 struct mlx5_flow_handle *flow_rule = NULL; 189 struct mlx5_flow_act flow_act = {0}; 190 struct mlx5_flow_destination dest = {}; 191 struct mlx5_flow_spec *spec; 192 void *mv_misc = NULL; 193 void *mc_misc = NULL; 194 u8 *dmac_v = NULL; 195 u8 *dmac_c = NULL; 196 197 if (rx_rule) 198 match_header |= MLX5_MATCH_MISC_PARAMETERS; 199 200 spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 201 if (!spec) 202 return NULL; 203 204 dmac_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, 205 outer_headers.dmac_47_16); 206 dmac_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 207 outer_headers.dmac_47_16); 208 209 if (match_header & MLX5_MATCH_OUTER_HEADERS) { 210 ether_addr_copy(dmac_v, mac_v); 211 ether_addr_copy(dmac_c, mac_c); 212 } 213 214 if (match_header & MLX5_MATCH_MISC_PARAMETERS) { 215 mv_misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, 216 misc_parameters); 217 mc_misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 218 misc_parameters); 219 MLX5_SET(fte_match_set_misc, mv_misc, source_port, MLX5_VPORT_UPLINK); 220 MLX5_SET_TO_ONES(fte_match_set_misc, mc_misc, source_port); 221 } 222 223 dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; 224 dest.vport.num = vport; 225 226 esw_debug(esw->dev, 227 "\tFDB add rule dmac_v(%pM) dmac_c(%pM) -> vport(%d)\n", 228 dmac_v, dmac_c, vport); 229 spec->match_criteria_enable = match_header; 230 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 231 flow_rule = 232 mlx5_add_flow_rules(esw->fdb_table.legacy.fdb, spec, 233 &flow_act, &dest, 1); 234 if (IS_ERR(flow_rule)) { 235 esw_warn(esw->dev, 236 "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n", 237 dmac_v, dmac_c, vport, PTR_ERR(flow_rule)); 238 flow_rule = NULL; 239 } 240 241 kvfree(spec); 242 return flow_rule; 243} 244 245static struct mlx5_flow_handle * 246esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u16 vport) 247{ 248 u8 mac_c[ETH_ALEN]; 249 250 eth_broadcast_addr(mac_c); 251 return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac); 252} 253 254static struct mlx5_flow_handle * 255esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u16 vport) 256{ 257 u8 mac_c[ETH_ALEN]; 258 u8 mac_v[ETH_ALEN]; 259 260 eth_zero_addr(mac_c); 261 eth_zero_addr(mac_v); 262 mac_c[0] = 0x01; 263 mac_v[0] = 0x01; 264 return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac_v); 265} 266 267static struct mlx5_flow_handle * 268esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport) 269{ 270 u8 mac_c[ETH_ALEN]; 271 u8 mac_v[ETH_ALEN]; 272 273 eth_zero_addr(mac_c); 274 eth_zero_addr(mac_v); 275 return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v); 276} 277 278/* E-Switch vport UC/MC lists management */ 279typedef int (*vport_addr_action)(struct mlx5_eswitch *esw, 280 struct vport_addr *vaddr); 281 282static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) 283{ 284 u8 *mac = vaddr->node.addr; 285 u16 vport = vaddr->vport; 286 int err; 287 288 /* Skip mlx5_mpfs_add_mac for eswitch_managers, 289 * it is already done by its netdev in mlx5e_execute_l2_action 290 */ 291 if (mlx5_esw_is_manager_vport(esw, vport)) 292 goto fdb_add; 293 294 err = mlx5_mpfs_add_mac(esw->dev, mac); 295 if (err) { 296 esw_warn(esw->dev, 297 "Failed to add L2 table mac(%pM) for vport(0x%x), err(%d)\n", 298 mac, vport, err); 299 return err; 300 } 301 vaddr->mpfs = true; 302 303fdb_add: 304 /* SRIOV is enabled: Forward UC MAC to vport */ 305 if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY) 306 vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport); 307 308 esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n", 309 vport, mac, vaddr->flow_rule); 310 311 return 0; 312} 313 314static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) 315{ 316 u8 *mac = vaddr->node.addr; 317 u16 vport = vaddr->vport; 318 int err = 0; 319 320 /* Skip mlx5_mpfs_del_mac for eswitch managers, 321 * it is already done by its netdev in mlx5e_execute_l2_action 322 */ 323 if (!vaddr->mpfs || mlx5_esw_is_manager_vport(esw, vport)) 324 goto fdb_del; 325 326 err = mlx5_mpfs_del_mac(esw->dev, mac); 327 if (err) 328 esw_warn(esw->dev, 329 "Failed to del L2 table mac(%pM) for vport(%d), err(%d)\n", 330 mac, vport, err); 331 vaddr->mpfs = false; 332 333fdb_del: 334 if (vaddr->flow_rule) 335 mlx5_del_flow_rules(vaddr->flow_rule); 336 vaddr->flow_rule = NULL; 337 338 return 0; 339} 340 341static void update_allmulti_vports(struct mlx5_eswitch *esw, 342 struct vport_addr *vaddr, 343 struct esw_mc_addr *esw_mc) 344{ 345 u8 *mac = vaddr->node.addr; 346 struct mlx5_vport *vport; 347 unsigned long i; 348 u16 vport_num; 349 350 mlx5_esw_for_each_vport(esw, i, vport) { 351 struct hlist_head *vport_hash = vport->mc_list; 352 struct vport_addr *iter_vaddr = 353 l2addr_hash_find(vport_hash, 354 mac, 355 struct vport_addr); 356 vport_num = vport->vport; 357 if (IS_ERR_OR_NULL(vport->allmulti_rule) || 358 vaddr->vport == vport_num) 359 continue; 360 switch (vaddr->action) { 361 case MLX5_ACTION_ADD: 362 if (iter_vaddr) 363 continue; 364 iter_vaddr = l2addr_hash_add(vport_hash, mac, 365 struct vport_addr, 366 GFP_KERNEL); 367 if (!iter_vaddr) { 368 esw_warn(esw->dev, 369 "ALL-MULTI: Failed to add MAC(%pM) to vport[%d] DB\n", 370 mac, vport_num); 371 continue; 372 } 373 iter_vaddr->vport = vport_num; 374 iter_vaddr->flow_rule = 375 esw_fdb_set_vport_rule(esw, 376 mac, 377 vport_num); 378 iter_vaddr->mc_promisc = true; 379 break; 380 case MLX5_ACTION_DEL: 381 if (!iter_vaddr) 382 continue; 383 mlx5_del_flow_rules(iter_vaddr->flow_rule); 384 l2addr_hash_del(iter_vaddr); 385 break; 386 } 387 } 388} 389 390static int esw_add_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) 391{ 392 struct hlist_head *hash = esw->mc_table; 393 struct esw_mc_addr *esw_mc; 394 u8 *mac = vaddr->node.addr; 395 u16 vport = vaddr->vport; 396 397 if (!esw->fdb_table.legacy.fdb) 398 return 0; 399 400 esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr); 401 if (esw_mc) 402 goto add; 403 404 esw_mc = l2addr_hash_add(hash, mac, struct esw_mc_addr, GFP_KERNEL); 405 if (!esw_mc) 406 return -ENOMEM; 407 408 esw_mc->uplink_rule = /* Forward MC MAC to Uplink */ 409 esw_fdb_set_vport_rule(esw, mac, MLX5_VPORT_UPLINK); 410 411 /* Add this multicast mac to all the mc promiscuous vports */ 412 update_allmulti_vports(esw, vaddr, esw_mc); 413 414add: 415 /* If the multicast mac is added as a result of mc promiscuous vport, 416 * don't increment the multicast ref count 417 */ 418 if (!vaddr->mc_promisc) 419 esw_mc->refcnt++; 420 421 /* Forward MC MAC to vport */ 422 vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport); 423 esw_debug(esw->dev, 424 "\tADDED MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n", 425 vport, mac, vaddr->flow_rule, 426 esw_mc->refcnt, esw_mc->uplink_rule); 427 return 0; 428} 429 430static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) 431{ 432 struct hlist_head *hash = esw->mc_table; 433 struct esw_mc_addr *esw_mc; 434 u8 *mac = vaddr->node.addr; 435 u16 vport = vaddr->vport; 436 437 if (!esw->fdb_table.legacy.fdb) 438 return 0; 439 440 esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr); 441 if (!esw_mc) { 442 esw_warn(esw->dev, 443 "Failed to find eswitch MC addr for MAC(%pM) vport(%d)", 444 mac, vport); 445 return -EINVAL; 446 } 447 esw_debug(esw->dev, 448 "\tDELETE MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n", 449 vport, mac, vaddr->flow_rule, esw_mc->refcnt, 450 esw_mc->uplink_rule); 451 452 if (vaddr->flow_rule) 453 mlx5_del_flow_rules(vaddr->flow_rule); 454 vaddr->flow_rule = NULL; 455 456 /* If the multicast mac is added as a result of mc promiscuous vport, 457 * don't decrement the multicast ref count. 458 */ 459 if (vaddr->mc_promisc || (--esw_mc->refcnt > 0)) 460 return 0; 461 462 /* Remove this multicast mac from all the mc promiscuous vports */ 463 update_allmulti_vports(esw, vaddr, esw_mc); 464 465 if (esw_mc->uplink_rule) 466 mlx5_del_flow_rules(esw_mc->uplink_rule); 467 468 l2addr_hash_del(esw_mc); 469 return 0; 470} 471 472/* Apply vport UC/MC list to HW l2 table and FDB table */ 473static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw, 474 struct mlx5_vport *vport, int list_type) 475{ 476 bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC; 477 vport_addr_action vport_addr_add; 478 vport_addr_action vport_addr_del; 479 struct vport_addr *addr; 480 struct l2addr_node *node; 481 struct hlist_head *hash; 482 struct hlist_node *tmp; 483 int hi; 484 485 vport_addr_add = is_uc ? esw_add_uc_addr : 486 esw_add_mc_addr; 487 vport_addr_del = is_uc ? esw_del_uc_addr : 488 esw_del_mc_addr; 489 490 hash = is_uc ? vport->uc_list : vport->mc_list; 491 for_each_l2hash_node(node, tmp, hash, hi) { 492 addr = container_of(node, struct vport_addr, node); 493 switch (addr->action) { 494 case MLX5_ACTION_ADD: 495 vport_addr_add(esw, addr); 496 addr->action = MLX5_ACTION_NONE; 497 break; 498 case MLX5_ACTION_DEL: 499 vport_addr_del(esw, addr); 500 l2addr_hash_del(addr); 501 break; 502 } 503 } 504} 505 506/* Sync vport UC/MC list from vport context */ 507static void esw_update_vport_addr_list(struct mlx5_eswitch *esw, 508 struct mlx5_vport *vport, int list_type) 509{ 510 bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC; 511 u8 (*mac_list)[ETH_ALEN]; 512 struct l2addr_node *node; 513 struct vport_addr *addr; 514 struct hlist_head *hash; 515 struct hlist_node *tmp; 516 int size; 517 int err; 518 int hi; 519 int i; 520 521 size = is_uc ? MLX5_MAX_UC_PER_VPORT(esw->dev) : 522 MLX5_MAX_MC_PER_VPORT(esw->dev); 523 524 mac_list = kcalloc(size, ETH_ALEN, GFP_KERNEL); 525 if (!mac_list) 526 return; 527 528 hash = is_uc ? vport->uc_list : vport->mc_list; 529 530 for_each_l2hash_node(node, tmp, hash, hi) { 531 addr = container_of(node, struct vport_addr, node); 532 addr->action = MLX5_ACTION_DEL; 533 } 534 535 if (!vport->enabled) 536 goto out; 537 538 err = mlx5_query_nic_vport_mac_list(esw->dev, vport->vport, list_type, 539 mac_list, &size); 540 if (err) 541 goto out; 542 esw_debug(esw->dev, "vport[%d] context update %s list size (%d)\n", 543 vport->vport, is_uc ? "UC" : "MC", size); 544 545 for (i = 0; i < size; i++) { 546 if (is_uc && !is_valid_ether_addr(mac_list[i])) 547 continue; 548 549 if (!is_uc && !is_multicast_ether_addr(mac_list[i])) 550 continue; 551 552 addr = l2addr_hash_find(hash, mac_list[i], struct vport_addr); 553 if (addr) { 554 addr->action = MLX5_ACTION_NONE; 555 /* If this mac was previously added because of allmulti 556 * promiscuous rx mode, its now converted to be original 557 * vport mac. 558 */ 559 if (addr->mc_promisc) { 560 struct esw_mc_addr *esw_mc = 561 l2addr_hash_find(esw->mc_table, 562 mac_list[i], 563 struct esw_mc_addr); 564 if (!esw_mc) { 565 esw_warn(esw->dev, 566 "Failed to MAC(%pM) in mcast DB\n", 567 mac_list[i]); 568 continue; 569 } 570 esw_mc->refcnt++; 571 addr->mc_promisc = false; 572 } 573 continue; 574 } 575 576 addr = l2addr_hash_add(hash, mac_list[i], struct vport_addr, 577 GFP_KERNEL); 578 if (!addr) { 579 esw_warn(esw->dev, 580 "Failed to add MAC(%pM) to vport[%d] DB\n", 581 mac_list[i], vport->vport); 582 continue; 583 } 584 addr->vport = vport->vport; 585 addr->action = MLX5_ACTION_ADD; 586 } 587out: 588 kfree(mac_list); 589} 590 591/* Sync vport UC/MC list from vport context 592 * Must be called after esw_update_vport_addr_list 593 */ 594static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, 595 struct mlx5_vport *vport) 596{ 597 struct l2addr_node *node; 598 struct vport_addr *addr; 599 struct hlist_head *hash; 600 struct hlist_node *tmp; 601 int hi; 602 603 hash = vport->mc_list; 604 605 for_each_l2hash_node(node, tmp, esw->mc_table, hi) { 606 u8 *mac = node->addr; 607 608 addr = l2addr_hash_find(hash, mac, struct vport_addr); 609 if (addr) { 610 if (addr->action == MLX5_ACTION_DEL) 611 addr->action = MLX5_ACTION_NONE; 612 continue; 613 } 614 addr = l2addr_hash_add(hash, mac, struct vport_addr, 615 GFP_KERNEL); 616 if (!addr) { 617 esw_warn(esw->dev, 618 "Failed to add allmulti MAC(%pM) to vport[%d] DB\n", 619 mac, vport->vport); 620 continue; 621 } 622 addr->vport = vport->vport; 623 addr->action = MLX5_ACTION_ADD; 624 addr->mc_promisc = true; 625 } 626} 627 628/* Apply vport rx mode to HW FDB table */ 629static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, 630 struct mlx5_vport *vport, 631 bool promisc, bool mc_promisc) 632{ 633 struct esw_mc_addr *allmulti_addr = &esw->mc_promisc; 634 635 if (IS_ERR_OR_NULL(vport->allmulti_rule) != mc_promisc) 636 goto promisc; 637 638 if (mc_promisc) { 639 vport->allmulti_rule = 640 esw_fdb_set_vport_allmulti_rule(esw, vport->vport); 641 if (!allmulti_addr->uplink_rule) 642 allmulti_addr->uplink_rule = 643 esw_fdb_set_vport_allmulti_rule(esw, 644 MLX5_VPORT_UPLINK); 645 allmulti_addr->refcnt++; 646 } else if (vport->allmulti_rule) { 647 mlx5_del_flow_rules(vport->allmulti_rule); 648 vport->allmulti_rule = NULL; 649 650 if (--allmulti_addr->refcnt > 0) 651 goto promisc; 652 653 if (allmulti_addr->uplink_rule) 654 mlx5_del_flow_rules(allmulti_addr->uplink_rule); 655 allmulti_addr->uplink_rule = NULL; 656 } 657 658promisc: 659 if (IS_ERR_OR_NULL(vport->promisc_rule) != promisc) 660 return; 661 662 if (promisc) { 663 vport->promisc_rule = 664 esw_fdb_set_vport_promisc_rule(esw, vport->vport); 665 } else if (vport->promisc_rule) { 666 mlx5_del_flow_rules(vport->promisc_rule); 667 vport->promisc_rule = NULL; 668 } 669} 670 671/* Sync vport rx mode from vport context */ 672static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw, 673 struct mlx5_vport *vport) 674{ 675 int promisc_all = 0; 676 int promisc_uc = 0; 677 int promisc_mc = 0; 678 int err; 679 680 err = mlx5_query_nic_vport_promisc(esw->dev, 681 vport->vport, 682 &promisc_uc, 683 &promisc_mc, 684 &promisc_all); 685 if (err) 686 return; 687 esw_debug(esw->dev, "vport[%d] context update rx mode promisc_all=%d, all_multi=%d\n", 688 vport->vport, promisc_all, promisc_mc); 689 690 if (!vport->info.trusted || !vport->enabled) { 691 promisc_uc = 0; 692 promisc_mc = 0; 693 promisc_all = 0; 694 } 695 696 esw_apply_vport_rx_mode(esw, vport, promisc_all, 697 (promisc_all || promisc_mc)); 698} 699 700void esw_vport_change_handle_locked(struct mlx5_vport *vport) 701{ 702 struct mlx5_core_dev *dev = vport->dev; 703 struct mlx5_eswitch *esw = dev->priv.eswitch; 704 u8 mac[ETH_ALEN]; 705 706 mlx5_query_nic_vport_mac_address(dev, vport->vport, true, mac); 707 esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n", 708 vport->vport, mac); 709 710 if (vport->enabled_events & MLX5_VPORT_UC_ADDR_CHANGE) { 711 esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC); 712 esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC); 713 } 714 715 if (vport->enabled_events & MLX5_VPORT_MC_ADDR_CHANGE) 716 esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC); 717 718 if (vport->enabled_events & MLX5_VPORT_PROMISC_CHANGE) { 719 esw_update_vport_rx_mode(esw, vport); 720 if (!IS_ERR_OR_NULL(vport->allmulti_rule)) 721 esw_update_vport_mc_promisc(esw, vport); 722 } 723 724 if (vport->enabled_events & (MLX5_VPORT_PROMISC_CHANGE | MLX5_VPORT_MC_ADDR_CHANGE)) 725 esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC); 726 727 esw_debug(esw->dev, "vport[%d] Context Changed: Done\n", vport->vport); 728 if (vport->enabled) 729 arm_vport_context_events_cmd(dev, vport->vport, 730 vport->enabled_events); 731} 732 733static void esw_vport_change_handler(struct work_struct *work) 734{ 735 struct mlx5_vport *vport = 736 container_of(work, struct mlx5_vport, vport_change_handler); 737 struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 738 739 mutex_lock(&esw->state_lock); 740 esw_vport_change_handle_locked(vport); 741 mutex_unlock(&esw->state_lock); 742} 743 744static void node_guid_gen_from_mac(u64 *node_guid, const u8 *mac) 745{ 746 ((u8 *)node_guid)[7] = mac[0]; 747 ((u8 *)node_guid)[6] = mac[1]; 748 ((u8 *)node_guid)[5] = mac[2]; 749 ((u8 *)node_guid)[4] = 0xff; 750 ((u8 *)node_guid)[3] = 0xfe; 751 ((u8 *)node_guid)[2] = mac[3]; 752 ((u8 *)node_guid)[1] = mac[4]; 753 ((u8 *)node_guid)[0] = mac[5]; 754} 755 756static int esw_vport_setup_acl(struct mlx5_eswitch *esw, 757 struct mlx5_vport *vport) 758{ 759 if (esw->mode == MLX5_ESWITCH_LEGACY) 760 return esw_legacy_vport_acl_setup(esw, vport); 761 else 762 return esw_vport_create_offloads_acl_tables(esw, vport); 763} 764 765static void esw_vport_cleanup_acl(struct mlx5_eswitch *esw, 766 struct mlx5_vport *vport) 767{ 768 if (esw->mode == MLX5_ESWITCH_LEGACY) 769 esw_legacy_vport_acl_cleanup(esw, vport); 770 else 771 esw_vport_destroy_offloads_acl_tables(esw, vport); 772} 773 774static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 775{ 776 u16 vport_num = vport->vport; 777 int flags; 778 int err; 779 780 err = esw_vport_setup_acl(esw, vport); 781 if (err) 782 return err; 783 784 if (mlx5_esw_is_manager_vport(esw, vport_num)) 785 return 0; 786 787 mlx5_modify_vport_admin_state(esw->dev, 788 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, 789 vport_num, 1, 790 vport->info.link_state); 791 792 /* Host PF has its own mac/guid. */ 793 if (vport_num) { 794 mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, 795 vport->info.mac); 796 mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, 797 vport->info.node_guid); 798 } 799 800 flags = (vport->info.vlan || vport->info.qos) ? 801 SET_VLAN_STRIP | SET_VLAN_INSERT : 0; 802 modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan, 803 vport->info.qos, flags); 804 805 return 0; 806} 807 808/* Don't cleanup vport->info, it's needed to restore vport configuration */ 809static void esw_vport_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 810{ 811 u16 vport_num = vport->vport; 812 813 if (!mlx5_esw_is_manager_vport(esw, vport_num)) 814 mlx5_modify_vport_admin_state(esw->dev, 815 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, 816 vport_num, 1, 817 MLX5_VPORT_ADMIN_STATE_DOWN); 818 819 mlx5_esw_qos_vport_disable(esw, vport); 820 esw_vport_cleanup_acl(esw, vport); 821} 822 823int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, u16 vport_num, 824 enum mlx5_eswitch_vport_event enabled_events) 825{ 826 struct mlx5_vport *vport; 827 int ret; 828 829 vport = mlx5_eswitch_get_vport(esw, vport_num); 830 if (IS_ERR(vport)) 831 return PTR_ERR(vport); 832 833 mutex_lock(&esw->state_lock); 834 WARN_ON(vport->enabled); 835 836 esw_debug(esw->dev, "Enabling VPORT(%d)\n", vport_num); 837 838 ret = esw_vport_setup(esw, vport); 839 if (ret) 840 goto done; 841 842 /* Sync with current vport context */ 843 vport->enabled_events = enabled_events; 844 vport->enabled = true; 845 846 /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well 847 * in smartNIC as it's a vport group manager. 848 */ 849 if (mlx5_esw_is_manager_vport(esw, vport_num) || 850 (!vport_num && mlx5_core_is_ecpf(esw->dev))) 851 vport->info.trusted = true; 852 853 if (!mlx5_esw_is_manager_vport(esw, vport->vport) && 854 MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) { 855 ret = mlx5_esw_vport_vhca_id_set(esw, vport_num); 856 if (ret) 857 goto err_vhca_mapping; 858 } 859 860 /* External controller host PF has factory programmed MAC. 861 * Read it from the device. 862 */ 863 if (mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF) 864 mlx5_query_nic_vport_mac_address(esw->dev, vport_num, true, vport->info.mac); 865 866 esw_vport_change_handle_locked(vport); 867 868 esw->enabled_vports++; 869 esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num); 870done: 871 mutex_unlock(&esw->state_lock); 872 return ret; 873 874err_vhca_mapping: 875 esw_vport_cleanup(esw, vport); 876 mutex_unlock(&esw->state_lock); 877 return ret; 878} 879 880void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num) 881{ 882 struct mlx5_vport *vport; 883 884 vport = mlx5_eswitch_get_vport(esw, vport_num); 885 if (IS_ERR(vport)) 886 return; 887 888 mutex_lock(&esw->state_lock); 889 if (!vport->enabled) 890 goto done; 891 892 esw_debug(esw->dev, "Disabling vport(%d)\n", vport_num); 893 /* Mark this vport as disabled to discard new events */ 894 vport->enabled = false; 895 896 /* Disable events from this vport */ 897 arm_vport_context_events_cmd(esw->dev, vport->vport, 0); 898 899 if (!mlx5_esw_is_manager_vport(esw, vport->vport) && 900 MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) 901 mlx5_esw_vport_vhca_id_clear(esw, vport_num); 902 903 /* We don't assume VFs will cleanup after themselves. 904 * Calling vport change handler while vport is disabled will cleanup 905 * the vport resources. 906 */ 907 esw_vport_change_handle_locked(vport); 908 vport->enabled_events = 0; 909 esw_vport_cleanup(esw, vport); 910 esw->enabled_vports--; 911 912done: 913 mutex_unlock(&esw->state_lock); 914} 915 916static int eswitch_vport_event(struct notifier_block *nb, 917 unsigned long type, void *data) 918{ 919 struct mlx5_eswitch *esw = mlx5_nb_cof(nb, struct mlx5_eswitch, nb); 920 struct mlx5_eqe *eqe = data; 921 struct mlx5_vport *vport; 922 u16 vport_num; 923 924 vport_num = be16_to_cpu(eqe->data.vport_change.vport_num); 925 vport = mlx5_eswitch_get_vport(esw, vport_num); 926 if (!IS_ERR(vport)) 927 queue_work(esw->work_queue, &vport->vport_change_handler); 928 return NOTIFY_OK; 929} 930 931/** 932 * mlx5_esw_query_functions - Returns raw output about functions state 933 * @dev: Pointer to device to query 934 * 935 * mlx5_esw_query_functions() allocates and returns functions changed 936 * raw output memory pointer from device on success. Otherwise returns ERR_PTR. 937 * Caller must free the memory using kvfree() when valid pointer is returned. 938 */ 939const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev) 940{ 941 int outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out); 942 u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {}; 943 u32 *out; 944 int err; 945 946 out = kvzalloc(outlen, GFP_KERNEL); 947 if (!out) 948 return ERR_PTR(-ENOMEM); 949 950 MLX5_SET(query_esw_functions_in, in, opcode, 951 MLX5_CMD_OP_QUERY_ESW_FUNCTIONS); 952 953 err = mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); 954 if (!err) 955 return out; 956 957 kvfree(out); 958 return ERR_PTR(err); 959} 960 961static void mlx5_eswitch_event_handlers_register(struct mlx5_eswitch *esw) 962{ 963 MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE); 964 mlx5_eq_notifier_register(esw->dev, &esw->nb); 965 966 if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) { 967 MLX5_NB_INIT(&esw->esw_funcs.nb, mlx5_esw_funcs_changed_handler, 968 ESW_FUNCTIONS_CHANGED); 969 mlx5_eq_notifier_register(esw->dev, &esw->esw_funcs.nb); 970 } 971} 972 973static void mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch *esw) 974{ 975 if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) 976 mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb); 977 978 mlx5_eq_notifier_unregister(esw->dev, &esw->nb); 979 980 flush_workqueue(esw->work_queue); 981} 982 983static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw) 984{ 985 struct mlx5_vport *vport; 986 unsigned long i; 987 988 mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) { 989 memset(&vport->qos, 0, sizeof(vport->qos)); 990 memset(&vport->info, 0, sizeof(vport->info)); 991 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 992 } 993} 994 995/* Public E-Switch API */ 996int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num, 997 enum mlx5_eswitch_vport_event enabled_events) 998{ 999 int err; 1000 1001 err = mlx5_esw_vport_enable(esw, vport_num, enabled_events); 1002 if (err) 1003 return err; 1004 1005 err = esw_offloads_load_rep(esw, vport_num); 1006 if (err) 1007 goto err_rep; 1008 1009 return err; 1010 1011err_rep: 1012 mlx5_esw_vport_disable(esw, vport_num); 1013 return err; 1014} 1015 1016void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num) 1017{ 1018 esw_offloads_unload_rep(esw, vport_num); 1019 mlx5_esw_vport_disable(esw, vport_num); 1020} 1021 1022void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs) 1023{ 1024 struct mlx5_vport *vport; 1025 unsigned long i; 1026 1027 mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) { 1028 if (!vport->enabled) 1029 continue; 1030 mlx5_eswitch_unload_vport(esw, vport->vport); 1031 } 1032} 1033 1034int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, 1035 enum mlx5_eswitch_vport_event enabled_events) 1036{ 1037 struct mlx5_vport *vport; 1038 unsigned long i; 1039 int err; 1040 1041 mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) { 1042 err = mlx5_eswitch_load_vport(esw, vport->vport, enabled_events); 1043 if (err) 1044 goto vf_err; 1045 } 1046 1047 return 0; 1048 1049vf_err: 1050 mlx5_eswitch_unload_vf_vports(esw, num_vfs); 1051 return err; 1052} 1053 1054static int host_pf_enable_hca(struct mlx5_core_dev *dev) 1055{ 1056 if (!mlx5_core_is_ecpf(dev)) 1057 return 0; 1058 1059 /* Once vport and representor are ready, take out the external host PF 1060 * out of initializing state. Enabling HCA clears the iser->initializing 1061 * bit and host PF driver loading can progress. 1062 */ 1063 return mlx5_cmd_host_pf_enable_hca(dev); 1064} 1065 1066static void host_pf_disable_hca(struct mlx5_core_dev *dev) 1067{ 1068 if (!mlx5_core_is_ecpf(dev)) 1069 return; 1070 1071 mlx5_cmd_host_pf_disable_hca(dev); 1072} 1073 1074/* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs 1075 * whichever are present on the eswitch. 1076 */ 1077int 1078mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, 1079 enum mlx5_eswitch_vport_event enabled_events) 1080{ 1081 int ret; 1082 1083 /* Enable PF vport */ 1084 ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_PF, enabled_events); 1085 if (ret) 1086 return ret; 1087 1088 /* Enable external host PF HCA */ 1089 ret = host_pf_enable_hca(esw->dev); 1090 if (ret) 1091 goto pf_hca_err; 1092 1093 /* Enable ECPF vport */ 1094 if (mlx5_ecpf_vport_exists(esw->dev)) { 1095 ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_ECPF, enabled_events); 1096 if (ret) 1097 goto ecpf_err; 1098 } 1099 1100 /* Enable VF vports */ 1101 ret = mlx5_eswitch_load_vf_vports(esw, esw->esw_funcs.num_vfs, 1102 enabled_events); 1103 if (ret) 1104 goto vf_err; 1105 return 0; 1106 1107vf_err: 1108 if (mlx5_ecpf_vport_exists(esw->dev)) 1109 mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF); 1110ecpf_err: 1111 host_pf_disable_hca(esw->dev); 1112pf_hca_err: 1113 mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF); 1114 return ret; 1115} 1116 1117/* mlx5_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs 1118 * whichever are previously enabled on the eswitch. 1119 */ 1120void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw) 1121{ 1122 mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); 1123 1124 if (mlx5_ecpf_vport_exists(esw->dev)) 1125 mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF); 1126 1127 host_pf_disable_hca(esw->dev); 1128 mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF); 1129} 1130 1131static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw) 1132{ 1133 struct devlink *devlink = priv_to_devlink(esw->dev); 1134 union devlink_param_value val; 1135 int err; 1136 1137 err = devlink_param_driverinit_value_get(devlink, 1138 MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 1139 &val); 1140 if (!err) { 1141 esw->params.large_group_num = val.vu32; 1142 } else { 1143 esw_warn(esw->dev, 1144 "Devlink can't get param fdb_large_groups, uses default (%d).\n", 1145 ESW_OFFLOADS_DEFAULT_NUM_GROUPS); 1146 esw->params.large_group_num = ESW_OFFLOADS_DEFAULT_NUM_GROUPS; 1147 } 1148} 1149 1150static void 1151mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs) 1152{ 1153 const u32 *out; 1154 1155 WARN_ON_ONCE(esw->mode != MLX5_ESWITCH_NONE); 1156 1157 if (num_vfs < 0) 1158 return; 1159 1160 if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) { 1161 esw->esw_funcs.num_vfs = num_vfs; 1162 return; 1163 } 1164 1165 out = mlx5_esw_query_functions(esw->dev); 1166 if (IS_ERR(out)) 1167 return; 1168 1169 esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out, 1170 host_params_context.host_num_of_vfs); 1171 kvfree(out); 1172} 1173 1174static void mlx5_esw_mode_change_notify(struct mlx5_eswitch *esw, u16 mode) 1175{ 1176 struct mlx5_esw_event_info info = {}; 1177 1178 info.new_mode = mode; 1179 1180 blocking_notifier_call_chain(&esw->n_head, 0, &info); 1181} 1182 1183static int mlx5_esw_acls_ns_init(struct mlx5_eswitch *esw) 1184{ 1185 struct mlx5_core_dev *dev = esw->dev; 1186 int total_vports; 1187 int err; 1188 1189 total_vports = mlx5_eswitch_get_total_vports(dev); 1190 1191 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) { 1192 err = mlx5_fs_egress_acls_init(dev, total_vports); 1193 if (err) 1194 return err; 1195 } else { 1196 esw_warn(dev, "engress ACL is not supported by FW\n"); 1197 } 1198 1199 if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) { 1200 err = mlx5_fs_ingress_acls_init(dev, total_vports); 1201 if (err) 1202 goto err; 1203 } else { 1204 esw_warn(dev, "ingress ACL is not supported by FW\n"); 1205 } 1206 return 0; 1207 1208err: 1209 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) 1210 mlx5_fs_egress_acls_cleanup(dev); 1211 return err; 1212} 1213 1214static void mlx5_esw_acls_ns_cleanup(struct mlx5_eswitch *esw) 1215{ 1216 struct mlx5_core_dev *dev = esw->dev; 1217 1218 if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) 1219 mlx5_fs_ingress_acls_cleanup(dev); 1220 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) 1221 mlx5_fs_egress_acls_cleanup(dev); 1222} 1223 1224/** 1225 * mlx5_eswitch_enable_locked - Enable eswitch 1226 * @esw: Pointer to eswitch 1227 * @mode: Eswitch mode to enable 1228 * @num_vfs: Enable eswitch for given number of VFs. This is optional. 1229 * Valid value are 0, > 0 and MLX5_ESWITCH_IGNORE_NUM_VFS. 1230 * Caller should pass num_vfs > 0 when enabling eswitch for 1231 * vf vports. Caller should pass num_vfs = 0, when eswitch 1232 * is enabled without sriov VFs or when caller 1233 * is unaware of the sriov state of the host PF on ECPF based 1234 * eswitch. Caller should pass < 0 when num_vfs should be 1235 * completely ignored. This is typically the case when eswitch 1236 * is enabled without sriov regardless of PF/ECPF system. 1237 * mlx5_eswitch_enable_locked() Enables eswitch in either legacy or offloads 1238 * mode. If num_vfs >=0 is provided, it setup VF related eswitch vports. 1239 * It returns 0 on success or error code on failure. 1240 */ 1241int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int mode, int num_vfs) 1242{ 1243 int err; 1244 1245 lockdep_assert_held(&esw->mode_lock); 1246 1247 if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) { 1248 esw_warn(esw->dev, "FDB is not supported, aborting ...\n"); 1249 return -EOPNOTSUPP; 1250 } 1251 1252 mlx5_eswitch_get_devlink_param(esw); 1253 1254 err = mlx5_esw_acls_ns_init(esw); 1255 if (err) 1256 return err; 1257 1258 mlx5_eswitch_update_num_of_vfs(esw, num_vfs); 1259 1260 esw->mode = mode; 1261 1262 if (mode == MLX5_ESWITCH_LEGACY) { 1263 err = esw_legacy_enable(esw); 1264 } else { 1265 mlx5_rescan_drivers(esw->dev); 1266 err = esw_offloads_enable(esw); 1267 } 1268 1269 if (err) 1270 goto abort; 1271 1272 mlx5_eswitch_event_handlers_register(esw); 1273 1274 esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n", 1275 mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", 1276 esw->esw_funcs.num_vfs, esw->enabled_vports); 1277 1278 mlx5_esw_mode_change_notify(esw, mode); 1279 1280 return 0; 1281 1282abort: 1283 esw->mode = MLX5_ESWITCH_NONE; 1284 1285 if (mode == MLX5_ESWITCH_OFFLOADS) 1286 mlx5_rescan_drivers(esw->dev); 1287 1288 mlx5_esw_acls_ns_cleanup(esw); 1289 return err; 1290} 1291 1292/** 1293 * mlx5_eswitch_enable - Enable eswitch 1294 * @esw: Pointer to eswitch 1295 * @num_vfs: Enable eswitch switch for given number of VFs. 1296 * Caller must pass num_vfs > 0 when enabling eswitch for 1297 * vf vports. 1298 * mlx5_eswitch_enable() returns 0 on success or error code on failure. 1299 */ 1300int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) 1301{ 1302 bool toggle_lag; 1303 int ret; 1304 1305 if (!mlx5_esw_allowed(esw)) 1306 return 0; 1307 1308 toggle_lag = esw->mode == MLX5_ESWITCH_NONE; 1309 1310 if (toggle_lag) 1311 mlx5_lag_disable_change(esw->dev); 1312 1313 down_write(&esw->mode_lock); 1314 if (esw->mode == MLX5_ESWITCH_NONE) { 1315 ret = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_LEGACY, num_vfs); 1316 } else { 1317 enum mlx5_eswitch_vport_event vport_events; 1318 1319 vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ? 1320 MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE; 1321 ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events); 1322 if (!ret) 1323 esw->esw_funcs.num_vfs = num_vfs; 1324 } 1325 up_write(&esw->mode_lock); 1326 1327 if (toggle_lag) 1328 mlx5_lag_enable_change(esw->dev); 1329 1330 return ret; 1331} 1332 1333void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw, bool clear_vf) 1334{ 1335 struct devlink *devlink = priv_to_devlink(esw->dev); 1336 int old_mode; 1337 1338 lockdep_assert_held_write(&esw->mode_lock); 1339 1340 if (esw->mode == MLX5_ESWITCH_NONE) 1341 return; 1342 1343 esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), active vports(%d)\n", 1344 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", 1345 esw->esw_funcs.num_vfs, esw->enabled_vports); 1346 1347 /* Notify eswitch users that it is exiting from current mode. 1348 * So that it can do necessary cleanup before the eswitch is disabled. 1349 */ 1350 mlx5_esw_mode_change_notify(esw, MLX5_ESWITCH_NONE); 1351 1352 mlx5_eswitch_event_handlers_unregister(esw); 1353 1354 if (esw->mode == MLX5_ESWITCH_LEGACY) 1355 esw_legacy_disable(esw); 1356 else if (esw->mode == MLX5_ESWITCH_OFFLOADS) 1357 esw_offloads_disable(esw); 1358 1359 old_mode = esw->mode; 1360 esw->mode = MLX5_ESWITCH_NONE; 1361 1362 if (old_mode == MLX5_ESWITCH_OFFLOADS) 1363 mlx5_rescan_drivers(esw->dev); 1364 1365 devlink_rate_nodes_destroy(devlink); 1366 1367 mlx5_esw_acls_ns_cleanup(esw); 1368 1369 if (clear_vf) 1370 mlx5_eswitch_clear_vf_vports_info(esw); 1371} 1372 1373void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf) 1374{ 1375 if (!mlx5_esw_allowed(esw)) 1376 return; 1377 1378 mlx5_lag_disable_change(esw->dev); 1379 down_write(&esw->mode_lock); 1380 mlx5_eswitch_disable_locked(esw, clear_vf); 1381 esw->esw_funcs.num_vfs = 0; 1382 up_write(&esw->mode_lock); 1383 mlx5_lag_enable_change(esw->dev); 1384} 1385 1386static int mlx5_query_hca_cap_host_pf(struct mlx5_core_dev *dev, void *out) 1387{ 1388 u16 opmod = (MLX5_CAP_GENERAL << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01); 1389 u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {}; 1390 1391 MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 1392 MLX5_SET(query_hca_cap_in, in, op_mod, opmod); 1393 MLX5_SET(query_hca_cap_in, in, function_id, MLX5_VPORT_PF); 1394 MLX5_SET(query_hca_cap_in, in, other_function, true); 1395 return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out); 1396} 1397 1398int mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev *dev, u16 *max_sfs, u16 *sf_base_id) 1399 1400{ 1401 int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); 1402 void *query_ctx; 1403 void *hca_caps; 1404 int err; 1405 1406 if (!mlx5_core_is_ecpf(dev)) { 1407 *max_sfs = 0; 1408 return 0; 1409 } 1410 1411 query_ctx = kzalloc(query_out_sz, GFP_KERNEL); 1412 if (!query_ctx) 1413 return -ENOMEM; 1414 1415 err = mlx5_query_hca_cap_host_pf(dev, query_ctx); 1416 if (err) 1417 goto out_free; 1418 1419 hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); 1420 *max_sfs = MLX5_GET(cmd_hca_cap, hca_caps, max_num_sf); 1421 *sf_base_id = MLX5_GET(cmd_hca_cap, hca_caps, sf_base_id); 1422 1423out_free: 1424 kfree(query_ctx); 1425 return err; 1426} 1427 1428static int mlx5_esw_vport_alloc(struct mlx5_eswitch *esw, struct mlx5_core_dev *dev, 1429 int index, u16 vport_num) 1430{ 1431 struct mlx5_vport *vport; 1432 int err; 1433 1434 vport = kzalloc(sizeof(*vport), GFP_KERNEL); 1435 if (!vport) 1436 return -ENOMEM; 1437 1438 vport->dev = esw->dev; 1439 vport->vport = vport_num; 1440 vport->index = index; 1441 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 1442 INIT_WORK(&vport->vport_change_handler, esw_vport_change_handler); 1443 err = xa_insert(&esw->vports, vport_num, vport, GFP_KERNEL); 1444 if (err) 1445 goto insert_err; 1446 1447 esw->total_vports++; 1448 return 0; 1449 1450insert_err: 1451 kfree(vport); 1452 return err; 1453} 1454 1455static void mlx5_esw_vport_free(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 1456{ 1457 xa_erase(&esw->vports, vport->vport); 1458 kfree(vport); 1459} 1460 1461static void mlx5_esw_vports_cleanup(struct mlx5_eswitch *esw) 1462{ 1463 struct mlx5_vport *vport; 1464 unsigned long i; 1465 1466 mlx5_esw_for_each_vport(esw, i, vport) 1467 mlx5_esw_vport_free(esw, vport); 1468 xa_destroy(&esw->vports); 1469} 1470 1471static int mlx5_esw_vports_init(struct mlx5_eswitch *esw) 1472{ 1473 struct mlx5_core_dev *dev = esw->dev; 1474 u16 max_host_pf_sfs; 1475 u16 base_sf_num; 1476 int idx = 0; 1477 int err; 1478 int i; 1479 1480 xa_init(&esw->vports); 1481 1482 err = mlx5_esw_vport_alloc(esw, dev, idx, MLX5_VPORT_PF); 1483 if (err) 1484 goto err; 1485 if (esw->first_host_vport == MLX5_VPORT_PF) 1486 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN); 1487 idx++; 1488 1489 for (i = 0; i < mlx5_core_max_vfs(dev); i++) { 1490 err = mlx5_esw_vport_alloc(esw, dev, idx, idx); 1491 if (err) 1492 goto err; 1493 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_VF); 1494 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN); 1495 idx++; 1496 } 1497 base_sf_num = mlx5_sf_start_function_id(dev); 1498 for (i = 0; i < mlx5_sf_max_functions(dev); i++) { 1499 err = mlx5_esw_vport_alloc(esw, dev, idx, base_sf_num + i); 1500 if (err) 1501 goto err; 1502 xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF); 1503 idx++; 1504 } 1505 1506 err = mlx5_esw_sf_max_hpf_functions(dev, &max_host_pf_sfs, &base_sf_num); 1507 if (err) 1508 goto err; 1509 for (i = 0; i < max_host_pf_sfs; i++) { 1510 err = mlx5_esw_vport_alloc(esw, dev, idx, base_sf_num + i); 1511 if (err) 1512 goto err; 1513 xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF); 1514 idx++; 1515 } 1516 1517 if (mlx5_ecpf_vport_exists(dev)) { 1518 err = mlx5_esw_vport_alloc(esw, dev, idx, MLX5_VPORT_ECPF); 1519 if (err) 1520 goto err; 1521 idx++; 1522 } 1523 err = mlx5_esw_vport_alloc(esw, dev, idx, MLX5_VPORT_UPLINK); 1524 if (err) 1525 goto err; 1526 return 0; 1527 1528err: 1529 mlx5_esw_vports_cleanup(esw); 1530 return err; 1531} 1532 1533int mlx5_eswitch_init(struct mlx5_core_dev *dev) 1534{ 1535 struct mlx5_eswitch *esw; 1536 int err; 1537 1538 if (!MLX5_VPORT_MANAGER(dev)) 1539 return 0; 1540 1541 esw = kzalloc(sizeof(*esw), GFP_KERNEL); 1542 if (!esw) 1543 return -ENOMEM; 1544 1545 esw->dev = dev; 1546 esw->manager_vport = mlx5_eswitch_manager_vport(dev); 1547 esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev); 1548 1549 esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq"); 1550 if (!esw->work_queue) { 1551 err = -ENOMEM; 1552 goto abort; 1553 } 1554 1555 err = mlx5_esw_vports_init(esw); 1556 if (err) 1557 goto abort; 1558 1559 err = esw_offloads_init_reps(esw); 1560 if (err) 1561 goto reps_err; 1562 1563 mutex_init(&esw->offloads.encap_tbl_lock); 1564 hash_init(esw->offloads.encap_tbl); 1565 mutex_init(&esw->offloads.decap_tbl_lock); 1566 hash_init(esw->offloads.decap_tbl); 1567 mlx5e_mod_hdr_tbl_init(&esw->offloads.mod_hdr); 1568 atomic64_set(&esw->offloads.num_flows, 0); 1569 ida_init(&esw->offloads.vport_metadata_ida); 1570 xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC); 1571 mutex_init(&esw->state_lock); 1572 init_rwsem(&esw->mode_lock); 1573 refcount_set(&esw->qos.refcnt, 0); 1574 1575 esw->enabled_vports = 0; 1576 esw->mode = MLX5_ESWITCH_NONE; 1577 esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE; 1578 if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) && 1579 MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap)) 1580 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; 1581 else 1582 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; 1583 if (MLX5_ESWITCH_MANAGER(dev) && 1584 mlx5_esw_vport_match_metadata_supported(esw)) 1585 esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA; 1586 1587 dev->priv.eswitch = esw; 1588 BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head); 1589 1590 esw_info(dev, 1591 "Total vports %d, per vport: max uc(%d) max mc(%d)\n", 1592 esw->total_vports, 1593 MLX5_MAX_UC_PER_VPORT(dev), 1594 MLX5_MAX_MC_PER_VPORT(dev)); 1595 return 0; 1596 1597reps_err: 1598 mlx5_esw_vports_cleanup(esw); 1599abort: 1600 if (esw->work_queue) 1601 destroy_workqueue(esw->work_queue); 1602 kfree(esw); 1603 return err; 1604} 1605 1606void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) 1607{ 1608 if (!esw || !MLX5_VPORT_MANAGER(esw->dev)) 1609 return; 1610 1611 esw_info(esw->dev, "cleanup\n"); 1612 1613 esw->dev->priv.eswitch = NULL; 1614 destroy_workqueue(esw->work_queue); 1615 WARN_ON(refcount_read(&esw->qos.refcnt)); 1616 mutex_destroy(&esw->state_lock); 1617 WARN_ON(!xa_empty(&esw->offloads.vhca_map)); 1618 xa_destroy(&esw->offloads.vhca_map); 1619 ida_destroy(&esw->offloads.vport_metadata_ida); 1620 mlx5e_mod_hdr_tbl_destroy(&esw->offloads.mod_hdr); 1621 mutex_destroy(&esw->offloads.encap_tbl_lock); 1622 mutex_destroy(&esw->offloads.decap_tbl_lock); 1623 esw_offloads_cleanup_reps(esw); 1624 mlx5_esw_vports_cleanup(esw); 1625 kfree(esw); 1626} 1627 1628/* Vport Administration */ 1629static int 1630mlx5_esw_set_vport_mac_locked(struct mlx5_eswitch *esw, 1631 struct mlx5_vport *evport, const u8 *mac) 1632{ 1633 u16 vport_num = evport->vport; 1634 u64 node_guid; 1635 int err = 0; 1636 1637 if (is_multicast_ether_addr(mac)) 1638 return -EINVAL; 1639 1640 if (evport->info.spoofchk && !is_valid_ether_addr(mac)) 1641 mlx5_core_warn(esw->dev, 1642 "Set invalid MAC while spoofchk is on, vport(%d)\n", 1643 vport_num); 1644 1645 err = mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, mac); 1646 if (err) { 1647 mlx5_core_warn(esw->dev, 1648 "Failed to mlx5_modify_nic_vport_mac vport(%d) err=(%d)\n", 1649 vport_num, err); 1650 return err; 1651 } 1652 1653 node_guid_gen_from_mac(&node_guid, mac); 1654 err = mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, node_guid); 1655 if (err) 1656 mlx5_core_warn(esw->dev, 1657 "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n", 1658 vport_num, err); 1659 1660 ether_addr_copy(evport->info.mac, mac); 1661 evport->info.node_guid = node_guid; 1662 if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) 1663 err = esw_acl_ingress_lgcy_setup(esw, evport); 1664 1665 return err; 1666} 1667 1668int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, 1669 u16 vport, const u8 *mac) 1670{ 1671 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 1672 int err = 0; 1673 1674 if (IS_ERR(evport)) 1675 return PTR_ERR(evport); 1676 1677 mutex_lock(&esw->state_lock); 1678 err = mlx5_esw_set_vport_mac_locked(esw, evport, mac); 1679 mutex_unlock(&esw->state_lock); 1680 return err; 1681} 1682 1683static bool mlx5_esw_check_port_type(struct mlx5_eswitch *esw, u16 vport_num, xa_mark_t mark) 1684{ 1685 struct mlx5_vport *vport; 1686 1687 vport = mlx5_eswitch_get_vport(esw, vport_num); 1688 if (IS_ERR(vport)) 1689 return false; 1690 1691 return xa_get_mark(&esw->vports, vport_num, mark); 1692} 1693 1694bool mlx5_eswitch_is_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) 1695{ 1696 return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_VF); 1697} 1698 1699bool mlx5_esw_is_sf_vport(struct mlx5_eswitch *esw, u16 vport_num) 1700{ 1701 return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_SF); 1702} 1703 1704int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, 1705 u16 vport, int link_state) 1706{ 1707 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 1708 int opmod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT; 1709 int other_vport = 1; 1710 int err = 0; 1711 1712 if (!mlx5_esw_allowed(esw)) 1713 return -EPERM; 1714 if (IS_ERR(evport)) 1715 return PTR_ERR(evport); 1716 1717 if (vport == MLX5_VPORT_UPLINK) { 1718 opmod = MLX5_VPORT_STATE_OP_MOD_UPLINK; 1719 other_vport = 0; 1720 vport = 0; 1721 } 1722 mutex_lock(&esw->state_lock); 1723 if (esw->mode != MLX5_ESWITCH_LEGACY) { 1724 err = -EOPNOTSUPP; 1725 goto unlock; 1726 } 1727 1728 err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, other_vport, link_state); 1729 if (err) { 1730 mlx5_core_warn(esw->dev, "Failed to set vport %d link state, opmod = %d, err = %d", 1731 vport, opmod, err); 1732 goto unlock; 1733 } 1734 1735 evport->info.link_state = link_state; 1736 1737unlock: 1738 mutex_unlock(&esw->state_lock); 1739 return err; 1740} 1741 1742int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw, 1743 u16 vport, struct ifla_vf_info *ivi) 1744{ 1745 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 1746 1747 if (IS_ERR(evport)) 1748 return PTR_ERR(evport); 1749 1750 memset(ivi, 0, sizeof(*ivi)); 1751 ivi->vf = vport - 1; 1752 1753 mutex_lock(&esw->state_lock); 1754 ether_addr_copy(ivi->mac, evport->info.mac); 1755 ivi->linkstate = evport->info.link_state; 1756 ivi->vlan = evport->info.vlan; 1757 ivi->qos = evport->info.qos; 1758 ivi->spoofchk = evport->info.spoofchk; 1759 ivi->trusted = evport->info.trusted; 1760 if (evport->qos.enabled) { 1761 ivi->min_tx_rate = evport->qos.min_rate; 1762 ivi->max_tx_rate = evport->qos.max_rate; 1763 } 1764 mutex_unlock(&esw->state_lock); 1765 1766 return 0; 1767} 1768 1769int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, 1770 u16 vport, u16 vlan, u8 qos, u8 set_flags) 1771{ 1772 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 1773 int err = 0; 1774 1775 if (IS_ERR(evport)) 1776 return PTR_ERR(evport); 1777 if (vlan > 4095 || qos > 7) 1778 return -EINVAL; 1779 1780 err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags); 1781 if (err) 1782 return err; 1783 1784 evport->info.vlan = vlan; 1785 evport->info.qos = qos; 1786 if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) { 1787 err = esw_acl_ingress_lgcy_setup(esw, evport); 1788 if (err) 1789 return err; 1790 err = esw_acl_egress_lgcy_setup(esw, evport); 1791 } 1792 1793 return err; 1794} 1795 1796int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, 1797 u16 vport_num, 1798 struct ifla_vf_stats *vf_stats) 1799{ 1800 struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); 1801 int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out); 1802 u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {}; 1803 struct mlx5_vport_drop_stats stats = {}; 1804 int err = 0; 1805 u32 *out; 1806 1807 if (IS_ERR(vport)) 1808 return PTR_ERR(vport); 1809 1810 out = kvzalloc(outlen, GFP_KERNEL); 1811 if (!out) 1812 return -ENOMEM; 1813 1814 MLX5_SET(query_vport_counter_in, in, opcode, 1815 MLX5_CMD_OP_QUERY_VPORT_COUNTER); 1816 MLX5_SET(query_vport_counter_in, in, op_mod, 0); 1817 MLX5_SET(query_vport_counter_in, in, vport_number, vport->vport); 1818 MLX5_SET(query_vport_counter_in, in, other_vport, 1); 1819 1820 err = mlx5_cmd_exec_inout(esw->dev, query_vport_counter, in, out); 1821 if (err) 1822 goto free_out; 1823 1824 #define MLX5_GET_CTR(p, x) \ 1825 MLX5_GET64(query_vport_counter_out, p, x) 1826 1827 memset(vf_stats, 0, sizeof(*vf_stats)); 1828 vf_stats->rx_packets = 1829 MLX5_GET_CTR(out, received_eth_unicast.packets) + 1830 MLX5_GET_CTR(out, received_ib_unicast.packets) + 1831 MLX5_GET_CTR(out, received_eth_multicast.packets) + 1832 MLX5_GET_CTR(out, received_ib_multicast.packets) + 1833 MLX5_GET_CTR(out, received_eth_broadcast.packets); 1834 1835 vf_stats->rx_bytes = 1836 MLX5_GET_CTR(out, received_eth_unicast.octets) + 1837 MLX5_GET_CTR(out, received_ib_unicast.octets) + 1838 MLX5_GET_CTR(out, received_eth_multicast.octets) + 1839 MLX5_GET_CTR(out, received_ib_multicast.octets) + 1840 MLX5_GET_CTR(out, received_eth_broadcast.octets); 1841 1842 vf_stats->tx_packets = 1843 MLX5_GET_CTR(out, transmitted_eth_unicast.packets) + 1844 MLX5_GET_CTR(out, transmitted_ib_unicast.packets) + 1845 MLX5_GET_CTR(out, transmitted_eth_multicast.packets) + 1846 MLX5_GET_CTR(out, transmitted_ib_multicast.packets) + 1847 MLX5_GET_CTR(out, transmitted_eth_broadcast.packets); 1848 1849 vf_stats->tx_bytes = 1850 MLX5_GET_CTR(out, transmitted_eth_unicast.octets) + 1851 MLX5_GET_CTR(out, transmitted_ib_unicast.octets) + 1852 MLX5_GET_CTR(out, transmitted_eth_multicast.octets) + 1853 MLX5_GET_CTR(out, transmitted_ib_multicast.octets) + 1854 MLX5_GET_CTR(out, transmitted_eth_broadcast.octets); 1855 1856 vf_stats->multicast = 1857 MLX5_GET_CTR(out, received_eth_multicast.packets) + 1858 MLX5_GET_CTR(out, received_ib_multicast.packets); 1859 1860 vf_stats->broadcast = 1861 MLX5_GET_CTR(out, received_eth_broadcast.packets); 1862 1863 err = mlx5_esw_query_vport_drop_stats(esw->dev, vport, &stats); 1864 if (err) 1865 goto free_out; 1866 vf_stats->rx_dropped = stats.rx_dropped; 1867 vf_stats->tx_dropped = stats.tx_dropped; 1868 1869free_out: 1870 kvfree(out); 1871 return err; 1872} 1873 1874u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev) 1875{ 1876 struct mlx5_eswitch *esw = dev->priv.eswitch; 1877 1878 return mlx5_esw_allowed(esw) ? esw->mode : MLX5_ESWITCH_NONE; 1879} 1880EXPORT_SYMBOL_GPL(mlx5_eswitch_mode); 1881 1882enum devlink_eswitch_encap_mode 1883mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev) 1884{ 1885 struct mlx5_eswitch *esw; 1886 1887 esw = dev->priv.eswitch; 1888 return (mlx5_eswitch_mode(dev) == MLX5_ESWITCH_OFFLOADS) ? esw->offloads.encap : 1889 DEVLINK_ESWITCH_ENCAP_MODE_NONE; 1890} 1891EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode); 1892 1893bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0, 1894 struct mlx5_core_dev *dev1) 1895{ 1896 return (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS && 1897 dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS); 1898} 1899 1900int mlx5_esw_event_notifier_register(struct mlx5_eswitch *esw, struct notifier_block *nb) 1901{ 1902 return blocking_notifier_chain_register(&esw->n_head, nb); 1903} 1904 1905void mlx5_esw_event_notifier_unregister(struct mlx5_eswitch *esw, struct notifier_block *nb) 1906{ 1907 blocking_notifier_chain_unregister(&esw->n_head, nb); 1908} 1909 1910/** 1911 * mlx5_esw_hold() - Try to take a read lock on esw mode lock. 1912 * @mdev: mlx5 core device. 1913 * 1914 * Should be called by esw resources callers. 1915 * 1916 * Return: true on success or false. 1917 */ 1918bool mlx5_esw_hold(struct mlx5_core_dev *mdev) 1919{ 1920 struct mlx5_eswitch *esw = mdev->priv.eswitch; 1921 1922 /* e.g. VF doesn't have eswitch so nothing to do */ 1923 if (!mlx5_esw_allowed(esw)) 1924 return true; 1925 1926 if (down_read_trylock(&esw->mode_lock) != 0) 1927 return true; 1928 1929 return false; 1930} 1931 1932/** 1933 * mlx5_esw_release() - Release a read lock on esw mode lock. 1934 * @mdev: mlx5 core device. 1935 */ 1936void mlx5_esw_release(struct mlx5_core_dev *mdev) 1937{ 1938 struct mlx5_eswitch *esw = mdev->priv.eswitch; 1939 1940 if (mlx5_esw_allowed(esw)) 1941 up_read(&esw->mode_lock); 1942} 1943 1944/** 1945 * mlx5_esw_get() - Increase esw user count. 1946 * @mdev: mlx5 core device. 1947 */ 1948void mlx5_esw_get(struct mlx5_core_dev *mdev) 1949{ 1950 struct mlx5_eswitch *esw = mdev->priv.eswitch; 1951 1952 if (mlx5_esw_allowed(esw)) 1953 atomic64_inc(&esw->user_count); 1954} 1955 1956/** 1957 * mlx5_esw_put() - Decrease esw user count. 1958 * @mdev: mlx5 core device. 1959 */ 1960void mlx5_esw_put(struct mlx5_core_dev *mdev) 1961{ 1962 struct mlx5_eswitch *esw = mdev->priv.eswitch; 1963 1964 if (mlx5_esw_allowed(esw)) 1965 atomic64_dec_if_positive(&esw->user_count); 1966} 1967 1968/** 1969 * mlx5_esw_try_lock() - Take a write lock on esw mode lock. 1970 * @esw: eswitch device. 1971 * 1972 * Should be called by esw mode change routine. 1973 * 1974 * Return: 1975 * * 0 - esw mode if successfully locked and refcount is 0. 1976 * * -EBUSY - refcount is not 0. 1977 * * -EINVAL - In the middle of switching mode or lock is already held. 1978 */ 1979int mlx5_esw_try_lock(struct mlx5_eswitch *esw) 1980{ 1981 if (down_write_trylock(&esw->mode_lock) == 0) 1982 return -EINVAL; 1983 1984 if (atomic64_read(&esw->user_count) > 0) { 1985 up_write(&esw->mode_lock); 1986 return -EBUSY; 1987 } 1988 1989 return esw->mode; 1990} 1991 1992/** 1993 * mlx5_esw_unlock() - Release write lock on esw mode lock 1994 * @esw: eswitch device. 1995 */ 1996void mlx5_esw_unlock(struct mlx5_eswitch *esw) 1997{ 1998 if (!mlx5_esw_allowed(esw)) 1999 return; 2000 up_write(&esw->mode_lock); 2001} 2002 2003/** 2004 * mlx5_eswitch_get_total_vports - Get total vports of the eswitch 2005 * 2006 * @dev: Pointer to core device 2007 * 2008 * mlx5_eswitch_get_total_vports returns total number of eswitch vports. 2009 */ 2010u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev) 2011{ 2012 struct mlx5_eswitch *esw; 2013 2014 esw = dev->priv.eswitch; 2015 return mlx5_esw_allowed(esw) ? esw->total_vports : 0; 2016} 2017EXPORT_SYMBOL_GPL(mlx5_eswitch_get_total_vports); 2018 2019/** 2020 * mlx5_eswitch_get_core_dev - Get the mdev device 2021 * @esw : eswitch device. 2022 * 2023 * Return the mellanox core device which manages the eswitch. 2024 */ 2025struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw) 2026{ 2027 return mlx5_esw_allowed(esw) ? esw->dev : NULL; 2028} 2029EXPORT_SYMBOL(mlx5_eswitch_get_core_dev);