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/debugfs.h> 35 #include <linux/mlx5/driver.h> 36 #include <linux/mlx5/mlx5_ifc.h> 37 #include <linux/mlx5/vport.h> 38 #include <linux/mlx5/fs.h> 39 #include <linux/mlx5/mpfs.h> 40 #include "esw/acl/lgcy.h" 41 #include "esw/legacy.h" 42 #include "esw/qos.h" 43 #include "mlx5_core.h" 44 #include "lib/eq.h" 45 #include "lag/lag.h" 46 #include "eswitch.h" 47 #include "fs_core.h" 48 #include "devlink.h" 49 #include "ecpf.h" 50 #include "en/mod_hdr.h" 51 #include "en_accel/ipsec.h" 52 53 enum { 54 MLX5_ACTION_NONE = 0, 55 MLX5_ACTION_ADD = 1, 56 MLX5_ACTION_DEL = 2, 57 }; 58 59 /* Vport UC/MC hash node */ 60 struct vport_addr { 61 struct l2addr_node node; 62 u8 action; 63 u16 vport; 64 struct mlx5_flow_handle *flow_rule; 65 bool mpfs; /* UC MAC was added to MPFs */ 66 /* A flag indicating that mac was added due to mc promiscuous vport */ 67 bool mc_promisc; 68 }; 69 70 static int mlx5_eswitch_check(const struct mlx5_core_dev *dev) 71 { 72 if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) 73 return -EOPNOTSUPP; 74 75 if (!MLX5_ESWITCH_MANAGER(dev)) 76 return -EOPNOTSUPP; 77 78 return 0; 79 } 80 81 static struct mlx5_eswitch *__mlx5_devlink_eswitch_get(struct devlink *devlink, bool check) 82 { 83 struct mlx5_core_dev *dev = devlink_priv(devlink); 84 int err; 85 86 if (check) { 87 err = mlx5_eswitch_check(dev); 88 if (err) 89 return ERR_PTR(err); 90 } 91 92 return dev->priv.eswitch; 93 } 94 95 struct mlx5_eswitch *__must_check 96 mlx5_devlink_eswitch_get(struct devlink *devlink) 97 { 98 return __mlx5_devlink_eswitch_get(devlink, true); 99 } 100 101 struct mlx5_eswitch *mlx5_devlink_eswitch_nocheck_get(struct devlink *devlink) 102 { 103 return __mlx5_devlink_eswitch_get(devlink, false); 104 } 105 106 struct mlx5_vport *__must_check 107 mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num) 108 { 109 struct mlx5_vport *vport; 110 111 if (!esw) 112 return ERR_PTR(-EPERM); 113 114 vport = xa_load(&esw->vports, vport_num); 115 if (!vport) { 116 esw_debug(esw->dev, "vport out of range: num(0x%x)\n", vport_num); 117 return ERR_PTR(-EINVAL); 118 } 119 return vport; 120 } 121 122 static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport, 123 u32 events_mask) 124 { 125 u32 in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)] = {}; 126 void *nic_vport_ctx; 127 128 MLX5_SET(modify_nic_vport_context_in, in, 129 opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 130 MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1); 131 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 132 if (vport || mlx5_core_is_ecpf(dev)) 133 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 134 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, 135 in, nic_vport_context); 136 137 MLX5_SET(nic_vport_context, nic_vport_ctx, arm_change_event, 1); 138 139 if (events_mask & MLX5_VPORT_UC_ADDR_CHANGE) 140 MLX5_SET(nic_vport_context, nic_vport_ctx, 141 event_on_uc_address_change, 1); 142 if (events_mask & MLX5_VPORT_MC_ADDR_CHANGE) 143 MLX5_SET(nic_vport_context, nic_vport_ctx, 144 event_on_mc_address_change, 1); 145 if (events_mask & MLX5_VPORT_PROMISC_CHANGE) 146 MLX5_SET(nic_vport_context, nic_vport_ctx, 147 event_on_promisc_change, 1); 148 149 return mlx5_cmd_exec_in(dev, modify_nic_vport_context, in); 150 } 151 152 /* E-Switch vport context HW commands */ 153 int mlx5_eswitch_modify_esw_vport_context(struct mlx5_core_dev *dev, u16 vport, 154 bool other_vport, void *in) 155 { 156 MLX5_SET(modify_esw_vport_context_in, in, opcode, 157 MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT); 158 MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport); 159 MLX5_SET(modify_esw_vport_context_in, in, other_vport, other_vport); 160 return mlx5_cmd_exec_in(dev, modify_esw_vport_context, in); 161 } 162 163 static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u16 vport, 164 u16 vlan, u8 qos, u8 set_flags) 165 { 166 u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {}; 167 168 if (!MLX5_CAP_ESW(dev, vport_cvlan_strip) || 169 !MLX5_CAP_ESW(dev, vport_cvlan_insert_if_not_exist)) 170 return -EOPNOTSUPP; 171 172 esw_debug(dev, "Set Vport[%d] VLAN %d qos %d set=%x\n", 173 vport, vlan, qos, set_flags); 174 175 if (set_flags & SET_VLAN_STRIP) 176 MLX5_SET(modify_esw_vport_context_in, in, 177 esw_vport_context.vport_cvlan_strip, 1); 178 179 if (set_flags & SET_VLAN_INSERT) { 180 if (MLX5_CAP_ESW(dev, vport_cvlan_insert_always)) { 181 /* insert either if vlan exist in packet or not */ 182 MLX5_SET(modify_esw_vport_context_in, in, 183 esw_vport_context.vport_cvlan_insert, 184 MLX5_VPORT_CVLAN_INSERT_ALWAYS); 185 } else { 186 /* insert only if no vlan in packet */ 187 MLX5_SET(modify_esw_vport_context_in, in, 188 esw_vport_context.vport_cvlan_insert, 189 MLX5_VPORT_CVLAN_INSERT_WHEN_NO_CVLAN); 190 } 191 MLX5_SET(modify_esw_vport_context_in, in, 192 esw_vport_context.cvlan_pcp, qos); 193 MLX5_SET(modify_esw_vport_context_in, in, 194 esw_vport_context.cvlan_id, vlan); 195 } 196 197 MLX5_SET(modify_esw_vport_context_in, in, 198 field_select.vport_cvlan_strip, 1); 199 MLX5_SET(modify_esw_vport_context_in, in, 200 field_select.vport_cvlan_insert, 1); 201 202 return mlx5_eswitch_modify_esw_vport_context(dev, vport, true, in); 203 } 204 205 /* E-Switch FDB */ 206 static struct mlx5_flow_handle * 207 __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u16 vport, bool rx_rule, 208 u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN]) 209 { 210 int match_header = (is_zero_ether_addr(mac_c) ? 0 : 211 MLX5_MATCH_OUTER_HEADERS); 212 struct mlx5_flow_handle *flow_rule = NULL; 213 struct mlx5_flow_act flow_act = {0}; 214 struct mlx5_flow_destination dest = {}; 215 struct mlx5_flow_spec *spec; 216 void *mv_misc = NULL; 217 void *mc_misc = NULL; 218 u8 *dmac_v = NULL; 219 u8 *dmac_c = NULL; 220 221 if (rx_rule) 222 match_header |= MLX5_MATCH_MISC_PARAMETERS; 223 224 spec = kvzalloc_obj(*spec); 225 if (!spec) 226 return NULL; 227 228 dmac_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, 229 outer_headers.dmac_47_16); 230 dmac_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 231 outer_headers.dmac_47_16); 232 233 if (match_header & MLX5_MATCH_OUTER_HEADERS) { 234 ether_addr_copy(dmac_v, mac_v); 235 ether_addr_copy(dmac_c, mac_c); 236 } 237 238 if (match_header & MLX5_MATCH_MISC_PARAMETERS) { 239 mv_misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, 240 misc_parameters); 241 mc_misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 242 misc_parameters); 243 MLX5_SET(fte_match_set_misc, mv_misc, source_port, MLX5_VPORT_UPLINK); 244 MLX5_SET_TO_ONES(fte_match_set_misc, mc_misc, source_port); 245 } 246 247 dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; 248 dest.vport.num = vport; 249 250 esw_debug(esw->dev, 251 "\tFDB add rule dmac_v(%pM) dmac_c(%pM) -> vport(%d)\n", 252 dmac_v, dmac_c, vport); 253 spec->match_criteria_enable = match_header; 254 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 255 flow_rule = 256 mlx5_add_flow_rules(esw->fdb_table.legacy.fdb, spec, 257 &flow_act, &dest, 1); 258 if (IS_ERR(flow_rule)) { 259 esw_warn(esw->dev, 260 "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%pe)\n", 261 dmac_v, dmac_c, vport, flow_rule); 262 flow_rule = NULL; 263 } 264 265 kvfree(spec); 266 return flow_rule; 267 } 268 269 static struct mlx5_flow_handle * 270 esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u16 vport) 271 { 272 u8 mac_c[ETH_ALEN]; 273 274 eth_broadcast_addr(mac_c); 275 return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac); 276 } 277 278 static struct mlx5_flow_handle * 279 esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u16 vport) 280 { 281 u8 mac_c[ETH_ALEN]; 282 u8 mac_v[ETH_ALEN]; 283 284 eth_zero_addr(mac_c); 285 eth_zero_addr(mac_v); 286 mac_c[0] = 0x01; 287 mac_v[0] = 0x01; 288 return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac_v); 289 } 290 291 static struct mlx5_flow_handle * 292 esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport) 293 { 294 u8 mac_c[ETH_ALEN]; 295 u8 mac_v[ETH_ALEN]; 296 297 eth_zero_addr(mac_c); 298 eth_zero_addr(mac_v); 299 return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v); 300 } 301 302 /* E-Switch vport UC/MC lists management */ 303 typedef int (*vport_addr_action)(struct mlx5_eswitch *esw, 304 struct vport_addr *vaddr); 305 306 static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) 307 { 308 u8 *mac = vaddr->node.addr; 309 u16 vport = vaddr->vport; 310 int err; 311 312 /* Skip mlx5_mpfs_add_mac for eswitch_managers, 313 * it is already done by its netdev in mlx5e_execute_l2_action 314 */ 315 if (mlx5_esw_is_manager_vport(esw, vport)) 316 goto fdb_add; 317 318 err = mlx5_mpfs_add_mac(esw->dev, mac); 319 if (err) { 320 esw_warn(esw->dev, 321 "Failed to add L2 table mac(%pM) for vport(0x%x), err(%d)\n", 322 mac, vport, err); 323 return err; 324 } 325 vaddr->mpfs = true; 326 327 fdb_add: 328 /* SRIOV is enabled: Forward UC MAC to vport */ 329 if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY) { 330 vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport); 331 332 esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n", 333 vport, mac, vaddr->flow_rule); 334 } 335 336 return 0; 337 } 338 339 static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) 340 { 341 u8 *mac = vaddr->node.addr; 342 u16 vport = vaddr->vport; 343 int err = 0; 344 345 /* Skip mlx5_mpfs_del_mac for eswitch managers, 346 * it is already done by its netdev in mlx5e_execute_l2_action 347 */ 348 if (!vaddr->mpfs || mlx5_esw_is_manager_vport(esw, vport)) 349 goto fdb_del; 350 351 err = mlx5_mpfs_del_mac(esw->dev, mac); 352 if (err) 353 esw_warn(esw->dev, 354 "Failed to del L2 table mac(%pM) for vport(%d), err(%d)\n", 355 mac, vport, err); 356 vaddr->mpfs = false; 357 358 fdb_del: 359 if (vaddr->flow_rule) 360 mlx5_del_flow_rules(vaddr->flow_rule); 361 vaddr->flow_rule = NULL; 362 363 return 0; 364 } 365 366 static void update_allmulti_vports(struct mlx5_eswitch *esw, 367 struct vport_addr *vaddr, 368 struct esw_mc_addr *esw_mc) 369 { 370 u8 *mac = vaddr->node.addr; 371 struct mlx5_vport *vport; 372 unsigned long i; 373 u16 vport_num; 374 375 mlx5_esw_for_each_vport(esw, i, vport) { 376 struct hlist_head *vport_hash = vport->mc_list; 377 struct vport_addr *iter_vaddr = 378 l2addr_hash_find(vport_hash, 379 mac, 380 struct vport_addr); 381 vport_num = vport->vport; 382 if (IS_ERR_OR_NULL(vport->allmulti_rule) || 383 vaddr->vport == vport_num) 384 continue; 385 switch (vaddr->action) { 386 case MLX5_ACTION_ADD: 387 if (iter_vaddr) 388 continue; 389 iter_vaddr = l2addr_hash_add(vport_hash, mac, 390 struct vport_addr, 391 GFP_KERNEL); 392 if (!iter_vaddr) { 393 esw_warn(esw->dev, 394 "ALL-MULTI: Failed to add MAC(%pM) to vport[%d] DB\n", 395 mac, vport_num); 396 continue; 397 } 398 iter_vaddr->vport = vport_num; 399 iter_vaddr->flow_rule = 400 esw_fdb_set_vport_rule(esw, 401 mac, 402 vport_num); 403 iter_vaddr->mc_promisc = true; 404 break; 405 case MLX5_ACTION_DEL: 406 if (!iter_vaddr) 407 continue; 408 mlx5_del_flow_rules(iter_vaddr->flow_rule); 409 l2addr_hash_del(iter_vaddr); 410 break; 411 } 412 } 413 } 414 415 static int esw_add_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) 416 { 417 struct hlist_head *hash = esw->mc_table; 418 struct esw_mc_addr *esw_mc; 419 u8 *mac = vaddr->node.addr; 420 u16 vport = vaddr->vport; 421 422 if (!esw->fdb_table.legacy.fdb) 423 return 0; 424 425 esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr); 426 if (esw_mc) 427 goto add; 428 429 esw_mc = l2addr_hash_add(hash, mac, struct esw_mc_addr, GFP_KERNEL); 430 if (!esw_mc) 431 return -ENOMEM; 432 433 esw_mc->uplink_rule = /* Forward MC MAC to Uplink */ 434 esw_fdb_set_vport_rule(esw, mac, MLX5_VPORT_UPLINK); 435 436 /* Add this multicast mac to all the mc promiscuous vports */ 437 update_allmulti_vports(esw, vaddr, esw_mc); 438 439 add: 440 /* If the multicast mac is added as a result of mc promiscuous vport, 441 * don't increment the multicast ref count 442 */ 443 if (!vaddr->mc_promisc) 444 esw_mc->refcnt++; 445 446 /* Forward MC MAC to vport */ 447 vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport); 448 esw_debug(esw->dev, 449 "\tADDED MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n", 450 vport, mac, vaddr->flow_rule, 451 esw_mc->refcnt, esw_mc->uplink_rule); 452 return 0; 453 } 454 455 static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) 456 { 457 struct hlist_head *hash = esw->mc_table; 458 struct esw_mc_addr *esw_mc; 459 u8 *mac = vaddr->node.addr; 460 u16 vport = vaddr->vport; 461 462 if (!esw->fdb_table.legacy.fdb) 463 return 0; 464 465 esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr); 466 if (!esw_mc) { 467 esw_warn(esw->dev, 468 "Failed to find eswitch MC addr for MAC(%pM) vport(%d)", 469 mac, vport); 470 return -EINVAL; 471 } 472 esw_debug(esw->dev, 473 "\tDELETE MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n", 474 vport, mac, vaddr->flow_rule, esw_mc->refcnt, 475 esw_mc->uplink_rule); 476 477 if (vaddr->flow_rule) 478 mlx5_del_flow_rules(vaddr->flow_rule); 479 vaddr->flow_rule = NULL; 480 481 /* If the multicast mac is added as a result of mc promiscuous vport, 482 * don't decrement the multicast ref count. 483 */ 484 if (vaddr->mc_promisc || (--esw_mc->refcnt > 0)) 485 return 0; 486 487 /* Remove this multicast mac from all the mc promiscuous vports */ 488 update_allmulti_vports(esw, vaddr, esw_mc); 489 490 if (esw_mc->uplink_rule) 491 mlx5_del_flow_rules(esw_mc->uplink_rule); 492 493 l2addr_hash_del(esw_mc); 494 return 0; 495 } 496 497 /* Apply vport UC/MC list to HW l2 table and FDB table */ 498 static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw, 499 struct mlx5_vport *vport, int list_type) 500 { 501 bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC; 502 vport_addr_action vport_addr_add; 503 vport_addr_action vport_addr_del; 504 struct vport_addr *addr; 505 struct l2addr_node *node; 506 struct hlist_head *hash; 507 struct hlist_node *tmp; 508 int hi; 509 510 vport_addr_add = is_uc ? esw_add_uc_addr : 511 esw_add_mc_addr; 512 vport_addr_del = is_uc ? esw_del_uc_addr : 513 esw_del_mc_addr; 514 515 hash = is_uc ? vport->uc_list : vport->mc_list; 516 for_each_l2hash_node(node, tmp, hash, hi) { 517 addr = container_of(node, struct vport_addr, node); 518 switch (addr->action) { 519 case MLX5_ACTION_ADD: 520 vport_addr_add(esw, addr); 521 addr->action = MLX5_ACTION_NONE; 522 break; 523 case MLX5_ACTION_DEL: 524 vport_addr_del(esw, addr); 525 l2addr_hash_del(addr); 526 break; 527 } 528 } 529 } 530 531 /* Sync vport UC/MC list from vport context */ 532 static void esw_update_vport_addr_list(struct mlx5_eswitch *esw, 533 struct mlx5_vport *vport, int list_type) 534 { 535 bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC; 536 u8 (*mac_list)[ETH_ALEN] = NULL; 537 struct l2addr_node *node; 538 struct vport_addr *addr; 539 struct hlist_head *hash; 540 struct hlist_node *tmp; 541 int size = 0; 542 int err; 543 int hi; 544 int i; 545 546 hash = is_uc ? vport->uc_list : vport->mc_list; 547 548 for_each_l2hash_node(node, tmp, hash, hi) { 549 addr = container_of(node, struct vport_addr, node); 550 addr->action = MLX5_ACTION_DEL; 551 } 552 553 if (!vport->enabled) 554 goto out; 555 556 err = mlx5_query_nic_vport_mac_list(esw->dev, vport->vport, list_type, 557 &mac_list, &size); 558 if (err) 559 goto out; 560 esw_debug(esw->dev, "vport[%d] context update %s list size (%d)\n", 561 vport->vport, is_uc ? "UC" : "MC", size); 562 563 for (i = 0; i < size; i++) { 564 if (is_uc && !is_valid_ether_addr(mac_list[i])) 565 continue; 566 567 if (!is_uc && !is_multicast_ether_addr(mac_list[i])) 568 continue; 569 570 addr = l2addr_hash_find(hash, mac_list[i], struct vport_addr); 571 if (addr) { 572 addr->action = MLX5_ACTION_NONE; 573 /* If this mac was previously added because of allmulti 574 * promiscuous rx mode, its now converted to be original 575 * vport mac. 576 */ 577 if (addr->mc_promisc) { 578 struct esw_mc_addr *esw_mc = 579 l2addr_hash_find(esw->mc_table, 580 mac_list[i], 581 struct esw_mc_addr); 582 if (!esw_mc) { 583 esw_warn(esw->dev, 584 "Failed to MAC(%pM) in mcast DB\n", 585 mac_list[i]); 586 continue; 587 } 588 esw_mc->refcnt++; 589 addr->mc_promisc = false; 590 } 591 continue; 592 } 593 594 addr = l2addr_hash_add(hash, mac_list[i], struct vport_addr, 595 GFP_KERNEL); 596 if (!addr) { 597 esw_warn(esw->dev, 598 "Failed to add MAC(%pM) to vport[%d] DB\n", 599 mac_list[i], vport->vport); 600 continue; 601 } 602 addr->vport = vport->vport; 603 addr->action = MLX5_ACTION_ADD; 604 } 605 out: 606 kfree(mac_list); 607 } 608 609 /* Sync vport UC/MC list from vport context 610 * Must be called after esw_update_vport_addr_list 611 */ 612 static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, 613 struct mlx5_vport *vport) 614 { 615 struct l2addr_node *node; 616 struct vport_addr *addr; 617 struct hlist_head *hash; 618 struct hlist_node *tmp; 619 int hi; 620 621 hash = vport->mc_list; 622 623 for_each_l2hash_node(node, tmp, esw->mc_table, hi) { 624 u8 *mac = node->addr; 625 626 addr = l2addr_hash_find(hash, mac, struct vport_addr); 627 if (addr) { 628 if (addr->action == MLX5_ACTION_DEL) 629 addr->action = MLX5_ACTION_NONE; 630 continue; 631 } 632 addr = l2addr_hash_add(hash, mac, struct vport_addr, 633 GFP_KERNEL); 634 if (!addr) { 635 esw_warn(esw->dev, 636 "Failed to add allmulti MAC(%pM) to vport[%d] DB\n", 637 mac, vport->vport); 638 continue; 639 } 640 addr->vport = vport->vport; 641 addr->action = MLX5_ACTION_ADD; 642 addr->mc_promisc = true; 643 } 644 } 645 646 /* Apply vport rx mode to HW FDB table */ 647 static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, 648 struct mlx5_vport *vport, 649 bool promisc, bool mc_promisc) 650 { 651 struct esw_mc_addr *allmulti_addr = &esw->mc_promisc; 652 653 if (IS_ERR_OR_NULL(vport->allmulti_rule) != mc_promisc) 654 goto promisc; 655 656 if (mc_promisc) { 657 vport->allmulti_rule = 658 esw_fdb_set_vport_allmulti_rule(esw, vport->vport); 659 if (!allmulti_addr->uplink_rule) 660 allmulti_addr->uplink_rule = 661 esw_fdb_set_vport_allmulti_rule(esw, 662 MLX5_VPORT_UPLINK); 663 allmulti_addr->refcnt++; 664 } else if (vport->allmulti_rule) { 665 mlx5_del_flow_rules(vport->allmulti_rule); 666 vport->allmulti_rule = NULL; 667 668 if (--allmulti_addr->refcnt > 0) 669 goto promisc; 670 671 if (allmulti_addr->uplink_rule) 672 mlx5_del_flow_rules(allmulti_addr->uplink_rule); 673 allmulti_addr->uplink_rule = NULL; 674 } 675 676 promisc: 677 if (IS_ERR_OR_NULL(vport->promisc_rule) != promisc) 678 return; 679 680 if (promisc) { 681 vport->promisc_rule = 682 esw_fdb_set_vport_promisc_rule(esw, vport->vport); 683 } else if (vport->promisc_rule) { 684 mlx5_del_flow_rules(vport->promisc_rule); 685 vport->promisc_rule = NULL; 686 } 687 } 688 689 /* Sync vport rx mode from vport context */ 690 static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw, 691 struct mlx5_vport *vport) 692 { 693 int promisc_all = 0; 694 int promisc_uc = 0; 695 int promisc_mc = 0; 696 int err; 697 698 err = mlx5_query_nic_vport_promisc(esw->dev, 699 vport->vport, 700 &promisc_uc, 701 &promisc_mc, 702 &promisc_all); 703 if (err) 704 return; 705 esw_debug(esw->dev, "vport[%d] context update rx mode promisc_all=%d, all_multi=%d\n", 706 vport->vport, promisc_all, promisc_mc); 707 708 if (!vport->info.trusted || !vport->enabled) { 709 promisc_uc = 0; 710 promisc_mc = 0; 711 promisc_all = 0; 712 } 713 714 esw_apply_vport_rx_mode(esw, vport, promisc_all, 715 (promisc_all || promisc_mc)); 716 } 717 718 void esw_vport_change_handle_locked(struct mlx5_vport *vport) 719 { 720 struct mlx5_core_dev *dev = vport->dev; 721 struct mlx5_eswitch *esw = dev->priv.eswitch; 722 u8 mac[ETH_ALEN]; 723 724 if (!MLX5_CAP_GEN(dev, log_max_l2_table)) 725 return; 726 727 mlx5_query_nic_vport_mac_address(dev, vport->vport, true, mac); 728 esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n", 729 vport->vport, mac); 730 731 if (vport->enabled_events & MLX5_VPORT_UC_ADDR_CHANGE) { 732 esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC); 733 esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC); 734 } 735 736 if (vport->enabled_events & MLX5_VPORT_MC_ADDR_CHANGE) 737 esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC); 738 739 if (vport->enabled_events & MLX5_VPORT_PROMISC_CHANGE) { 740 esw_update_vport_rx_mode(esw, vport); 741 if (!IS_ERR_OR_NULL(vport->allmulti_rule)) 742 esw_update_vport_mc_promisc(esw, vport); 743 } 744 745 if (vport->enabled_events & (MLX5_VPORT_PROMISC_CHANGE | MLX5_VPORT_MC_ADDR_CHANGE)) 746 esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC); 747 748 esw_debug(esw->dev, "vport[%d] Context Changed: Done\n", vport->vport); 749 if (vport->enabled) 750 arm_vport_context_events_cmd(dev, vport->vport, 751 vport->enabled_events); 752 } 753 754 static void esw_vport_change_handler(struct work_struct *work) 755 { 756 struct mlx5_vport *vport = 757 container_of(work, struct mlx5_vport, vport_change_handler); 758 struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 759 760 mutex_lock(&esw->state_lock); 761 esw_vport_change_handle_locked(vport); 762 mutex_unlock(&esw->state_lock); 763 } 764 765 static void node_guid_gen_from_mac(u64 *node_guid, const u8 *mac) 766 { 767 ((u8 *)node_guid)[7] = mac[0]; 768 ((u8 *)node_guid)[6] = mac[1]; 769 ((u8 *)node_guid)[5] = mac[2]; 770 ((u8 *)node_guid)[4] = 0xff; 771 ((u8 *)node_guid)[3] = 0xfe; 772 ((u8 *)node_guid)[2] = mac[3]; 773 ((u8 *)node_guid)[1] = mac[4]; 774 ((u8 *)node_guid)[0] = mac[5]; 775 } 776 777 static int esw_vport_setup_acl(struct mlx5_eswitch *esw, 778 struct mlx5_vport *vport) 779 { 780 if (esw->mode == MLX5_ESWITCH_LEGACY) 781 return esw_legacy_vport_acl_setup(esw, vport); 782 else 783 return esw_vport_create_offloads_acl_tables(esw, vport); 784 } 785 786 static void esw_vport_cleanup_acl(struct mlx5_eswitch *esw, 787 struct mlx5_vport *vport) 788 { 789 if (esw->mode == MLX5_ESWITCH_LEGACY) 790 esw_legacy_vport_acl_cleanup(esw, vport); 791 else 792 esw_vport_destroy_offloads_acl_tables(esw, vport); 793 } 794 795 static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 796 { 797 int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); 798 void *query_ctx; 799 void *hca_caps; 800 int err; 801 802 if (!MLX5_CAP_GEN(esw->dev, vport_group_manager)) 803 return 0; 804 805 query_ctx = kzalloc(query_out_sz, GFP_KERNEL); 806 if (!query_ctx) 807 return -ENOMEM; 808 809 err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx, 810 MLX5_CAP_GENERAL); 811 if (err) 812 goto out_free; 813 814 hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); 815 vport->info.roce_enabled = MLX5_GET(cmd_hca_cap, hca_caps, roce); 816 vport->vhca_id = MLX5_GET(cmd_hca_cap, hca_caps, vhca_id); 817 818 if (!MLX5_CAP_GEN_MAX(esw->dev, hca_cap_2)) 819 goto out_free; 820 821 memset(query_ctx, 0, query_out_sz); 822 err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx, 823 MLX5_CAP_GENERAL_2); 824 if (err) 825 goto out_free; 826 827 hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); 828 vport->info.mig_enabled = MLX5_GET(cmd_hca_cap_2, hca_caps, migratable); 829 830 err = mlx5_esw_ipsec_vf_offload_get(esw->dev, vport); 831 out_free: 832 kfree(query_ctx); 833 return err; 834 } 835 836 bool mlx5_esw_vport_vhca_id(struct mlx5_eswitch *esw, u16 vportn, u16 *vhca_id) 837 { 838 struct mlx5_vport *vport; 839 840 vport = mlx5_eswitch_get_vport(esw, vportn); 841 if (IS_ERR(vport) || MLX5_VPORT_INVAL_VHCA_ID(vport)) 842 return false; 843 844 *vhca_id = vport->vhca_id; 845 return true; 846 } 847 848 static enum mlx5_func_type 849 esw_vport_to_func_type(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 850 { 851 u16 vport_num = vport->vport; 852 853 if (vport_num == MLX5_VPORT_HOST_PF) 854 return MLX5_HOST_PF; 855 if (xa_get_mark(&esw->vports, vport_num, MLX5_ESW_VPT_SF)) 856 return MLX5_SF; 857 if (xa_get_mark(&esw->vports, vport_num, MLX5_ESW_VPT_VF)) 858 return MLX5_VF; 859 if (mlx5_esw_is_spf_vport(esw, vport_num)) 860 return MLX5_SPF; 861 return MLX5_EC_VF; 862 } 863 864 u16 mlx5_esw_vhca_id_to_func_type(struct mlx5_core_dev *dev, u16 vhca_id) 865 { 866 struct mlx5_eswitch *esw = dev->priv.eswitch; 867 void *entry; 868 869 if (vhca_id == MLX5_CAP_GEN(dev, vhca_id)) 870 return MLX5_SELF; 871 872 if (!esw) 873 return MLX5_FUNC_TYPE_NONE; 874 875 entry = xa_load(&esw->vhca_type_map, vhca_id); 876 if (entry) 877 return xa_to_value(entry); 878 879 return MLX5_FUNC_TYPE_NONE; 880 } 881 882 static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 883 { 884 bool vst_mode_steering = esw_vst_mode_is_steering(esw); 885 u16 vport_num = vport->vport; 886 int flags; 887 int err; 888 889 err = esw_vport_setup_acl(esw, vport); 890 if (err) 891 return err; 892 893 if (mlx5_esw_is_manager_vport(esw, vport_num)) 894 return 0; 895 896 err = mlx5_esw_vport_caps_get(esw, vport); 897 if (err) 898 goto err_caps; 899 900 mlx5_modify_vport_admin_state(esw->dev, 901 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, 902 vport_num, 1, 903 vport->info.link_state); 904 905 mlx5_query_nic_vport_mac_address(esw->dev, vport_num, true, 906 vport->info.mac); 907 mlx5_query_nic_vport_node_guid(esw->dev, vport_num, true, 908 &vport->info.node_guid); 909 910 flags = (vport->info.vlan || vport->info.qos) ? 911 SET_VLAN_STRIP | SET_VLAN_INSERT : 0; 912 if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering) 913 modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan, 914 vport->info.qos, flags); 915 916 return 0; 917 918 err_caps: 919 esw_vport_cleanup_acl(esw, vport); 920 return err; 921 } 922 923 /* Don't cleanup vport->info, it's needed to restore vport configuration */ 924 static void esw_vport_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 925 { 926 u16 vport_num = vport->vport; 927 928 if (!mlx5_esw_is_manager_vport(esw, vport_num)) 929 mlx5_modify_vport_admin_state(esw->dev, 930 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, 931 vport_num, 1, 932 MLX5_VPORT_ADMIN_STATE_DOWN); 933 934 mlx5_esw_qos_vport_disable(vport); 935 esw_vport_cleanup_acl(esw, vport); 936 } 937 938 static void mlx5_esw_vport_set_max_tx_speed(struct mlx5_eswitch *esw, 939 struct mlx5_vport *vport) 940 { 941 int ret; 942 943 if (!MLX5_CAP_ESW(esw->dev, esw_vport_state_max_tx_speed)) 944 return; 945 946 ret = mlx5_modify_vport_max_tx_speed(esw->dev, 947 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, 948 vport->vport, true, 949 vport->agg_max_tx_speed); 950 if (ret) 951 mlx5_core_dbg(esw->dev, 952 "Failed to set vport %d speed %d, err=%d\n", 953 vport->vport, vport->agg_max_tx_speed, ret); 954 } 955 956 int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport, 957 enum mlx5_eswitch_vport_event enabled_events) 958 { 959 u16 vport_num = vport->vport; 960 int ret; 961 962 mutex_lock(&esw->state_lock); 963 WARN_ON(vport->enabled); 964 965 esw_debug(esw->dev, "Enabling VPORT(%d)\n", vport_num); 966 967 ret = esw_vport_setup(esw, vport); 968 if (ret) 969 goto done; 970 971 /* Sync with current vport context */ 972 vport->enabled_events = enabled_events; 973 vport->enabled = true; 974 if (mlx5_eswitch_is_vf_vport(esw, vport_num) && 975 (vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled)) 976 esw->enabled_ipsec_vf_count++; 977 978 /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well 979 * in smartNIC as it's a vport group manager. 980 */ 981 if (mlx5_esw_is_manager_vport(esw, vport_num) || 982 (!vport_num && mlx5_core_is_ecpf(esw->dev))) 983 vport->info.trusted = true; 984 985 if (!mlx5_esw_is_manager_vport(esw, vport_num) && 986 MLX5_CAP_GEN(esw->dev, vport_group_manager)) { 987 ret = mlx5_esw_vport_vhca_id_map(esw, vport); 988 if (ret) 989 goto err_vhca_mapping; 990 ret = xa_insert(&esw->vhca_type_map, vport->vhca_id, 991 xa_mk_value(esw_vport_to_func_type(esw, vport)), 992 GFP_KERNEL); 993 if (ret) 994 goto err_type_map; 995 } 996 997 esw_vport_change_handle_locked(vport); 998 999 esw->enabled_vports++; 1000 esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num); 1001 1002 if (vport->agg_max_tx_speed) 1003 mlx5_esw_vport_set_max_tx_speed(esw, vport); 1004 done: 1005 mutex_unlock(&esw->state_lock); 1006 return ret; 1007 1008 err_type_map: 1009 mlx5_esw_vport_vhca_id_unmap(esw, vport); 1010 err_vhca_mapping: 1011 esw_vport_cleanup(esw, vport); 1012 mutex_unlock(&esw->state_lock); 1013 return ret; 1014 } 1015 1016 void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 1017 { 1018 u16 vport_num = vport->vport; 1019 1020 mutex_lock(&esw->state_lock); 1021 1022 if (!vport->enabled) 1023 goto done; 1024 1025 esw_debug(esw->dev, "Disabling vport(%d)\n", vport_num); 1026 /* Mark this vport as disabled to discard new events */ 1027 vport->enabled = false; 1028 1029 /* Disable events from this vport */ 1030 if (MLX5_CAP_GEN(esw->dev, log_max_l2_table)) 1031 arm_vport_context_events_cmd(esw->dev, vport_num, 0); 1032 1033 if (!mlx5_esw_is_manager_vport(esw, vport_num) && 1034 MLX5_CAP_GEN(esw->dev, vport_group_manager)) { 1035 xa_erase(&esw->vhca_type_map, vport->vhca_id); 1036 mlx5_esw_vport_vhca_id_unmap(esw, vport); 1037 } 1038 1039 if (mlx5_eswitch_is_vf_vport(esw, vport_num) && 1040 (vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled)) 1041 esw->enabled_ipsec_vf_count--; 1042 1043 /* Clear rx-mode before esw_vport_change_handle_locked(): on 1044 * MLX5_VPORT_PROMISC_CHANGE it calls esw_update_vport_mc_promisc() 1045 * when vport->allmulti_rule is set, repopulating mc_list with FDB 1046 * rules that dangle once the FDB is destroyed. NULL allmulti_rule 1047 * here skips that path. 1048 */ 1049 esw_apply_vport_rx_mode(esw, vport, false, false); 1050 /* We don't assume VFs will cleanup after themselves. 1051 * Calling vport change handler while vport is disabled will cleanup 1052 * the vport resources. 1053 */ 1054 esw_vport_change_handle_locked(vport); 1055 vport->enabled_events = 0; 1056 esw_vport_cleanup(esw, vport); 1057 esw->enabled_vports--; 1058 1059 done: 1060 mutex_unlock(&esw->state_lock); 1061 } 1062 1063 static int eswitch_vport_event(struct notifier_block *nb, 1064 unsigned long type, void *data) 1065 { 1066 struct mlx5_eswitch *esw = mlx5_nb_cof(nb, struct mlx5_eswitch, nb); 1067 struct mlx5_eqe *eqe = data; 1068 struct mlx5_vport *vport; 1069 u16 vport_num; 1070 1071 vport_num = be16_to_cpu(eqe->data.vport_change.vport_num); 1072 vport = mlx5_eswitch_get_vport(esw, vport_num); 1073 if (!IS_ERR(vport)) 1074 queue_work(esw->work_queue, &vport->vport_change_handler); 1075 return NOTIFY_OK; 1076 } 1077 1078 /** 1079 * mlx5_esw_query_functions - Returns raw output about functions state 1080 * @dev: Pointer to device to query 1081 * 1082 * mlx5_esw_query_functions() allocates and returns functions changed 1083 * raw output memory pointer from device on success. Otherwise returns ERR_PTR. 1084 * Caller must free the memory using kvfree() when valid pointer is returned. 1085 */ 1086 const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev) 1087 { 1088 bool net_func_v1 = MLX5_CAP_GEN(dev, query_host_net_function_v1); 1089 u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {}; 1090 int alloc_entries; 1091 int outlen; 1092 u32 *out; 1093 int err; 1094 1095 if (net_func_v1) { 1096 alloc_entries = MLX5_CAP_GEN(dev, 1097 query_host_net_function_num_max); 1098 alloc_entries = max(alloc_entries, 1); 1099 MLX5_SET(query_esw_functions_in, in, op_mod, 1100 MLX5_QUERY_ESW_FUNC_OP_MOD_LAYOUT_V1); 1101 outlen = MLX5_BYTE_OFF(query_esw_functions_out, 1102 net_function_params) + 1103 alloc_entries * MLX5_UN_SZ_BYTES(net_function_params); 1104 outlen = max_t(int, outlen, 1105 MLX5_ST_SZ_BYTES(query_esw_functions_out)); 1106 } else { 1107 outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out); 1108 } 1109 1110 out = kvzalloc(outlen, GFP_KERNEL); 1111 if (!out) 1112 return ERR_PTR(-ENOMEM); 1113 1114 MLX5_SET(query_esw_functions_in, in, opcode, 1115 MLX5_CMD_OP_QUERY_ESW_FUNCTIONS); 1116 1117 err = mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); 1118 if (err) 1119 goto free; 1120 1121 if (net_func_v1) { 1122 int num_entries; 1123 1124 num_entries = MLX5_GET(query_esw_functions_out, out, 1125 net_function_num); 1126 if (num_entries > alloc_entries) { 1127 mlx5_core_warn(dev, "Got %d entries, max expected %d\n", 1128 num_entries, alloc_entries); 1129 err = -EINVAL; 1130 goto free; 1131 } 1132 } 1133 1134 return out; 1135 1136 free: 1137 kvfree(out); 1138 return ERR_PTR(err); 1139 } 1140 1141 static struct mlx5_esw_pf_info 1142 mlx5_esw_host_pf_from_host_params(const void *entry) 1143 { 1144 return (struct mlx5_esw_pf_info) { 1145 .pf_not_exist = MLX5_GET(host_params_context, entry, 1146 host_pf_not_exist), 1147 .pf_disabled = MLX5_GET(host_params_context, entry, 1148 host_pf_disabled), 1149 .num_of_vfs = MLX5_GET(host_params_context, entry, 1150 host_num_of_vfs), 1151 .total_vfs = MLX5_GET(host_params_context, entry, 1152 host_total_vfs), 1153 .host_number = MLX5_GET(host_params_context, entry, 1154 host_number), 1155 }; 1156 } 1157 1158 static struct mlx5_esw_pf_info 1159 mlx5_esw_host_pf_from_net_func_params(const u8 *entry, int num_entries) 1160 { 1161 int i; 1162 1163 for (i = 0; i < num_entries; i++) { 1164 int pf_type, state; 1165 1166 pf_type = MLX5_GET(network_function_params, entry, pci_pf_type); 1167 if (pf_type != MLX5_PCI_PF_TYPE_EXTERNAL_HOST_PF) { 1168 entry += MLX5_UN_SZ_BYTES(net_function_params); 1169 continue; 1170 } 1171 1172 state = MLX5_GET(network_function_params, entry, vhca_state); 1173 1174 return (struct mlx5_esw_pf_info) { 1175 .pf_disabled = state != MLX5_VHCA_STATE_IN_USE, 1176 .num_of_vfs = MLX5_GET(network_function_params, 1177 entry, pci_num_vfs), 1178 .total_vfs = MLX5_GET(network_function_params, 1179 entry, pci_total_vfs), 1180 .host_number = MLX5_GET(network_function_params, 1181 entry, host_number), 1182 .pf_num = MLX5_GET(network_function_params, entry, 1183 pci_device_function), 1184 }; 1185 } 1186 1187 /* No external host PF entry found */ 1188 return (struct mlx5_esw_pf_info) { 1189 .pf_not_exist = true, 1190 .pf_disabled = true, 1191 }; 1192 } 1193 1194 struct mlx5_esw_pf_info 1195 mlx5_esw_get_host_pf_info(struct mlx5_core_dev *dev, const u32 *out) 1196 { 1197 const void *entry; 1198 1199 entry = MLX5_ADDR_OF(query_esw_functions_out, out, net_function_params); 1200 1201 if (MLX5_CAP_GEN(dev, query_host_net_function_v1)) { 1202 int num_entries = MLX5_GET(query_esw_functions_out, out, 1203 net_function_num); 1204 1205 return mlx5_esw_host_pf_from_net_func_params(entry, 1206 num_entries); 1207 } 1208 1209 return mlx5_esw_host_pf_from_host_params(entry); 1210 } 1211 1212 bool mlx5_esw_get_spf_disabled(struct mlx5_core_dev *dev, const u32 *out, 1213 u16 vhca_id) 1214 { 1215 int num_entries; 1216 const u8 *entry; 1217 int i; 1218 1219 num_entries = MLX5_GET(query_esw_functions_out, out, net_function_num); 1220 entry = MLX5_ADDR_OF(query_esw_functions_out, out, net_function_params); 1221 1222 for (i = 0; i < num_entries; i++) { 1223 u16 entry_vhca_id = MLX5_GET(network_function_params, 1224 entry, vhca_id); 1225 1226 if (entry_vhca_id == vhca_id) { 1227 int state; 1228 1229 state = MLX5_GET(network_function_params, entry, 1230 vhca_state); 1231 return state != MLX5_VHCA_STATE_IN_USE; 1232 } 1233 entry += MLX5_UN_SZ_BYTES(net_function_params); 1234 } 1235 1236 return true; 1237 } 1238 1239 static int mlx5_esw_host_functions_enabled_query(struct mlx5_eswitch *esw) 1240 { 1241 struct mlx5_esw_pf_info host_pf_info; 1242 const u32 *query_host_out; 1243 1244 if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) 1245 return 0; 1246 1247 query_host_out = mlx5_esw_query_functions(esw->dev); 1248 if (IS_ERR(query_host_out)) 1249 return PTR_ERR(query_host_out); 1250 1251 host_pf_info = mlx5_esw_get_host_pf_info(esw->dev, query_host_out); 1252 esw->esw_funcs.host_funcs_disabled = host_pf_info.pf_not_exist; 1253 1254 kvfree(query_host_out); 1255 return 0; 1256 } 1257 1258 static void mlx5_eswitch_event_handler_register(struct mlx5_eswitch *esw) 1259 { 1260 if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) { 1261 MLX5_NB_INIT(&esw->esw_funcs.nb, mlx5_esw_funcs_changed_handler, 1262 ESW_FUNCTIONS_CHANGED); 1263 mlx5_eq_notifier_register(esw->dev, &esw->esw_funcs.nb); 1264 } 1265 } 1266 1267 static void mlx5_eswitch_invalidate_wq(struct mlx5_eswitch *esw) 1268 { 1269 atomic_inc(&esw->generation); 1270 wake_up_all(&esw->work_queue_wait); 1271 } 1272 1273 static void mlx5_eswitch_event_handler_unregister(struct mlx5_eswitch *esw) 1274 { 1275 if (esw->mode == MLX5_ESWITCH_OFFLOADS && 1276 mlx5_eswitch_is_funcs_handler(esw->dev)) 1277 mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb); 1278 } 1279 1280 static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw) 1281 { 1282 struct mlx5_vport *vport; 1283 unsigned long i; 1284 1285 mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) { 1286 mlx5_esw_qos_vport_qos_free(vport); 1287 memset(&vport->info, 0, sizeof(vport->info)); 1288 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 1289 } 1290 } 1291 1292 static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw) 1293 { 1294 struct mlx5_vport *vport; 1295 unsigned long i; 1296 1297 mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) { 1298 mlx5_esw_qos_vport_qos_free(vport); 1299 memset(&vport->info, 0, sizeof(vport->info)); 1300 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 1301 } 1302 } 1303 1304 static int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport, 1305 enum mlx5_eswitch_vport_event enabled_events) 1306 { 1307 int err; 1308 1309 err = mlx5_esw_vport_enable(esw, vport, enabled_events); 1310 if (err) 1311 return err; 1312 1313 err = mlx5_esw_offloads_load_rep(esw, vport); 1314 if (err) 1315 goto err_rep; 1316 1317 return err; 1318 1319 err_rep: 1320 mlx5_esw_vport_disable(esw, vport); 1321 return err; 1322 } 1323 1324 static void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 1325 { 1326 mlx5_esw_offloads_unload_rep(esw, vport); 1327 mlx5_esw_vport_disable(esw, vport); 1328 } 1329 1330 static int mlx5_eswitch_load_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num, 1331 enum mlx5_eswitch_vport_event enabled_events) 1332 { 1333 struct mlx5_vport *vport; 1334 int err; 1335 1336 vport = mlx5_eswitch_get_vport(esw, vport_num); 1337 if (IS_ERR(vport)) 1338 return PTR_ERR(vport); 1339 1340 err = mlx5_esw_offloads_init_pf_vf_rep(esw, vport); 1341 if (err) 1342 return err; 1343 1344 err = mlx5_eswitch_load_vport(esw, vport, enabled_events); 1345 if (err) 1346 goto err_load; 1347 return 0; 1348 1349 err_load: 1350 mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport); 1351 return err; 1352 } 1353 1354 static void mlx5_eswitch_unload_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) 1355 { 1356 struct mlx5_vport *vport; 1357 1358 vport = mlx5_eswitch_get_vport(esw, vport_num); 1359 if (IS_ERR(vport)) 1360 return; 1361 1362 mlx5_eswitch_unload_vport(esw, vport); 1363 mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport); 1364 } 1365 1366 int mlx5_eswitch_load_sf_vport(struct mlx5_eswitch *esw, u16 vport_num, 1367 enum mlx5_eswitch_vport_event enabled_events, 1368 struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum) 1369 { 1370 struct mlx5_vport *vport; 1371 int err; 1372 1373 vport = mlx5_eswitch_get_vport(esw, vport_num); 1374 if (IS_ERR(vport)) 1375 return PTR_ERR(vport); 1376 1377 err = mlx5_esw_offloads_init_sf_rep(esw, vport, dl_port, controller, sfnum); 1378 if (err) 1379 return err; 1380 1381 err = mlx5_eswitch_load_vport(esw, vport, enabled_events); 1382 if (err) 1383 goto err_load; 1384 1385 return 0; 1386 1387 err_load: 1388 mlx5_esw_offloads_cleanup_sf_rep(esw, vport); 1389 return err; 1390 } 1391 1392 void mlx5_eswitch_unload_sf_vport(struct mlx5_eswitch *esw, u16 vport_num) 1393 { 1394 struct mlx5_vport *vport; 1395 1396 vport = mlx5_eswitch_get_vport(esw, vport_num); 1397 if (IS_ERR(vport)) 1398 return; 1399 1400 mlx5_eswitch_unload_vport(esw, vport); 1401 mlx5_esw_offloads_cleanup_sf_rep(esw, vport); 1402 } 1403 1404 void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs) 1405 { 1406 struct mlx5_vport *vport; 1407 unsigned long i; 1408 1409 mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) { 1410 /* Adjacent VFs are unloaded separately */ 1411 if (!vport->enabled || vport->adjacent) 1412 continue; 1413 mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport); 1414 } 1415 } 1416 1417 static void mlx5_eswitch_unload_ec_vf_vports(struct mlx5_eswitch *esw, 1418 u16 num_ec_vfs) 1419 { 1420 struct mlx5_vport *vport; 1421 unsigned long i; 1422 1423 mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { 1424 if (!vport->enabled) 1425 continue; 1426 mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport); 1427 } 1428 } 1429 1430 static void mlx5_eswitch_unload_adj_vf_vports(struct mlx5_eswitch *esw) 1431 { 1432 struct mlx5_vport *vport; 1433 unsigned long i; 1434 1435 mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) { 1436 if (!vport->enabled || !vport->adjacent) 1437 continue; 1438 mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport); 1439 } 1440 } 1441 1442 static int 1443 mlx5_eswitch_load_adj_vf_vports(struct mlx5_eswitch *esw, 1444 enum mlx5_eswitch_vport_event enabled_events) 1445 { 1446 struct mlx5_vport *vport; 1447 unsigned long i; 1448 int err; 1449 1450 mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) { 1451 if (!vport->adjacent) 1452 continue; 1453 err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, 1454 enabled_events); 1455 if (err) 1456 goto unload_adj_vf_vport; 1457 } 1458 1459 return 0; 1460 1461 unload_adj_vf_vport: 1462 mlx5_eswitch_unload_adj_vf_vports(esw); 1463 return err; 1464 } 1465 1466 int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, 1467 enum mlx5_eswitch_vport_event enabled_events) 1468 { 1469 struct mlx5_vport *vport; 1470 unsigned long i; 1471 int err; 1472 1473 mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) { 1474 err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events); 1475 if (err) 1476 goto vf_err; 1477 } 1478 1479 return 0; 1480 1481 vf_err: 1482 mlx5_eswitch_unload_vf_vports(esw, num_vfs); 1483 return err; 1484 } 1485 1486 static int mlx5_eswitch_load_ec_vf_vports(struct mlx5_eswitch *esw, u16 num_ec_vfs, 1487 enum mlx5_eswitch_vport_event enabled_events) 1488 { 1489 struct mlx5_vport *vport; 1490 unsigned long i; 1491 int err; 1492 1493 mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { 1494 err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events); 1495 if (err) 1496 goto vf_err; 1497 } 1498 1499 return 0; 1500 1501 vf_err: 1502 mlx5_eswitch_unload_ec_vf_vports(esw, num_ec_vfs); 1503 return err; 1504 } 1505 1506 int mlx5_esw_pf_enable_hca(struct mlx5_core_dev *dev, u16 vport_num) 1507 { 1508 struct mlx5_eswitch *esw = dev->priv.eswitch; 1509 struct mlx5_vport *vport; 1510 int err; 1511 1512 if (!mlx5_core_is_ecpf(dev) || !mlx5_esw_allowed(esw)) 1513 return 0; 1514 1515 vport = mlx5_eswitch_get_vport(esw, vport_num); 1516 if (IS_ERR(vport)) 1517 return PTR_ERR(vport); 1518 1519 /* Once vport and representor are ready, take the PF out of 1520 * initializing state. Enabling HCA clears the iser->initializing 1521 * bit and PF driver loading can progress. 1522 */ 1523 err = mlx5_cmd_pf_enable_hca(dev, vport_num); 1524 if (err) 1525 return err; 1526 1527 vport->pf_activated = true; 1528 1529 return 0; 1530 } 1531 1532 int mlx5_esw_pf_disable_hca(struct mlx5_core_dev *dev, u16 vport_num) 1533 { 1534 struct mlx5_eswitch *esw = dev->priv.eswitch; 1535 struct mlx5_vport *vport; 1536 int err; 1537 1538 if (!mlx5_core_is_ecpf(dev) || !mlx5_esw_allowed(esw)) 1539 return 0; 1540 1541 vport = mlx5_eswitch_get_vport(esw, vport_num); 1542 if (IS_ERR(vport)) 1543 return PTR_ERR(vport); 1544 1545 err = mlx5_cmd_pf_disable_hca(dev, vport_num); 1546 if (err) 1547 return err; 1548 1549 vport->pf_activated = false; 1550 1551 return 0; 1552 } 1553 1554 int mlx5_esw_host_pf_enable_hca(struct mlx5_core_dev *dev) 1555 { 1556 return mlx5_esw_pf_enable_hca(dev, MLX5_VPORT_HOST_PF); 1557 } 1558 1559 int mlx5_esw_host_pf_disable_hca(struct mlx5_core_dev *dev) 1560 { 1561 return mlx5_esw_pf_disable_hca(dev, MLX5_VPORT_HOST_PF); 1562 } 1563 1564 /* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs 1565 * whichever are present on the eswitch. 1566 */ 1567 int 1568 mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, 1569 enum mlx5_eswitch_vport_event enabled_events) 1570 { 1571 struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs; 1572 bool pf_needed; 1573 u16 vport_num; 1574 int ret; 1575 int i; 1576 1577 pf_needed = mlx5_core_is_ecpf_esw_manager(esw->dev) || 1578 esw->mode == MLX5_ESWITCH_LEGACY; 1579 1580 /* Enable PF vport */ 1581 if (pf_needed && mlx5_esw_host_functions_enabled(esw->dev)) { 1582 ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_HOST_PF, 1583 enabled_events); 1584 if (ret) 1585 return ret; 1586 } 1587 1588 if (mlx5_esw_host_functions_enabled(esw->dev)) { 1589 /* Enable external host PF HCA */ 1590 ret = mlx5_esw_host_pf_enable_hca(esw->dev); 1591 if (ret) 1592 goto pf_hca_err; 1593 } 1594 1595 /* Enable ECPF vport */ 1596 if (mlx5_ecpf_vport_exists(esw->dev)) { 1597 ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_ECPF, enabled_events); 1598 if (ret) 1599 goto ecpf_err; 1600 } 1601 1602 /* Enable ECVF vports */ 1603 if (mlx5_core_ec_sriov_enabled(esw->dev)) { 1604 ret = mlx5_eswitch_load_ec_vf_vports(esw, 1605 esw_funcs->num_ec_vfs, 1606 enabled_events); 1607 if (ret) 1608 goto ec_vf_err; 1609 } 1610 1611 /* Enable VF vports */ 1612 ret = mlx5_eswitch_load_vf_vports(esw, esw_funcs->num_vfs, 1613 enabled_events); 1614 if (ret) 1615 goto vf_err; 1616 1617 /* Enable adjacent VF vports */ 1618 ret = mlx5_eswitch_load_adj_vf_vports(esw, enabled_events); 1619 if (ret) 1620 goto unload_vf_vports; 1621 1622 /* Enable satellite PF vports */ 1623 for (i = 0; i < esw_funcs->num_spfs; i++) { 1624 vport_num = esw_funcs->spfs[i].vport_num; 1625 1626 ret = mlx5_eswitch_load_pf_vf_vport(esw, vport_num, 1627 enabled_events); 1628 if (ret) 1629 goto spf_err; 1630 1631 ret = mlx5_esw_pf_enable_hca(esw->dev, vport_num); 1632 if (ret) { 1633 mlx5_eswitch_unload_pf_vf_vport(esw, vport_num); 1634 goto spf_err; 1635 } 1636 } 1637 1638 return 0; 1639 1640 spf_err: 1641 while (i-- > 0) { 1642 vport_num = esw_funcs->spfs[i].vport_num; 1643 mlx5_esw_pf_disable_hca(esw->dev, vport_num); 1644 mlx5_eswitch_unload_pf_vf_vport(esw, vport_num); 1645 } 1646 mlx5_eswitch_unload_adj_vf_vports(esw); 1647 unload_vf_vports: 1648 mlx5_eswitch_unload_vf_vports(esw, esw_funcs->num_vfs); 1649 vf_err: 1650 if (mlx5_core_ec_sriov_enabled(esw->dev)) 1651 mlx5_eswitch_unload_ec_vf_vports(esw, esw_funcs->num_ec_vfs); 1652 ec_vf_err: 1653 if (mlx5_ecpf_vport_exists(esw->dev)) 1654 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF); 1655 ecpf_err: 1656 if (mlx5_esw_host_functions_enabled(esw->dev)) 1657 mlx5_esw_host_pf_disable_hca(esw->dev); 1658 pf_hca_err: 1659 if (pf_needed && mlx5_esw_host_functions_enabled(esw->dev)) 1660 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_HOST_PF); 1661 return ret; 1662 } 1663 1664 /* mlx5_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs 1665 * whichever are previously enabled on the eswitch. 1666 */ 1667 void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw) 1668 { 1669 struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs; 1670 u16 vport_num; 1671 int i; 1672 1673 for (i = 0; i < esw_funcs->num_spfs; i++) { 1674 vport_num = esw_funcs->spfs[i].vport_num; 1675 mlx5_esw_pf_disable_hca(esw->dev, vport_num); 1676 mlx5_eswitch_unload_pf_vf_vport(esw, vport_num); 1677 } 1678 1679 mlx5_eswitch_unload_adj_vf_vports(esw); 1680 1681 mlx5_eswitch_unload_vf_vports(esw, esw_funcs->num_vfs); 1682 1683 if (mlx5_core_ec_sriov_enabled(esw->dev)) 1684 mlx5_eswitch_unload_ec_vf_vports(esw, esw_funcs->num_ec_vfs); 1685 1686 if (mlx5_ecpf_vport_exists(esw->dev)) { 1687 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF); 1688 } 1689 1690 if (mlx5_esw_host_functions_enabled(esw->dev)) 1691 mlx5_esw_host_pf_disable_hca(esw->dev); 1692 1693 if ((mlx5_core_is_ecpf_esw_manager(esw->dev) || 1694 esw->mode == MLX5_ESWITCH_LEGACY) && 1695 mlx5_esw_host_functions_enabled(esw->dev)) 1696 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_HOST_PF); 1697 } 1698 1699 static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw) 1700 { 1701 struct devlink *devlink = priv_to_devlink(esw->dev); 1702 union devlink_param_value val; 1703 int err; 1704 1705 err = devl_param_driverinit_value_get(devlink, 1706 MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 1707 &val); 1708 if (!err) { 1709 esw->params.large_group_num = val.vu32; 1710 } else { 1711 esw_warn(esw->dev, 1712 "Devlink can't get param fdb_large_groups, uses default (%d).\n", 1713 ESW_OFFLOADS_DEFAULT_NUM_GROUPS); 1714 esw->params.large_group_num = ESW_OFFLOADS_DEFAULT_NUM_GROUPS; 1715 } 1716 } 1717 1718 static void 1719 mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs) 1720 { 1721 struct mlx5_esw_pf_info host_pf_info; 1722 const u32 *out; 1723 1724 if (num_vfs < 0) 1725 return; 1726 1727 if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) { 1728 esw->esw_funcs.num_vfs = num_vfs; 1729 return; 1730 } 1731 1732 out = mlx5_esw_query_functions(esw->dev); 1733 if (IS_ERR(out)) 1734 return; 1735 1736 host_pf_info = mlx5_esw_get_host_pf_info(esw->dev, out); 1737 esw->esw_funcs.num_vfs = host_pf_info.num_of_vfs; 1738 if (mlx5_core_ec_sriov_enabled(esw->dev)) 1739 esw->esw_funcs.num_ec_vfs = num_vfs; 1740 1741 kvfree(out); 1742 } 1743 1744 static void mlx5_esw_mode_change_notify(struct mlx5_eswitch *esw, u16 mode) 1745 { 1746 struct mlx5_esw_event_info info = {}; 1747 1748 info.new_mode = mode; 1749 1750 blocking_notifier_call_chain(&esw->dev->priv.esw_n_head, 0, &info); 1751 } 1752 1753 static int mlx5_esw_egress_acls_init(struct mlx5_core_dev *dev) 1754 { 1755 struct mlx5_flow_steering *steering = dev->priv.steering; 1756 int total_vports = mlx5_eswitch_get_total_vports(dev); 1757 int err; 1758 int i; 1759 1760 for (i = 0; i < total_vports; i++) { 1761 err = mlx5_fs_vport_egress_acl_ns_add(steering, i); 1762 if (err) 1763 goto acl_ns_remove; 1764 } 1765 return 0; 1766 1767 acl_ns_remove: 1768 while (i--) 1769 mlx5_fs_vport_egress_acl_ns_remove(steering, i); 1770 return err; 1771 } 1772 1773 static void mlx5_esw_egress_acls_cleanup(struct mlx5_core_dev *dev) 1774 { 1775 struct mlx5_flow_steering *steering = dev->priv.steering; 1776 int total_vports = mlx5_eswitch_get_total_vports(dev); 1777 int i; 1778 1779 for (i = total_vports - 1; i >= 0; i--) 1780 mlx5_fs_vport_egress_acl_ns_remove(steering, i); 1781 } 1782 1783 static int mlx5_esw_ingress_acls_init(struct mlx5_core_dev *dev) 1784 { 1785 struct mlx5_flow_steering *steering = dev->priv.steering; 1786 int total_vports = mlx5_eswitch_get_total_vports(dev); 1787 int err; 1788 int i; 1789 1790 for (i = 0; i < total_vports; i++) { 1791 err = mlx5_fs_vport_ingress_acl_ns_add(steering, i); 1792 if (err) 1793 goto acl_ns_remove; 1794 } 1795 return 0; 1796 1797 acl_ns_remove: 1798 while (i--) 1799 mlx5_fs_vport_ingress_acl_ns_remove(steering, i); 1800 return err; 1801 } 1802 1803 static void mlx5_esw_ingress_acls_cleanup(struct mlx5_core_dev *dev) 1804 { 1805 struct mlx5_flow_steering *steering = dev->priv.steering; 1806 int total_vports = mlx5_eswitch_get_total_vports(dev); 1807 int i; 1808 1809 for (i = total_vports - 1; i >= 0; i--) 1810 mlx5_fs_vport_ingress_acl_ns_remove(steering, i); 1811 } 1812 1813 static int mlx5_esw_acls_ns_init(struct mlx5_eswitch *esw) 1814 { 1815 struct mlx5_core_dev *dev = esw->dev; 1816 int err; 1817 1818 if (esw->flags & MLX5_ESWITCH_VPORT_ACL_NS_CREATED) 1819 return 0; 1820 1821 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) { 1822 err = mlx5_esw_egress_acls_init(dev); 1823 if (err) 1824 return err; 1825 } else { 1826 esw_warn(dev, "egress ACL is not supported by FW\n"); 1827 } 1828 1829 if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) { 1830 err = mlx5_esw_ingress_acls_init(dev); 1831 if (err) 1832 goto err; 1833 } else { 1834 esw_warn(dev, "ingress ACL is not supported by FW\n"); 1835 } 1836 esw->flags |= MLX5_ESWITCH_VPORT_ACL_NS_CREATED; 1837 return 0; 1838 1839 err: 1840 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) 1841 mlx5_esw_egress_acls_cleanup(dev); 1842 return err; 1843 } 1844 1845 static void mlx5_esw_acls_ns_cleanup(struct mlx5_eswitch *esw) 1846 { 1847 struct mlx5_core_dev *dev = esw->dev; 1848 1849 esw->flags &= ~MLX5_ESWITCH_VPORT_ACL_NS_CREATED; 1850 if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) 1851 mlx5_esw_ingress_acls_cleanup(dev); 1852 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) 1853 mlx5_esw_egress_acls_cleanup(dev); 1854 } 1855 1856 /** 1857 * mlx5_eswitch_enable_locked - Enable eswitch 1858 * @esw: Pointer to eswitch 1859 * @num_vfs: Enable eswitch for given number of VFs. This is optional. 1860 * Valid value are 0, > 0 and MLX5_ESWITCH_IGNORE_NUM_VFS. 1861 * Caller should pass num_vfs > 0 when enabling eswitch for 1862 * vf vports. Caller should pass num_vfs = 0, when eswitch 1863 * is enabled without sriov VFs or when caller 1864 * is unaware of the sriov state of the host PF on ECPF based 1865 * eswitch. Caller should pass < 0 when num_vfs should be 1866 * completely ignored. This is typically the case when eswitch 1867 * is enabled without sriov regardless of PF/ECPF system. 1868 * mlx5_eswitch_enable_locked() Enables eswitch in either legacy or offloads 1869 * mode. If num_vfs >=0 is provided, it setup VF related eswitch vports. 1870 * It returns 0 on success or error code on failure. 1871 */ 1872 int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs) 1873 { 1874 int err; 1875 1876 devl_assert_locked(priv_to_devlink(esw->dev)); 1877 1878 if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) { 1879 esw_warn(esw->dev, "FDB is not supported, aborting ...\n"); 1880 return -EOPNOTSUPP; 1881 } 1882 1883 mlx5_eswitch_get_devlink_param(esw); 1884 1885 err = mlx5_esw_acls_ns_init(esw); 1886 if (err) 1887 return err; 1888 1889 mlx5_eswitch_update_num_of_vfs(esw, num_vfs); 1890 1891 MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE); 1892 mlx5_eq_notifier_register(esw->dev, &esw->nb); 1893 1894 if (esw->mode == MLX5_ESWITCH_LEGACY) { 1895 err = esw_legacy_enable(esw); 1896 } else { 1897 err = esw_offloads_enable(esw); 1898 } 1899 1900 if (err) 1901 goto err_esw_init; 1902 1903 esw->fdb_table.flags |= MLX5_ESW_FDB_CREATED; 1904 1905 mlx5_eswitch_event_handler_register(esw); 1906 1907 esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", 1908 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", 1909 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); 1910 1911 mlx5_esw_mode_change_notify(esw, esw->mode); 1912 1913 return 0; 1914 1915 err_esw_init: 1916 mlx5_eq_notifier_unregister(esw->dev, &esw->nb); 1917 mlx5_esw_acls_ns_cleanup(esw); 1918 return err; 1919 } 1920 1921 /** 1922 * mlx5_eswitch_enable - Enable eswitch 1923 * @esw: Pointer to eswitch 1924 * @num_vfs: Enable eswitch switch for given number of VFs. 1925 * Caller must pass num_vfs > 0 when enabling eswitch for 1926 * vf vports. 1927 * mlx5_eswitch_enable() returns 0 on success or error code on failure. 1928 */ 1929 int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) 1930 { 1931 bool toggle_lag; 1932 int ret = 0; 1933 1934 if (!mlx5_esw_allowed(esw)) 1935 return 0; 1936 1937 devl_assert_locked(priv_to_devlink(esw->dev)); 1938 1939 toggle_lag = !mlx5_esw_is_fdb_created(esw); 1940 1941 if (toggle_lag) 1942 mlx5_lag_disable_change(esw->dev); 1943 1944 mlx5_eswitch_invalidate_wq(esw); 1945 mlx5_esw_reps_block(esw); 1946 1947 if (!mlx5_esw_is_fdb_created(esw)) { 1948 ret = mlx5_eswitch_enable_locked(esw, num_vfs); 1949 } else { 1950 enum mlx5_eswitch_vport_event vport_events; 1951 1952 vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ? 1953 MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE; 1954 /* If this is the ECPF the number of host VFs is managed via the 1955 * eswitch function change event handler, and any num_vfs provided 1956 * here are intended to be EC VFs. 1957 */ 1958 if (!mlx5_core_is_ecpf(esw->dev)) { 1959 ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events); 1960 if (!ret) 1961 esw->esw_funcs.num_vfs = num_vfs; 1962 } else if (mlx5_core_ec_sriov_enabled(esw->dev)) { 1963 ret = mlx5_eswitch_load_ec_vf_vports(esw, num_vfs, vport_events); 1964 if (!ret) 1965 esw->esw_funcs.num_ec_vfs = num_vfs; 1966 } 1967 } 1968 1969 mlx5_esw_reps_unblock(esw); 1970 1971 if (toggle_lag) 1972 mlx5_lag_enable_change(esw->dev); 1973 1974 return ret; 1975 } 1976 1977 /* When disabling sriov, free driver level resources. */ 1978 void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) 1979 { 1980 if (!mlx5_esw_allowed(esw)) 1981 return; 1982 1983 devl_assert_locked(priv_to_devlink(esw->dev)); 1984 /* If driver is unloaded, this function is called twice by remove_one() 1985 * and mlx5_unload(). Prevent the second call. 1986 */ 1987 if (!esw->esw_funcs.num_vfs && !esw->esw_funcs.num_ec_vfs && !clear_vf) 1988 return; 1989 1990 esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", 1991 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", 1992 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); 1993 1994 mlx5_eswitch_invalidate_wq(esw); 1995 1996 if (esw->mode == MLX5_ESWITCH_OFFLOADS) { 1997 struct devlink *devlink = priv_to_devlink(esw->dev); 1998 1999 devl_rate_nodes_destroy(devlink); 2000 } 2001 2002 mlx5_esw_reps_block(esw); 2003 2004 if (!mlx5_core_is_ecpf(esw->dev)) { 2005 mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); 2006 if (clear_vf) 2007 mlx5_eswitch_clear_vf_vports_info(esw); 2008 } else if (mlx5_core_ec_sriov_enabled(esw->dev)) { 2009 mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs); 2010 if (clear_vf) 2011 mlx5_eswitch_clear_ec_vf_vports_info(esw); 2012 } 2013 2014 mlx5_esw_reps_unblock(esw); 2015 /* Destroy legacy fdb when disabling sriov in legacy mode. */ 2016 if (esw->mode == MLX5_ESWITCH_LEGACY) 2017 mlx5_eswitch_disable_locked(esw); 2018 2019 if (!mlx5_core_is_ecpf(esw->dev)) 2020 esw->esw_funcs.num_vfs = 0; 2021 else 2022 esw->esw_funcs.num_ec_vfs = 0; 2023 } 2024 2025 /* Free resources for corresponding eswitch mode. It is called by devlink 2026 * when changing eswitch mode or modprobe when unloading driver. 2027 */ 2028 void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw) 2029 { 2030 struct devlink *devlink = priv_to_devlink(esw->dev); 2031 2032 /* Notify eswitch users that it is exiting from current mode. 2033 * So that it can do necessary cleanup before the eswitch is disabled. 2034 */ 2035 mlx5_esw_mode_change_notify(esw, MLX5_ESWITCH_LEGACY); 2036 2037 mlx5_eq_notifier_unregister(esw->dev, &esw->nb); 2038 mlx5_eswitch_event_handler_unregister(esw); 2039 mlx5_eswitch_invalidate_wq(esw); 2040 2041 esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", 2042 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", 2043 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); 2044 2045 if (esw->mode == MLX5_ESWITCH_OFFLOADS) 2046 devl_rate_nodes_destroy(devlink); 2047 2048 if (esw->fdb_table.flags & MLX5_ESW_FDB_CREATED) { 2049 esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED; 2050 if (esw->mode == MLX5_ESWITCH_OFFLOADS) 2051 esw_offloads_disable(esw); 2052 else if (esw->mode == MLX5_ESWITCH_LEGACY) 2053 esw_legacy_disable(esw); 2054 mlx5_esw_acls_ns_cleanup(esw); 2055 } 2056 } 2057 2058 void mlx5_eswitch_disable(struct mlx5_eswitch *esw) 2059 { 2060 if (!mlx5_esw_allowed(esw)) 2061 return; 2062 2063 devl_assert_locked(priv_to_devlink(esw->dev)); 2064 mlx5_lag_disable_change(esw->dev); 2065 2066 mlx5_esw_reps_block(esw); 2067 mlx5_eswitch_disable_locked(esw); 2068 mlx5_esw_reps_unblock(esw); 2069 2070 esw->mode = MLX5_ESWITCH_LEGACY; 2071 mlx5_sd_eswitch_mode_set(esw->dev, MLX5_ESWITCH_LEGACY); 2072 mlx5_lag_enable_change(esw->dev); 2073 } 2074 2075 static int mlx5_esw_sf_max_pf_functions(struct mlx5_core_dev *dev, 2076 u16 vport_num, u16 *max_sfs, 2077 u16 *sf_base_id) 2078 { 2079 int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); 2080 void *query_ctx; 2081 void *hca_caps; 2082 int err; 2083 2084 query_ctx = kzalloc(query_out_sz, GFP_KERNEL); 2085 if (!query_ctx) 2086 return -ENOMEM; 2087 2088 err = mlx5_vport_get_other_func_general_cap(dev, vport_num, query_ctx); 2089 if (err) 2090 goto out_free; 2091 2092 hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); 2093 *max_sfs = MLX5_GET(cmd_hca_cap, hca_caps, max_num_sf); 2094 *sf_base_id = MLX5_GET(cmd_hca_cap, hca_caps, sf_base_id); 2095 2096 out_free: 2097 kfree(query_ctx); 2098 return err; 2099 } 2100 2101 int mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev *dev, u16 *max_sfs, 2102 u16 *sf_base_id) 2103 { 2104 if (!mlx5_core_is_ecpf(dev) || 2105 !mlx5_esw_host_functions_enabled(dev)) { 2106 *max_sfs = 0; 2107 return 0; 2108 } 2109 2110 return mlx5_esw_sf_max_pf_functions(dev, MLX5_VPORT_HOST_PF, max_sfs, 2111 sf_base_id); 2112 } 2113 2114 int mlx5_esw_sf_max_spf_functions(struct mlx5_core_dev *dev, int spf_idx, 2115 u16 *max_sfs, u16 *sf_base_id) 2116 { 2117 struct mlx5_eswitch *esw = dev->priv.eswitch; 2118 u16 vport_num; 2119 2120 if (!mlx5_esw_allowed(esw)) { 2121 *max_sfs = 0; 2122 return 0; 2123 } 2124 2125 if (spf_idx >= esw->esw_funcs.num_spfs) 2126 return -EINVAL; 2127 2128 vport_num = esw->esw_funcs.spfs[spf_idx].vport_num; 2129 return mlx5_esw_sf_max_pf_functions(dev, vport_num, max_sfs, 2130 sf_base_id); 2131 } 2132 2133 int mlx5_esw_get_num_spfs(struct mlx5_core_dev *dev) 2134 { 2135 struct mlx5_eswitch *esw = dev->priv.eswitch; 2136 2137 if (!mlx5_esw_allowed(esw)) 2138 return 0; 2139 2140 return esw->esw_funcs.num_spfs; 2141 } 2142 2143 int mlx5_esw_spf_get_host_number(struct mlx5_core_dev *dev, int spf_idx, 2144 u16 *host_number) 2145 { 2146 struct mlx5_eswitch *esw = dev->priv.eswitch; 2147 2148 if (!mlx5_esw_allowed(esw)) 2149 return -EPERM; 2150 2151 if (spf_idx >= esw->esw_funcs.num_spfs) 2152 return -EINVAL; 2153 2154 *host_number = esw->esw_funcs.spfs[spf_idx].host_number; 2155 return 0; 2156 } 2157 2158 u16 mlx5_esw_get_hpf_host_number(struct mlx5_core_dev *dev) 2159 { 2160 struct mlx5_eswitch *esw = dev->priv.eswitch; 2161 2162 if (!mlx5_esw_allowed(esw)) 2163 return 0; 2164 2165 return esw->esw_funcs.hpf_host_number; 2166 } 2167 2168 u16 mlx5_esw_get_hpf_pf_num(struct mlx5_core_dev *dev) 2169 { 2170 struct mlx5_eswitch *esw = dev->priv.eswitch; 2171 2172 if (mlx5_core_is_ecpf_esw_manager(dev) && 2173 MLX5_CAP_GEN(dev, query_host_net_function_v1)) 2174 return esw->esw_funcs.hpf_pf_num; 2175 2176 return PCI_FUNC(dev->pdev->devfn); 2177 } 2178 2179 u16 mlx5_esw_sf_controller_to_pfnum(struct mlx5_core_dev *dev, u32 controller) 2180 { 2181 struct mlx5_eswitch *esw = dev->priv.eswitch; 2182 struct mlx5_esw_functions *esw_funcs; 2183 int i; 2184 2185 if (!controller) 2186 return PCI_FUNC(dev->pdev->devfn); 2187 2188 esw_funcs = &esw->esw_funcs; 2189 for (i = 0; i < esw_funcs->num_spfs; i++) 2190 if (controller == esw_funcs->spfs[i].host_number + 1) 2191 return esw_funcs->spfs[i].pf_num; 2192 2193 return mlx5_esw_get_hpf_pf_num(dev); 2194 } 2195 2196 bool mlx5_esw_has_spf_sfs(struct mlx5_core_dev *dev) 2197 { 2198 struct mlx5_eswitch *esw = dev->priv.eswitch; 2199 2200 if (!mlx5_esw_allowed(esw)) 2201 return false; 2202 2203 return esw->esw_funcs.has_spf_sfs; 2204 } 2205 2206 static int mlx5_esw_hpf_info_init(struct mlx5_eswitch *esw) 2207 { 2208 struct mlx5_esw_pf_info host_pf_info; 2209 const u32 *query_host_out; 2210 2211 if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) 2212 return 0; 2213 2214 query_host_out = mlx5_esw_query_functions(esw->dev); 2215 if (IS_ERR(query_host_out)) 2216 return PTR_ERR(query_host_out); 2217 2218 /* Mark non local controller with non zero controller number. */ 2219 host_pf_info = mlx5_esw_get_host_pf_info(esw->dev, query_host_out); 2220 esw->esw_funcs.hpf_host_number = host_pf_info.host_number; 2221 esw->esw_funcs.hpf_pf_num = host_pf_info.pf_num; 2222 kvfree(query_host_out); 2223 return 0; 2224 } 2225 2226 int mlx5_esw_vport_alloc(struct mlx5_eswitch *esw, int index, u16 vport_num) 2227 { 2228 struct mlx5_vport *vport; 2229 int err; 2230 2231 vport = kzalloc_obj(*vport); 2232 if (!vport) 2233 return -ENOMEM; 2234 2235 vport->dev = esw->dev; 2236 vport->vport = vport_num; 2237 vport->index = index; 2238 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 2239 vport->vhca_id = MLX5_VHCA_ID_INVALID; 2240 INIT_WORK(&vport->vport_change_handler, esw_vport_change_handler); 2241 err = xa_insert(&esw->vports, vport_num, vport, GFP_KERNEL); 2242 if (err) 2243 goto insert_err; 2244 2245 esw->total_vports++; 2246 return 0; 2247 2248 insert_err: 2249 kfree(vport); 2250 return err; 2251 } 2252 2253 void mlx5_esw_vport_free(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 2254 { 2255 esw->total_vports--; 2256 xa_erase(&esw->vports, vport->vport); 2257 kfree(vport); 2258 } 2259 2260 static void mlx5_esw_spfs_cleanup(struct mlx5_eswitch *esw) 2261 { 2262 struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs; 2263 int i; 2264 2265 for (i = 0; i < esw_funcs->num_spfs; i++) 2266 mlx5_esw_destroy_esw_vport(esw->dev, 2267 esw_funcs->spfs[i].vport_num); 2268 2269 kfree(esw_funcs->spfs); 2270 esw_funcs->spfs = NULL; 2271 esw_funcs->num_spfs = 0; 2272 } 2273 2274 static int mlx5_esw_spfs_init(struct mlx5_eswitch *esw) 2275 { 2276 struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs; 2277 struct mlx5_core_dev *dev = esw->dev; 2278 int num_entries; 2279 const u8 *entry; 2280 const u32 *out; 2281 int err = 0; 2282 int pf_type; 2283 u16 vhca_id; 2284 int i; 2285 2286 if (!MLX5_CAP_GEN(dev, query_host_net_function_v1)) 2287 return 0; 2288 2289 out = mlx5_esw_query_functions(dev); 2290 if (IS_ERR(out)) 2291 return PTR_ERR(out); 2292 2293 num_entries = MLX5_GET(query_esw_functions_out, out, net_function_num); 2294 if (!num_entries) 2295 goto out_free; 2296 2297 esw_funcs->spfs = kzalloc_objs(*esw_funcs->spfs, num_entries); 2298 if (!esw_funcs->spfs) { 2299 err = -ENOMEM; 2300 goto out_free; 2301 } 2302 2303 entry = MLX5_ADDR_OF(query_esw_functions_out, out, net_function_params); 2304 2305 for (i = 0; i < num_entries; i++) { 2306 u16 vport_num; 2307 2308 pf_type = MLX5_GET(network_function_params, entry, pci_pf_type); 2309 if (pf_type != MLX5_PCI_PF_TYPE_SATELLITE_PF) { 2310 entry += MLX5_UN_SZ_BYTES(net_function_params); 2311 continue; 2312 } 2313 2314 if (!MLX5_GET(network_function_params, entry, 2315 esw_vport_manual)) { 2316 esw_warn(dev, "Satellite PF without esw_vport_manual is not supported\n"); 2317 entry += MLX5_UN_SZ_BYTES(net_function_params); 2318 continue; 2319 } 2320 2321 vhca_id = MLX5_GET(network_function_params, entry, vhca_id); 2322 2323 err = mlx5_esw_create_esw_vport(dev, vhca_id, &vport_num); 2324 if (err) { 2325 esw_warn(dev, "Failed to create satellite PF vport for vhca_id 0x%x, err %d\n", 2326 vhca_id, err); 2327 goto spfs_cleanup; 2328 } 2329 2330 esw_funcs->spfs[esw_funcs->num_spfs].vport_num = vport_num; 2331 esw_funcs->spfs[esw_funcs->num_spfs].vhca_id = vhca_id; 2332 esw_funcs->spfs[esw_funcs->num_spfs].host_number = 2333 MLX5_GET(network_function_params, entry, host_number); 2334 esw_funcs->spfs[esw_funcs->num_spfs].pf_num = 2335 MLX5_GET(network_function_params, entry, 2336 pci_device_function); 2337 esw_funcs->num_spfs++; 2338 2339 entry += MLX5_UN_SZ_BYTES(net_function_params); 2340 } 2341 2342 if (!esw_funcs->num_spfs) { 2343 kfree(esw_funcs->spfs); 2344 esw_funcs->spfs = NULL; 2345 } 2346 2347 kvfree(out); 2348 return 0; 2349 2350 spfs_cleanup: 2351 mlx5_esw_spfs_cleanup(esw); 2352 out_free: 2353 kvfree(out); 2354 return err; 2355 } 2356 2357 static void mlx5_esw_vports_cleanup(struct mlx5_eswitch *esw) 2358 { 2359 struct mlx5_vport *vport; 2360 unsigned long i; 2361 2362 mlx5_esw_spfs_cleanup(esw); 2363 esw->esw_funcs.has_spf_sfs = false; 2364 mlx5_esw_for_each_vport(esw, i, vport) 2365 mlx5_esw_vport_free(esw, vport); 2366 xa_destroy(&esw->vports); 2367 } 2368 2369 static int mlx5_esw_vports_init(struct mlx5_eswitch *esw) 2370 { 2371 struct mlx5_core_dev *dev = esw->dev; 2372 u16 max_sfs, base_sf_num; 2373 int idx = 0; 2374 int err; 2375 int i; 2376 2377 xa_init(&esw->vports); 2378 2379 err = mlx5_esw_hpf_info_init(esw); 2380 if (err) 2381 goto err; 2382 2383 if (mlx5_esw_host_functions_enabled(dev)) { 2384 err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_HOST_PF); 2385 if (err) 2386 goto err; 2387 if (esw->first_host_vport == MLX5_VPORT_HOST_PF) 2388 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN); 2389 idx++; 2390 for (i = 0; i < mlx5_core_max_vfs(dev); i++) { 2391 err = mlx5_esw_vport_alloc(esw, idx, idx); 2392 if (err) 2393 goto err; 2394 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_VF); 2395 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN); 2396 idx++; 2397 } 2398 } 2399 2400 base_sf_num = mlx5_sf_start_function_id(dev); 2401 for (i = 0; i < mlx5_sf_max_functions(dev); i++) { 2402 err = mlx5_esw_vport_alloc(esw, idx, base_sf_num + i); 2403 if (err) 2404 goto err; 2405 xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF); 2406 idx++; 2407 } 2408 2409 err = mlx5_esw_sf_max_hpf_functions(dev, &max_sfs, &base_sf_num); 2410 if (err) 2411 goto err; 2412 for (i = 0; i < max_sfs; i++) { 2413 err = mlx5_esw_vport_alloc(esw, idx, base_sf_num + i); 2414 if (err) 2415 goto err; 2416 xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF); 2417 idx++; 2418 } 2419 2420 err = mlx5_esw_spfs_init(esw); 2421 if (err) 2422 goto err; 2423 2424 for (i = 0; i < esw->esw_funcs.num_spfs; i++) { 2425 struct mlx5_vport *vport; 2426 u16 vport_num; 2427 2428 vport_num = esw->esw_funcs.spfs[i].vport_num; 2429 err = mlx5_esw_vport_alloc(esw, idx++, vport_num); 2430 if (err) 2431 goto err; 2432 vport = mlx5_eswitch_get_vport(esw, vport_num); 2433 vport->vhca_id = esw->esw_funcs.spfs[i].vhca_id; 2434 2435 err = mlx5_esw_sf_max_spf_functions(dev, i, 2436 &max_sfs, &base_sf_num); 2437 if (err) 2438 goto err; 2439 if (max_sfs) 2440 esw->esw_funcs.has_spf_sfs = true; 2441 for (int j = 0; j < max_sfs; j++) { 2442 err = mlx5_esw_vport_alloc(esw, idx, 2443 base_sf_num + j); 2444 if (err) 2445 goto err; 2446 xa_set_mark(&esw->vports, base_sf_num + j, 2447 MLX5_ESW_VPT_SF); 2448 idx++; 2449 } 2450 } 2451 2452 if (mlx5_core_ec_sriov_enabled(esw->dev)) { 2453 int ec_vf_base_num = mlx5_core_ec_vf_vport_base(dev); 2454 2455 for (i = 0; i < mlx5_core_max_ec_vfs(esw->dev); i++) { 2456 err = mlx5_esw_vport_alloc(esw, idx, ec_vf_base_num + i); 2457 if (err) 2458 goto err; 2459 idx++; 2460 } 2461 } 2462 2463 if (mlx5_ecpf_vport_exists(dev) || 2464 mlx5_core_is_ecpf_esw_manager(dev)) { 2465 err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_ECPF); 2466 if (err) 2467 goto err; 2468 idx++; 2469 } 2470 err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_UPLINK); 2471 if (err) 2472 goto err; 2473 2474 /* Adjacent vports or other dynamically create vports will use this */ 2475 esw->last_vport_idx = ++idx; 2476 return 0; 2477 2478 err: 2479 mlx5_esw_vports_cleanup(esw); 2480 return err; 2481 } 2482 2483 static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id, 2484 struct devlink_param_gset_ctx *ctx, 2485 struct netlink_ext_ack *extack) 2486 { 2487 struct mlx5_core_dev *dev = devlink_priv(devlink); 2488 2489 if (!MLX5_ESWITCH_MANAGER(dev)) 2490 return -EOPNOTSUPP; 2491 2492 if (ctx->val.vbool) 2493 return mlx5_lag_mpesw_enable(dev); 2494 2495 mlx5_lag_mpesw_disable(dev); 2496 return 0; 2497 } 2498 2499 static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id, 2500 struct devlink_param_gset_ctx *ctx, 2501 struct netlink_ext_ack *extack) 2502 { 2503 struct mlx5_core_dev *dev = devlink_priv(devlink); 2504 2505 ctx->val.vbool = mlx5_lag_is_mpesw(dev); 2506 return 0; 2507 } 2508 2509 static const struct devlink_param mlx5_eswitch_params[] = { 2510 DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT, 2511 "esw_multiport", DEVLINK_PARAM_TYPE_BOOL, 2512 BIT(DEVLINK_PARAM_CMODE_RUNTIME), 2513 mlx5_devlink_esw_multiport_get, 2514 mlx5_devlink_esw_multiport_set, NULL), 2515 }; 2516 2517 int mlx5_eswitch_init(struct mlx5_core_dev *dev) 2518 { 2519 struct mlx5_eswitch *esw; 2520 int err; 2521 2522 if (!MLX5_VPORT_MANAGER(dev) && !MLX5_ESWITCH_MANAGER(dev)) 2523 return 0; 2524 2525 esw = kzalloc_obj(*esw); 2526 if (!esw) 2527 return -ENOMEM; 2528 2529 err = devl_params_register(priv_to_devlink(dev), mlx5_eswitch_params, 2530 ARRAY_SIZE(mlx5_eswitch_params)); 2531 if (err) 2532 goto free_esw; 2533 2534 esw->dev = dev; 2535 dev->priv.eswitch = esw; 2536 esw->manager_vport = mlx5_eswitch_manager_vport(dev); 2537 esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev); 2538 2539 esw->debugfs_root = debugfs_create_dir("esw", mlx5_debugfs_get_dev_root(dev)); 2540 esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq"); 2541 if (!esw->work_queue) { 2542 err = -ENOMEM; 2543 goto abort; 2544 } 2545 2546 err = mlx5_esw_host_functions_enabled_query(esw); 2547 if (err) 2548 goto abort; 2549 2550 err = mlx5_esw_vports_init(esw); 2551 if (err) 2552 goto abort; 2553 2554 err = esw_offloads_init(esw); 2555 if (err) 2556 goto reps_err; 2557 2558 esw->mode = MLX5_ESWITCH_LEGACY; 2559 2560 mutex_init(&esw->offloads.encap_tbl_lock); 2561 hash_init(esw->offloads.encap_tbl); 2562 mutex_init(&esw->offloads.decap_tbl_lock); 2563 hash_init(esw->offloads.decap_tbl); 2564 mlx5e_mod_hdr_tbl_init(&esw->offloads.mod_hdr); 2565 atomic64_set(&esw->offloads.num_flows, 0); 2566 ida_init(&esw->offloads.vport_metadata_ida); 2567 xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC); 2568 xa_init(&esw->vhca_type_map); 2569 mutex_init(&esw->state_lock); 2570 init_rwsem(&esw->mode_lock); 2571 refcount_set(&esw->qos.refcnt, 0); 2572 init_waitqueue_head(&esw->work_queue_wait); 2573 atomic_set(&esw->generation, 0); 2574 2575 esw->enabled_vports = 0; 2576 esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE; 2577 if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) && 2578 MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap)) 2579 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; 2580 else 2581 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; 2582 2583 esw_info(dev, 2584 "Total vports %d, per vport: max uc(%d) max mc(%d)\n", 2585 esw->total_vports, 2586 MLX5_MAX_UC_PER_VPORT(dev), 2587 MLX5_MAX_MC_PER_VPORT(dev)); 2588 return 0; 2589 2590 reps_err: 2591 mlx5_esw_vports_cleanup(esw); 2592 dev->priv.eswitch = NULL; 2593 abort: 2594 if (esw->work_queue) 2595 destroy_workqueue(esw->work_queue); 2596 debugfs_remove_recursive(esw->debugfs_root); 2597 devl_params_unregister(priv_to_devlink(dev), mlx5_eswitch_params, 2598 ARRAY_SIZE(mlx5_eswitch_params)); 2599 free_esw: 2600 kfree(esw); 2601 return err; 2602 } 2603 2604 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) 2605 { 2606 if (!esw) 2607 return; 2608 2609 esw_info(esw->dev, "cleanup\n"); 2610 2611 mlx5_eswitch_invalidate_wq(esw); 2612 destroy_workqueue(esw->work_queue); 2613 WARN_ON(refcount_read(&esw->qos.refcnt)); 2614 mutex_destroy(&esw->state_lock); 2615 WARN_ON(!xa_empty(&esw->offloads.vhca_map)); 2616 xa_destroy(&esw->offloads.vhca_map); 2617 xa_destroy(&esw->vhca_type_map); 2618 ida_destroy(&esw->offloads.vport_metadata_ida); 2619 mlx5e_mod_hdr_tbl_destroy(&esw->offloads.mod_hdr); 2620 mutex_destroy(&esw->offloads.encap_tbl_lock); 2621 mutex_destroy(&esw->offloads.decap_tbl_lock); 2622 esw_offloads_cleanup(esw); 2623 esw->dev->priv.eswitch = NULL; 2624 mlx5_esw_vports_cleanup(esw); 2625 debugfs_remove_recursive(esw->debugfs_root); 2626 devl_params_unregister(priv_to_devlink(esw->dev), mlx5_eswitch_params, 2627 ARRAY_SIZE(mlx5_eswitch_params)); 2628 kfree(esw); 2629 } 2630 2631 /* Vport Administration */ 2632 static int 2633 mlx5_esw_set_vport_mac_locked(struct mlx5_eswitch *esw, 2634 struct mlx5_vport *evport, const u8 *mac) 2635 { 2636 u16 vport_num = evport->vport; 2637 u64 node_guid; 2638 int err = 0; 2639 2640 if (is_multicast_ether_addr(mac)) 2641 return -EINVAL; 2642 2643 if (evport->info.spoofchk && !is_valid_ether_addr(mac)) 2644 mlx5_core_warn(esw->dev, 2645 "Set invalid MAC while spoofchk is on, vport(%d)\n", 2646 vport_num); 2647 2648 err = mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, mac); 2649 if (err) { 2650 mlx5_core_warn(esw->dev, 2651 "Failed to mlx5_modify_nic_vport_mac vport(%d) err=(%d)\n", 2652 vport_num, err); 2653 return err; 2654 } 2655 2656 node_guid_gen_from_mac(&node_guid, mac); 2657 err = mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, node_guid); 2658 if (err) 2659 mlx5_core_warn(esw->dev, 2660 "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n", 2661 vport_num, err); 2662 2663 ether_addr_copy(evport->info.mac, mac); 2664 evport->info.node_guid = node_guid; 2665 if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) 2666 err = esw_acl_ingress_lgcy_setup(esw, evport); 2667 2668 return err; 2669 } 2670 2671 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, 2672 u16 vport, const u8 *mac) 2673 { 2674 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2675 int err = 0; 2676 2677 if (IS_ERR(evport)) 2678 return PTR_ERR(evport); 2679 2680 mutex_lock(&esw->state_lock); 2681 err = mlx5_esw_set_vport_mac_locked(esw, evport, mac); 2682 mutex_unlock(&esw->state_lock); 2683 return err; 2684 } 2685 2686 static bool mlx5_esw_check_port_type(struct mlx5_eswitch *esw, u16 vport_num, xa_mark_t mark) 2687 { 2688 return xa_get_mark(&esw->vports, vport_num, mark); 2689 } 2690 2691 bool mlx5_eswitch_is_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) 2692 { 2693 return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_VF); 2694 } 2695 2696 int mlx5_esw_spf_vport_to_idx(struct mlx5_eswitch *esw, u16 vport_num) 2697 { 2698 struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs; 2699 int i; 2700 2701 for (i = 0; i < esw_funcs->num_spfs; i++) { 2702 if (esw_funcs->spfs[i].vport_num == vport_num) 2703 return i; 2704 } 2705 2706 return -ENOENT; 2707 } 2708 2709 bool mlx5_esw_is_spf_vport(struct mlx5_eswitch *esw, u16 vport_num) 2710 { 2711 return mlx5_esw_spf_vport_to_idx(esw, vport_num) >= 0; 2712 } 2713 2714 bool mlx5_eswitch_is_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) 2715 { 2716 return vport_num == MLX5_VPORT_HOST_PF || 2717 mlx5_eswitch_is_vf_vport(esw, vport_num) || 2718 mlx5_esw_is_spf_vport(esw, vport_num); 2719 } 2720 2721 bool mlx5_esw_is_sf_vport(struct mlx5_eswitch *esw, u16 vport_num) 2722 { 2723 return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_SF); 2724 } 2725 2726 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, 2727 u16 vport, int link_state) 2728 { 2729 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2730 int opmod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT; 2731 int other_vport = 1; 2732 int err = 0; 2733 2734 if (!mlx5_esw_allowed(esw)) 2735 return -EPERM; 2736 if (IS_ERR(evport)) 2737 return PTR_ERR(evport); 2738 2739 if (vport == MLX5_VPORT_UPLINK) { 2740 opmod = MLX5_VPORT_STATE_OP_MOD_UPLINK; 2741 other_vport = 0; 2742 vport = 0; 2743 } 2744 mutex_lock(&esw->state_lock); 2745 if (esw->mode != MLX5_ESWITCH_LEGACY) { 2746 err = -EOPNOTSUPP; 2747 goto unlock; 2748 } 2749 2750 err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, other_vport, link_state); 2751 if (err) { 2752 mlx5_core_warn(esw->dev, "Failed to set vport %d link state, opmod = %d, err = %d", 2753 vport, opmod, err); 2754 goto unlock; 2755 } 2756 2757 evport->info.link_state = link_state; 2758 2759 unlock: 2760 mutex_unlock(&esw->state_lock); 2761 return err; 2762 } 2763 2764 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw, 2765 u16 vport, struct ifla_vf_info *ivi) 2766 { 2767 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2768 u32 max_rate, min_rate; 2769 2770 if (IS_ERR(evport)) 2771 return PTR_ERR(evport); 2772 2773 memset(ivi, 0, sizeof(*ivi)); 2774 ivi->vf = vport - 1; 2775 2776 mutex_lock(&esw->state_lock); 2777 2778 mlx5_query_nic_vport_mac_address(esw->dev, vport, true, 2779 evport->info.mac); 2780 ether_addr_copy(ivi->mac, evport->info.mac); 2781 ivi->linkstate = evport->info.link_state; 2782 ivi->vlan = evport->info.vlan; 2783 ivi->qos = evport->info.qos; 2784 ivi->spoofchk = evport->info.spoofchk; 2785 ivi->trusted = evport->info.trusted; 2786 2787 if (mlx5_esw_qos_get_vport_rate(evport, &max_rate, &min_rate)) { 2788 ivi->max_tx_rate = max_rate; 2789 ivi->min_tx_rate = min_rate; 2790 } 2791 mutex_unlock(&esw->state_lock); 2792 2793 return 0; 2794 } 2795 2796 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, 2797 u16 vport, u16 vlan, u8 qos, u8 set_flags) 2798 { 2799 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2800 bool vst_mode_steering = esw_vst_mode_is_steering(esw); 2801 int err = 0; 2802 2803 if (IS_ERR(evport)) 2804 return PTR_ERR(evport); 2805 if (vlan > 4095 || qos > 7) 2806 return -EINVAL; 2807 2808 if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering) { 2809 err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags); 2810 if (err) 2811 return err; 2812 } 2813 2814 evport->info.vlan = vlan; 2815 evport->info.qos = qos; 2816 if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) { 2817 err = esw_acl_ingress_lgcy_setup(esw, evport); 2818 if (err) 2819 return err; 2820 err = esw_acl_egress_lgcy_setup(esw, evport); 2821 } 2822 2823 return err; 2824 } 2825 2826 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, 2827 u16 vport_num, 2828 struct ifla_vf_stats *vf_stats) 2829 { 2830 struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); 2831 int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out); 2832 u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {}; 2833 struct mlx5_vport_drop_stats stats = {}; 2834 int err = 0; 2835 u32 *out; 2836 2837 if (IS_ERR(vport)) 2838 return PTR_ERR(vport); 2839 2840 out = kvzalloc(outlen, GFP_KERNEL); 2841 if (!out) 2842 return -ENOMEM; 2843 2844 MLX5_SET(query_vport_counter_in, in, opcode, 2845 MLX5_CMD_OP_QUERY_VPORT_COUNTER); 2846 MLX5_SET(query_vport_counter_in, in, op_mod, 0); 2847 MLX5_SET(query_vport_counter_in, in, vport_number, vport->vport); 2848 MLX5_SET(query_vport_counter_in, in, other_vport, 1); 2849 2850 err = mlx5_cmd_exec_inout(esw->dev, query_vport_counter, in, out); 2851 if (err) 2852 goto free_out; 2853 2854 #define MLX5_GET_CTR(p, x) \ 2855 MLX5_GET64(query_vport_counter_out, p, x) 2856 2857 memset(vf_stats, 0, sizeof(*vf_stats)); 2858 vf_stats->rx_packets = 2859 MLX5_GET_CTR(out, received_eth_unicast.packets) + 2860 MLX5_GET_CTR(out, received_ib_unicast.packets) + 2861 MLX5_GET_CTR(out, received_eth_multicast.packets) + 2862 MLX5_GET_CTR(out, received_ib_multicast.packets) + 2863 MLX5_GET_CTR(out, received_eth_broadcast.packets); 2864 2865 vf_stats->rx_bytes = 2866 MLX5_GET_CTR(out, received_eth_unicast.octets) + 2867 MLX5_GET_CTR(out, received_ib_unicast.octets) + 2868 MLX5_GET_CTR(out, received_eth_multicast.octets) + 2869 MLX5_GET_CTR(out, received_ib_multicast.octets) + 2870 MLX5_GET_CTR(out, received_eth_broadcast.octets); 2871 2872 vf_stats->tx_packets = 2873 MLX5_GET_CTR(out, transmitted_eth_unicast.packets) + 2874 MLX5_GET_CTR(out, transmitted_ib_unicast.packets) + 2875 MLX5_GET_CTR(out, transmitted_eth_multicast.packets) + 2876 MLX5_GET_CTR(out, transmitted_ib_multicast.packets) + 2877 MLX5_GET_CTR(out, transmitted_eth_broadcast.packets); 2878 2879 vf_stats->tx_bytes = 2880 MLX5_GET_CTR(out, transmitted_eth_unicast.octets) + 2881 MLX5_GET_CTR(out, transmitted_ib_unicast.octets) + 2882 MLX5_GET_CTR(out, transmitted_eth_multicast.octets) + 2883 MLX5_GET_CTR(out, transmitted_ib_multicast.octets) + 2884 MLX5_GET_CTR(out, transmitted_eth_broadcast.octets); 2885 2886 vf_stats->multicast = 2887 MLX5_GET_CTR(out, received_eth_multicast.packets) + 2888 MLX5_GET_CTR(out, received_ib_multicast.packets); 2889 2890 vf_stats->broadcast = 2891 MLX5_GET_CTR(out, received_eth_broadcast.packets); 2892 2893 err = mlx5_esw_query_vport_drop_stats(esw->dev, vport, &stats); 2894 if (err) 2895 goto free_out; 2896 vf_stats->rx_dropped = stats.rx_dropped; 2897 vf_stats->tx_dropped = stats.tx_dropped; 2898 2899 free_out: 2900 kvfree(out); 2901 return err; 2902 } 2903 2904 u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev) 2905 { 2906 struct mlx5_eswitch *esw = dev->priv.eswitch; 2907 2908 return mlx5_esw_allowed(esw) ? esw->mode : MLX5_ESWITCH_LEGACY; 2909 } 2910 EXPORT_SYMBOL_GPL(mlx5_eswitch_mode); 2911 2912 enum devlink_eswitch_encap_mode 2913 mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev) 2914 { 2915 struct mlx5_eswitch *esw; 2916 2917 esw = dev->priv.eswitch; 2918 return (mlx5_eswitch_mode(dev) == MLX5_ESWITCH_OFFLOADS) ? esw->offloads.encap : 2919 DEVLINK_ESWITCH_ENCAP_MODE_NONE; 2920 } 2921 EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode); 2922 2923 bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0, 2924 struct mlx5_core_dev *dev1) 2925 { 2926 return (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS && 2927 dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS); 2928 } 2929 2930 int mlx5_esw_event_notifier_register(struct mlx5_core_dev *dev, 2931 struct notifier_block *nb) 2932 { 2933 return blocking_notifier_chain_register(&dev->priv.esw_n_head, nb); 2934 } 2935 2936 void mlx5_esw_event_notifier_unregister(struct mlx5_core_dev *dev, 2937 struct notifier_block *nb) 2938 { 2939 blocking_notifier_chain_unregister(&dev->priv.esw_n_head, nb); 2940 } 2941 2942 /** 2943 * mlx5_esw_hold() - Try to take a read lock on esw mode lock. 2944 * @mdev: mlx5 core device. 2945 * 2946 * Should be called by esw resources callers. 2947 * 2948 * Return: true on success or false. 2949 */ 2950 bool mlx5_esw_hold(struct mlx5_core_dev *mdev) 2951 { 2952 struct mlx5_eswitch *esw = mdev->priv.eswitch; 2953 2954 /* e.g. VF doesn't have eswitch so nothing to do */ 2955 if (!mlx5_esw_allowed(esw)) 2956 return true; 2957 2958 if (down_read_trylock(&esw->mode_lock) != 0) { 2959 if (esw->eswitch_operation_in_progress) { 2960 up_read(&esw->mode_lock); 2961 return false; 2962 } 2963 return true; 2964 } 2965 2966 return false; 2967 } 2968 2969 /** 2970 * mlx5_esw_release() - Release a read lock on esw mode lock. 2971 * @mdev: mlx5 core device. 2972 */ 2973 void mlx5_esw_release(struct mlx5_core_dev *mdev) 2974 { 2975 struct mlx5_eswitch *esw = mdev->priv.eswitch; 2976 2977 if (mlx5_esw_allowed(esw)) 2978 up_read(&esw->mode_lock); 2979 } 2980 2981 /** 2982 * mlx5_esw_get() - Increase esw user count. 2983 * @mdev: mlx5 core device. 2984 */ 2985 void mlx5_esw_get(struct mlx5_core_dev *mdev) 2986 { 2987 struct mlx5_eswitch *esw = mdev->priv.eswitch; 2988 2989 if (mlx5_esw_allowed(esw)) 2990 atomic64_inc(&esw->user_count); 2991 } 2992 2993 /** 2994 * mlx5_esw_put() - Decrease esw user count. 2995 * @mdev: mlx5 core device. 2996 */ 2997 void mlx5_esw_put(struct mlx5_core_dev *mdev) 2998 { 2999 struct mlx5_eswitch *esw = mdev->priv.eswitch; 3000 3001 if (mlx5_esw_allowed(esw)) 3002 atomic64_dec_if_positive(&esw->user_count); 3003 } 3004 3005 /** 3006 * mlx5_esw_try_lock() - Take a write lock on esw mode lock. 3007 * @esw: eswitch device. 3008 * 3009 * Should be called by esw mode change routine. 3010 * 3011 * Return: 3012 * * 0 - esw mode if successfully locked and refcount is 0. 3013 * * -EBUSY - refcount is not 0. 3014 * * -EINVAL - In the middle of switching mode or lock is already held. 3015 */ 3016 int mlx5_esw_try_lock(struct mlx5_eswitch *esw) 3017 { 3018 if (down_write_trylock(&esw->mode_lock) == 0) 3019 return -EINVAL; 3020 3021 if (esw->eswitch_operation_in_progress || 3022 atomic64_read(&esw->user_count) > 0) { 3023 up_write(&esw->mode_lock); 3024 return -EBUSY; 3025 } 3026 3027 return esw->mode; 3028 } 3029 3030 int mlx5_esw_lock(struct mlx5_eswitch *esw) 3031 { 3032 down_write(&esw->mode_lock); 3033 3034 if (esw->eswitch_operation_in_progress) { 3035 up_write(&esw->mode_lock); 3036 return -EBUSY; 3037 } 3038 3039 return 0; 3040 } 3041 3042 /** 3043 * mlx5_esw_unlock() - Release write lock on esw mode lock 3044 * @esw: eswitch device. 3045 */ 3046 void mlx5_esw_unlock(struct mlx5_eswitch *esw) 3047 { 3048 up_write(&esw->mode_lock); 3049 } 3050 3051 /** 3052 * mlx5_eswitch_get_total_vports - Get total vports of the eswitch 3053 * 3054 * @dev: Pointer to core device 3055 * 3056 * mlx5_eswitch_get_total_vports returns total number of eswitch vports. 3057 */ 3058 u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev) 3059 { 3060 struct mlx5_eswitch *esw; 3061 3062 esw = dev->priv.eswitch; 3063 return mlx5_esw_allowed(esw) ? esw->total_vports : 0; 3064 } 3065 EXPORT_SYMBOL_GPL(mlx5_eswitch_get_total_vports); 3066 3067 /** 3068 * mlx5_eswitch_get_core_dev - Get the mdev device 3069 * @esw : eswitch device. 3070 * 3071 * Return the mellanox core device which manages the eswitch. 3072 */ 3073 struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw) 3074 { 3075 return mlx5_esw_allowed(esw) ? esw->dev : NULL; 3076 } 3077 EXPORT_SYMBOL(mlx5_eswitch_get_core_dev); 3078 3079 bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev) 3080 { 3081 struct mlx5_eswitch *esw = dev->priv.eswitch; 3082 3083 if (!mlx5_esw_allowed(esw)) 3084 return true; 3085 3086 mutex_lock(&esw->state_lock); 3087 if (esw->enabled_ipsec_vf_count) { 3088 mutex_unlock(&esw->state_lock); 3089 return false; 3090 } 3091 3092 dev->num_ipsec_offloads++; 3093 mutex_unlock(&esw->state_lock); 3094 return true; 3095 } 3096 3097 void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev) 3098 { 3099 struct mlx5_eswitch *esw = dev->priv.eswitch; 3100 3101 if (!mlx5_esw_allowed(esw)) 3102 /* Failure means no eswitch => core dev is not a PF */ 3103 return; 3104 3105 mutex_lock(&esw->state_lock); 3106 dev->num_ipsec_offloads--; 3107 mutex_unlock(&esw->state_lock); 3108 } 3109 3110 bool mlx5_esw_host_functions_enabled(const struct mlx5_core_dev *dev) 3111 { 3112 if (!dev->priv.eswitch) 3113 return true; 3114 3115 return !dev->priv.eswitch->esw_funcs.host_funcs_disabled; 3116 } 3117