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 /* We don't assume VFs will cleanup after themselves. 1044 * Calling vport change handler while vport is disabled will cleanup 1045 * the vport resources. 1046 */ 1047 esw_vport_change_handle_locked(vport); 1048 vport->enabled_events = 0; 1049 esw_apply_vport_rx_mode(esw, vport, false, false); 1050 esw_vport_cleanup(esw, vport); 1051 esw->enabled_vports--; 1052 1053 done: 1054 mutex_unlock(&esw->state_lock); 1055 } 1056 1057 static int eswitch_vport_event(struct notifier_block *nb, 1058 unsigned long type, void *data) 1059 { 1060 struct mlx5_eswitch *esw = mlx5_nb_cof(nb, struct mlx5_eswitch, nb); 1061 struct mlx5_eqe *eqe = data; 1062 struct mlx5_vport *vport; 1063 u16 vport_num; 1064 1065 vport_num = be16_to_cpu(eqe->data.vport_change.vport_num); 1066 vport = mlx5_eswitch_get_vport(esw, vport_num); 1067 if (!IS_ERR(vport)) 1068 queue_work(esw->work_queue, &vport->vport_change_handler); 1069 return NOTIFY_OK; 1070 } 1071 1072 /** 1073 * mlx5_esw_query_functions - Returns raw output about functions state 1074 * @dev: Pointer to device to query 1075 * 1076 * mlx5_esw_query_functions() allocates and returns functions changed 1077 * raw output memory pointer from device on success. Otherwise returns ERR_PTR. 1078 * Caller must free the memory using kvfree() when valid pointer is returned. 1079 */ 1080 const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev) 1081 { 1082 bool net_func_v1 = MLX5_CAP_GEN(dev, query_host_net_function_v1); 1083 u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {}; 1084 int alloc_entries; 1085 int outlen; 1086 u32 *out; 1087 int err; 1088 1089 if (net_func_v1) { 1090 alloc_entries = MLX5_CAP_GEN(dev, 1091 query_host_net_function_num_max); 1092 alloc_entries = max(alloc_entries, 1); 1093 MLX5_SET(query_esw_functions_in, in, op_mod, 1094 MLX5_QUERY_ESW_FUNC_OP_MOD_LAYOUT_V1); 1095 outlen = MLX5_BYTE_OFF(query_esw_functions_out, 1096 net_function_params) + 1097 alloc_entries * MLX5_UN_SZ_BYTES(net_function_params); 1098 outlen = max_t(int, outlen, 1099 MLX5_ST_SZ_BYTES(query_esw_functions_out)); 1100 } else { 1101 outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out); 1102 } 1103 1104 out = kvzalloc(outlen, GFP_KERNEL); 1105 if (!out) 1106 return ERR_PTR(-ENOMEM); 1107 1108 MLX5_SET(query_esw_functions_in, in, opcode, 1109 MLX5_CMD_OP_QUERY_ESW_FUNCTIONS); 1110 1111 err = mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); 1112 if (err) 1113 goto free; 1114 1115 if (net_func_v1) { 1116 int num_entries; 1117 1118 num_entries = MLX5_GET(query_esw_functions_out, out, 1119 net_function_num); 1120 if (num_entries > alloc_entries) { 1121 mlx5_core_warn(dev, "Got %d entries, max expected %d\n", 1122 num_entries, alloc_entries); 1123 err = -EINVAL; 1124 goto free; 1125 } 1126 } 1127 1128 return out; 1129 1130 free: 1131 kvfree(out); 1132 return ERR_PTR(err); 1133 } 1134 1135 static struct mlx5_esw_pf_info 1136 mlx5_esw_host_pf_from_host_params(const void *entry) 1137 { 1138 return (struct mlx5_esw_pf_info) { 1139 .pf_not_exist = MLX5_GET(host_params_context, entry, 1140 host_pf_not_exist), 1141 .pf_disabled = MLX5_GET(host_params_context, entry, 1142 host_pf_disabled), 1143 .num_of_vfs = MLX5_GET(host_params_context, entry, 1144 host_num_of_vfs), 1145 .total_vfs = MLX5_GET(host_params_context, entry, 1146 host_total_vfs), 1147 .host_number = MLX5_GET(host_params_context, entry, 1148 host_number), 1149 }; 1150 } 1151 1152 static struct mlx5_esw_pf_info 1153 mlx5_esw_host_pf_from_net_func_params(const u8 *entry, int num_entries) 1154 { 1155 int i; 1156 1157 for (i = 0; i < num_entries; i++) { 1158 int pf_type, state; 1159 1160 pf_type = MLX5_GET(network_function_params, entry, pci_pf_type); 1161 if (pf_type != MLX5_PCI_PF_TYPE_EXTERNAL_HOST_PF) { 1162 entry += MLX5_UN_SZ_BYTES(net_function_params); 1163 continue; 1164 } 1165 1166 state = MLX5_GET(network_function_params, entry, vhca_state); 1167 1168 return (struct mlx5_esw_pf_info) { 1169 .pf_disabled = state != MLX5_VHCA_STATE_IN_USE, 1170 .num_of_vfs = MLX5_GET(network_function_params, 1171 entry, pci_num_vfs), 1172 .total_vfs = MLX5_GET(network_function_params, 1173 entry, pci_total_vfs), 1174 .host_number = MLX5_GET(network_function_params, 1175 entry, host_number), 1176 .pf_num = MLX5_GET(network_function_params, entry, 1177 pci_device_function), 1178 }; 1179 } 1180 1181 /* No external host PF entry found */ 1182 return (struct mlx5_esw_pf_info) { 1183 .pf_not_exist = true, 1184 .pf_disabled = true, 1185 }; 1186 } 1187 1188 struct mlx5_esw_pf_info 1189 mlx5_esw_get_host_pf_info(struct mlx5_core_dev *dev, const u32 *out) 1190 { 1191 const void *entry; 1192 1193 entry = MLX5_ADDR_OF(query_esw_functions_out, out, net_function_params); 1194 1195 if (MLX5_CAP_GEN(dev, query_host_net_function_v1)) { 1196 int num_entries = MLX5_GET(query_esw_functions_out, out, 1197 net_function_num); 1198 1199 return mlx5_esw_host_pf_from_net_func_params(entry, 1200 num_entries); 1201 } 1202 1203 return mlx5_esw_host_pf_from_host_params(entry); 1204 } 1205 1206 bool mlx5_esw_get_spf_disabled(struct mlx5_core_dev *dev, const u32 *out, 1207 u16 vhca_id) 1208 { 1209 int num_entries; 1210 const u8 *entry; 1211 int i; 1212 1213 num_entries = MLX5_GET(query_esw_functions_out, out, net_function_num); 1214 entry = MLX5_ADDR_OF(query_esw_functions_out, out, net_function_params); 1215 1216 for (i = 0; i < num_entries; i++) { 1217 u16 entry_vhca_id = MLX5_GET(network_function_params, 1218 entry, vhca_id); 1219 1220 if (entry_vhca_id == vhca_id) { 1221 int state; 1222 1223 state = MLX5_GET(network_function_params, entry, 1224 vhca_state); 1225 return state != MLX5_VHCA_STATE_IN_USE; 1226 } 1227 entry += MLX5_UN_SZ_BYTES(net_function_params); 1228 } 1229 1230 return true; 1231 } 1232 1233 static int mlx5_esw_host_functions_enabled_query(struct mlx5_eswitch *esw) 1234 { 1235 struct mlx5_esw_pf_info host_pf_info; 1236 const u32 *query_host_out; 1237 1238 if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) 1239 return 0; 1240 1241 query_host_out = mlx5_esw_query_functions(esw->dev); 1242 if (IS_ERR(query_host_out)) 1243 return PTR_ERR(query_host_out); 1244 1245 host_pf_info = mlx5_esw_get_host_pf_info(esw->dev, query_host_out); 1246 esw->esw_funcs.host_funcs_disabled = host_pf_info.pf_not_exist; 1247 1248 kvfree(query_host_out); 1249 return 0; 1250 } 1251 1252 static void mlx5_eswitch_event_handler_register(struct mlx5_eswitch *esw) 1253 { 1254 if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) { 1255 MLX5_NB_INIT(&esw->esw_funcs.nb, mlx5_esw_funcs_changed_handler, 1256 ESW_FUNCTIONS_CHANGED); 1257 mlx5_eq_notifier_register(esw->dev, &esw->esw_funcs.nb); 1258 } 1259 } 1260 1261 static void mlx5_eswitch_invalidate_wq(struct mlx5_eswitch *esw) 1262 { 1263 atomic_inc(&esw->generation); 1264 wake_up_all(&esw->work_queue_wait); 1265 } 1266 1267 static void mlx5_eswitch_event_handler_unregister(struct mlx5_eswitch *esw) 1268 { 1269 if (esw->mode == MLX5_ESWITCH_OFFLOADS && 1270 mlx5_eswitch_is_funcs_handler(esw->dev)) 1271 mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb); 1272 } 1273 1274 static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw) 1275 { 1276 struct mlx5_vport *vport; 1277 unsigned long i; 1278 1279 mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) { 1280 mlx5_esw_qos_vport_qos_free(vport); 1281 memset(&vport->info, 0, sizeof(vport->info)); 1282 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 1283 } 1284 } 1285 1286 static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw) 1287 { 1288 struct mlx5_vport *vport; 1289 unsigned long i; 1290 1291 mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) { 1292 mlx5_esw_qos_vport_qos_free(vport); 1293 memset(&vport->info, 0, sizeof(vport->info)); 1294 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 1295 } 1296 } 1297 1298 static int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport, 1299 enum mlx5_eswitch_vport_event enabled_events) 1300 { 1301 int err; 1302 1303 err = mlx5_esw_vport_enable(esw, vport, enabled_events); 1304 if (err) 1305 return err; 1306 1307 err = mlx5_esw_offloads_load_rep(esw, vport); 1308 if (err) 1309 goto err_rep; 1310 1311 return err; 1312 1313 err_rep: 1314 mlx5_esw_vport_disable(esw, vport); 1315 return err; 1316 } 1317 1318 static void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 1319 { 1320 mlx5_esw_offloads_unload_rep(esw, vport); 1321 mlx5_esw_vport_disable(esw, vport); 1322 } 1323 1324 static int mlx5_eswitch_load_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num, 1325 enum mlx5_eswitch_vport_event enabled_events) 1326 { 1327 struct mlx5_vport *vport; 1328 int err; 1329 1330 vport = mlx5_eswitch_get_vport(esw, vport_num); 1331 if (IS_ERR(vport)) 1332 return PTR_ERR(vport); 1333 1334 err = mlx5_esw_offloads_init_pf_vf_rep(esw, vport); 1335 if (err) 1336 return err; 1337 1338 err = mlx5_eswitch_load_vport(esw, vport, enabled_events); 1339 if (err) 1340 goto err_load; 1341 return 0; 1342 1343 err_load: 1344 mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport); 1345 return err; 1346 } 1347 1348 static void mlx5_eswitch_unload_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) 1349 { 1350 struct mlx5_vport *vport; 1351 1352 vport = mlx5_eswitch_get_vport(esw, vport_num); 1353 if (IS_ERR(vport)) 1354 return; 1355 1356 mlx5_eswitch_unload_vport(esw, vport); 1357 mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport); 1358 } 1359 1360 int mlx5_eswitch_load_sf_vport(struct mlx5_eswitch *esw, u16 vport_num, 1361 enum mlx5_eswitch_vport_event enabled_events, 1362 struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum) 1363 { 1364 struct mlx5_vport *vport; 1365 int err; 1366 1367 vport = mlx5_eswitch_get_vport(esw, vport_num); 1368 if (IS_ERR(vport)) 1369 return PTR_ERR(vport); 1370 1371 err = mlx5_esw_offloads_init_sf_rep(esw, vport, dl_port, controller, sfnum); 1372 if (err) 1373 return err; 1374 1375 err = mlx5_eswitch_load_vport(esw, vport, enabled_events); 1376 if (err) 1377 goto err_load; 1378 1379 return 0; 1380 1381 err_load: 1382 mlx5_esw_offloads_cleanup_sf_rep(esw, vport); 1383 return err; 1384 } 1385 1386 void mlx5_eswitch_unload_sf_vport(struct mlx5_eswitch *esw, u16 vport_num) 1387 { 1388 struct mlx5_vport *vport; 1389 1390 vport = mlx5_eswitch_get_vport(esw, vport_num); 1391 if (IS_ERR(vport)) 1392 return; 1393 1394 mlx5_eswitch_unload_vport(esw, vport); 1395 mlx5_esw_offloads_cleanup_sf_rep(esw, vport); 1396 } 1397 1398 void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs) 1399 { 1400 struct mlx5_vport *vport; 1401 unsigned long i; 1402 1403 mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) { 1404 /* Adjacent VFs are unloaded separately */ 1405 if (!vport->enabled || vport->adjacent) 1406 continue; 1407 mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport); 1408 } 1409 } 1410 1411 static void mlx5_eswitch_unload_ec_vf_vports(struct mlx5_eswitch *esw, 1412 u16 num_ec_vfs) 1413 { 1414 struct mlx5_vport *vport; 1415 unsigned long i; 1416 1417 mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { 1418 if (!vport->enabled) 1419 continue; 1420 mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport); 1421 } 1422 } 1423 1424 static void mlx5_eswitch_unload_adj_vf_vports(struct mlx5_eswitch *esw) 1425 { 1426 struct mlx5_vport *vport; 1427 unsigned long i; 1428 1429 mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) { 1430 if (!vport->enabled || !vport->adjacent) 1431 continue; 1432 mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport); 1433 } 1434 } 1435 1436 static int 1437 mlx5_eswitch_load_adj_vf_vports(struct mlx5_eswitch *esw, 1438 enum mlx5_eswitch_vport_event enabled_events) 1439 { 1440 struct mlx5_vport *vport; 1441 unsigned long i; 1442 int err; 1443 1444 mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) { 1445 if (!vport->adjacent) 1446 continue; 1447 err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, 1448 enabled_events); 1449 if (err) 1450 goto unload_adj_vf_vport; 1451 } 1452 1453 return 0; 1454 1455 unload_adj_vf_vport: 1456 mlx5_eswitch_unload_adj_vf_vports(esw); 1457 return err; 1458 } 1459 1460 int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, 1461 enum mlx5_eswitch_vport_event enabled_events) 1462 { 1463 struct mlx5_vport *vport; 1464 unsigned long i; 1465 int err; 1466 1467 mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) { 1468 err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events); 1469 if (err) 1470 goto vf_err; 1471 } 1472 1473 return 0; 1474 1475 vf_err: 1476 mlx5_eswitch_unload_vf_vports(esw, num_vfs); 1477 return err; 1478 } 1479 1480 static int mlx5_eswitch_load_ec_vf_vports(struct mlx5_eswitch *esw, u16 num_ec_vfs, 1481 enum mlx5_eswitch_vport_event enabled_events) 1482 { 1483 struct mlx5_vport *vport; 1484 unsigned long i; 1485 int err; 1486 1487 mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { 1488 err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events); 1489 if (err) 1490 goto vf_err; 1491 } 1492 1493 return 0; 1494 1495 vf_err: 1496 mlx5_eswitch_unload_ec_vf_vports(esw, num_ec_vfs); 1497 return err; 1498 } 1499 1500 int mlx5_esw_pf_enable_hca(struct mlx5_core_dev *dev, u16 vport_num) 1501 { 1502 struct mlx5_eswitch *esw = dev->priv.eswitch; 1503 struct mlx5_vport *vport; 1504 int err; 1505 1506 if (!mlx5_core_is_ecpf(dev) || !mlx5_esw_allowed(esw)) 1507 return 0; 1508 1509 vport = mlx5_eswitch_get_vport(esw, vport_num); 1510 if (IS_ERR(vport)) 1511 return PTR_ERR(vport); 1512 1513 /* Once vport and representor are ready, take the PF out of 1514 * initializing state. Enabling HCA clears the iser->initializing 1515 * bit and PF driver loading can progress. 1516 */ 1517 err = mlx5_cmd_pf_enable_hca(dev, vport_num); 1518 if (err) 1519 return err; 1520 1521 vport->pf_activated = true; 1522 1523 return 0; 1524 } 1525 1526 int mlx5_esw_pf_disable_hca(struct mlx5_core_dev *dev, u16 vport_num) 1527 { 1528 struct mlx5_eswitch *esw = dev->priv.eswitch; 1529 struct mlx5_vport *vport; 1530 int err; 1531 1532 if (!mlx5_core_is_ecpf(dev) || !mlx5_esw_allowed(esw)) 1533 return 0; 1534 1535 vport = mlx5_eswitch_get_vport(esw, vport_num); 1536 if (IS_ERR(vport)) 1537 return PTR_ERR(vport); 1538 1539 err = mlx5_cmd_pf_disable_hca(dev, vport_num); 1540 if (err) 1541 return err; 1542 1543 vport->pf_activated = false; 1544 1545 return 0; 1546 } 1547 1548 int mlx5_esw_host_pf_enable_hca(struct mlx5_core_dev *dev) 1549 { 1550 return mlx5_esw_pf_enable_hca(dev, MLX5_VPORT_HOST_PF); 1551 } 1552 1553 int mlx5_esw_host_pf_disable_hca(struct mlx5_core_dev *dev) 1554 { 1555 return mlx5_esw_pf_disable_hca(dev, MLX5_VPORT_HOST_PF); 1556 } 1557 1558 /* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs 1559 * whichever are present on the eswitch. 1560 */ 1561 int 1562 mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, 1563 enum mlx5_eswitch_vport_event enabled_events) 1564 { 1565 struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs; 1566 bool pf_needed; 1567 u16 vport_num; 1568 int ret; 1569 int i; 1570 1571 pf_needed = mlx5_core_is_ecpf_esw_manager(esw->dev) || 1572 esw->mode == MLX5_ESWITCH_LEGACY; 1573 1574 /* Enable PF vport */ 1575 if (pf_needed && mlx5_esw_host_functions_enabled(esw->dev)) { 1576 ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_HOST_PF, 1577 enabled_events); 1578 if (ret) 1579 return ret; 1580 } 1581 1582 if (mlx5_esw_host_functions_enabled(esw->dev)) { 1583 /* Enable external host PF HCA */ 1584 ret = mlx5_esw_host_pf_enable_hca(esw->dev); 1585 if (ret) 1586 goto pf_hca_err; 1587 } 1588 1589 /* Enable ECPF vport */ 1590 if (mlx5_ecpf_vport_exists(esw->dev)) { 1591 ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_ECPF, enabled_events); 1592 if (ret) 1593 goto ecpf_err; 1594 } 1595 1596 /* Enable ECVF vports */ 1597 if (mlx5_core_ec_sriov_enabled(esw->dev)) { 1598 ret = mlx5_eswitch_load_ec_vf_vports(esw, 1599 esw_funcs->num_ec_vfs, 1600 enabled_events); 1601 if (ret) 1602 goto ec_vf_err; 1603 } 1604 1605 /* Enable VF vports */ 1606 ret = mlx5_eswitch_load_vf_vports(esw, esw_funcs->num_vfs, 1607 enabled_events); 1608 if (ret) 1609 goto vf_err; 1610 1611 /* Enable adjacent VF vports */ 1612 ret = mlx5_eswitch_load_adj_vf_vports(esw, enabled_events); 1613 if (ret) 1614 goto unload_vf_vports; 1615 1616 /* Enable satellite PF vports */ 1617 for (i = 0; i < esw_funcs->num_spfs; i++) { 1618 vport_num = esw_funcs->spfs[i].vport_num; 1619 1620 ret = mlx5_eswitch_load_pf_vf_vport(esw, vport_num, 1621 enabled_events); 1622 if (ret) 1623 goto spf_err; 1624 1625 ret = mlx5_esw_pf_enable_hca(esw->dev, vport_num); 1626 if (ret) { 1627 mlx5_eswitch_unload_pf_vf_vport(esw, vport_num); 1628 goto spf_err; 1629 } 1630 } 1631 1632 return 0; 1633 1634 spf_err: 1635 while (i-- > 0) { 1636 vport_num = esw_funcs->spfs[i].vport_num; 1637 mlx5_esw_pf_disable_hca(esw->dev, vport_num); 1638 mlx5_eswitch_unload_pf_vf_vport(esw, vport_num); 1639 } 1640 mlx5_eswitch_unload_adj_vf_vports(esw); 1641 unload_vf_vports: 1642 mlx5_eswitch_unload_vf_vports(esw, esw_funcs->num_vfs); 1643 vf_err: 1644 if (mlx5_core_ec_sriov_enabled(esw->dev)) 1645 mlx5_eswitch_unload_ec_vf_vports(esw, esw_funcs->num_ec_vfs); 1646 ec_vf_err: 1647 if (mlx5_ecpf_vport_exists(esw->dev)) 1648 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF); 1649 ecpf_err: 1650 if (mlx5_esw_host_functions_enabled(esw->dev)) 1651 mlx5_esw_host_pf_disable_hca(esw->dev); 1652 pf_hca_err: 1653 if (pf_needed && mlx5_esw_host_functions_enabled(esw->dev)) 1654 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_HOST_PF); 1655 return ret; 1656 } 1657 1658 /* mlx5_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs 1659 * whichever are previously enabled on the eswitch. 1660 */ 1661 void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw) 1662 { 1663 struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs; 1664 u16 vport_num; 1665 int i; 1666 1667 for (i = 0; i < esw_funcs->num_spfs; i++) { 1668 vport_num = esw_funcs->spfs[i].vport_num; 1669 mlx5_esw_pf_disable_hca(esw->dev, vport_num); 1670 mlx5_eswitch_unload_pf_vf_vport(esw, vport_num); 1671 } 1672 1673 mlx5_eswitch_unload_adj_vf_vports(esw); 1674 1675 mlx5_eswitch_unload_vf_vports(esw, esw_funcs->num_vfs); 1676 1677 if (mlx5_core_ec_sriov_enabled(esw->dev)) 1678 mlx5_eswitch_unload_ec_vf_vports(esw, esw_funcs->num_ec_vfs); 1679 1680 if (mlx5_ecpf_vport_exists(esw->dev)) { 1681 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF); 1682 } 1683 1684 if (mlx5_esw_host_functions_enabled(esw->dev)) 1685 mlx5_esw_host_pf_disable_hca(esw->dev); 1686 1687 if ((mlx5_core_is_ecpf_esw_manager(esw->dev) || 1688 esw->mode == MLX5_ESWITCH_LEGACY) && 1689 mlx5_esw_host_functions_enabled(esw->dev)) 1690 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_HOST_PF); 1691 } 1692 1693 static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw) 1694 { 1695 struct devlink *devlink = priv_to_devlink(esw->dev); 1696 union devlink_param_value val; 1697 int err; 1698 1699 err = devl_param_driverinit_value_get(devlink, 1700 MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 1701 &val); 1702 if (!err) { 1703 esw->params.large_group_num = val.vu32; 1704 } else { 1705 esw_warn(esw->dev, 1706 "Devlink can't get param fdb_large_groups, uses default (%d).\n", 1707 ESW_OFFLOADS_DEFAULT_NUM_GROUPS); 1708 esw->params.large_group_num = ESW_OFFLOADS_DEFAULT_NUM_GROUPS; 1709 } 1710 } 1711 1712 static void 1713 mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs) 1714 { 1715 struct mlx5_esw_pf_info host_pf_info; 1716 const u32 *out; 1717 1718 if (num_vfs < 0) 1719 return; 1720 1721 if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) { 1722 esw->esw_funcs.num_vfs = num_vfs; 1723 return; 1724 } 1725 1726 out = mlx5_esw_query_functions(esw->dev); 1727 if (IS_ERR(out)) 1728 return; 1729 1730 host_pf_info = mlx5_esw_get_host_pf_info(esw->dev, out); 1731 esw->esw_funcs.num_vfs = host_pf_info.num_of_vfs; 1732 if (mlx5_core_ec_sriov_enabled(esw->dev)) 1733 esw->esw_funcs.num_ec_vfs = num_vfs; 1734 1735 kvfree(out); 1736 } 1737 1738 static void mlx5_esw_mode_change_notify(struct mlx5_eswitch *esw, u16 mode) 1739 { 1740 struct mlx5_esw_event_info info = {}; 1741 1742 info.new_mode = mode; 1743 1744 blocking_notifier_call_chain(&esw->dev->priv.esw_n_head, 0, &info); 1745 } 1746 1747 static int mlx5_esw_egress_acls_init(struct mlx5_core_dev *dev) 1748 { 1749 struct mlx5_flow_steering *steering = dev->priv.steering; 1750 int total_vports = mlx5_eswitch_get_total_vports(dev); 1751 int err; 1752 int i; 1753 1754 for (i = 0; i < total_vports; i++) { 1755 err = mlx5_fs_vport_egress_acl_ns_add(steering, i); 1756 if (err) 1757 goto acl_ns_remove; 1758 } 1759 return 0; 1760 1761 acl_ns_remove: 1762 while (i--) 1763 mlx5_fs_vport_egress_acl_ns_remove(steering, i); 1764 return err; 1765 } 1766 1767 static void mlx5_esw_egress_acls_cleanup(struct mlx5_core_dev *dev) 1768 { 1769 struct mlx5_flow_steering *steering = dev->priv.steering; 1770 int total_vports = mlx5_eswitch_get_total_vports(dev); 1771 int i; 1772 1773 for (i = total_vports - 1; i >= 0; i--) 1774 mlx5_fs_vport_egress_acl_ns_remove(steering, i); 1775 } 1776 1777 static int mlx5_esw_ingress_acls_init(struct mlx5_core_dev *dev) 1778 { 1779 struct mlx5_flow_steering *steering = dev->priv.steering; 1780 int total_vports = mlx5_eswitch_get_total_vports(dev); 1781 int err; 1782 int i; 1783 1784 for (i = 0; i < total_vports; i++) { 1785 err = mlx5_fs_vport_ingress_acl_ns_add(steering, i); 1786 if (err) 1787 goto acl_ns_remove; 1788 } 1789 return 0; 1790 1791 acl_ns_remove: 1792 while (i--) 1793 mlx5_fs_vport_ingress_acl_ns_remove(steering, i); 1794 return err; 1795 } 1796 1797 static void mlx5_esw_ingress_acls_cleanup(struct mlx5_core_dev *dev) 1798 { 1799 struct mlx5_flow_steering *steering = dev->priv.steering; 1800 int total_vports = mlx5_eswitch_get_total_vports(dev); 1801 int i; 1802 1803 for (i = total_vports - 1; i >= 0; i--) 1804 mlx5_fs_vport_ingress_acl_ns_remove(steering, i); 1805 } 1806 1807 static int mlx5_esw_acls_ns_init(struct mlx5_eswitch *esw) 1808 { 1809 struct mlx5_core_dev *dev = esw->dev; 1810 int err; 1811 1812 if (esw->flags & MLX5_ESWITCH_VPORT_ACL_NS_CREATED) 1813 return 0; 1814 1815 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) { 1816 err = mlx5_esw_egress_acls_init(dev); 1817 if (err) 1818 return err; 1819 } else { 1820 esw_warn(dev, "egress ACL is not supported by FW\n"); 1821 } 1822 1823 if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) { 1824 err = mlx5_esw_ingress_acls_init(dev); 1825 if (err) 1826 goto err; 1827 } else { 1828 esw_warn(dev, "ingress ACL is not supported by FW\n"); 1829 } 1830 esw->flags |= MLX5_ESWITCH_VPORT_ACL_NS_CREATED; 1831 return 0; 1832 1833 err: 1834 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) 1835 mlx5_esw_egress_acls_cleanup(dev); 1836 return err; 1837 } 1838 1839 static void mlx5_esw_acls_ns_cleanup(struct mlx5_eswitch *esw) 1840 { 1841 struct mlx5_core_dev *dev = esw->dev; 1842 1843 esw->flags &= ~MLX5_ESWITCH_VPORT_ACL_NS_CREATED; 1844 if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) 1845 mlx5_esw_ingress_acls_cleanup(dev); 1846 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) 1847 mlx5_esw_egress_acls_cleanup(dev); 1848 } 1849 1850 /** 1851 * mlx5_eswitch_enable_locked - Enable eswitch 1852 * @esw: Pointer to eswitch 1853 * @num_vfs: Enable eswitch for given number of VFs. This is optional. 1854 * Valid value are 0, > 0 and MLX5_ESWITCH_IGNORE_NUM_VFS. 1855 * Caller should pass num_vfs > 0 when enabling eswitch for 1856 * vf vports. Caller should pass num_vfs = 0, when eswitch 1857 * is enabled without sriov VFs or when caller 1858 * is unaware of the sriov state of the host PF on ECPF based 1859 * eswitch. Caller should pass < 0 when num_vfs should be 1860 * completely ignored. This is typically the case when eswitch 1861 * is enabled without sriov regardless of PF/ECPF system. 1862 * mlx5_eswitch_enable_locked() Enables eswitch in either legacy or offloads 1863 * mode. If num_vfs >=0 is provided, it setup VF related eswitch vports. 1864 * It returns 0 on success or error code on failure. 1865 */ 1866 int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs) 1867 { 1868 int err; 1869 1870 devl_assert_locked(priv_to_devlink(esw->dev)); 1871 1872 if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) { 1873 esw_warn(esw->dev, "FDB is not supported, aborting ...\n"); 1874 return -EOPNOTSUPP; 1875 } 1876 1877 mlx5_eswitch_get_devlink_param(esw); 1878 1879 err = mlx5_esw_acls_ns_init(esw); 1880 if (err) 1881 return err; 1882 1883 mlx5_eswitch_update_num_of_vfs(esw, num_vfs); 1884 1885 MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE); 1886 mlx5_eq_notifier_register(esw->dev, &esw->nb); 1887 1888 err = mlx5_esw_qos_init(esw); 1889 if (err) 1890 goto err_esw_init; 1891 1892 if (esw->mode == MLX5_ESWITCH_LEGACY) { 1893 err = esw_legacy_enable(esw); 1894 } else { 1895 err = esw_offloads_enable(esw); 1896 } 1897 1898 if (err) 1899 goto err_esw_init; 1900 1901 esw->fdb_table.flags |= MLX5_ESW_FDB_CREATED; 1902 1903 mlx5_eswitch_event_handler_register(esw); 1904 1905 esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", 1906 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", 1907 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); 1908 1909 mlx5_esw_mode_change_notify(esw, esw->mode); 1910 1911 return 0; 1912 1913 err_esw_init: 1914 mlx5_eq_notifier_unregister(esw->dev, &esw->nb); 1915 mlx5_esw_acls_ns_cleanup(esw); 1916 return err; 1917 } 1918 1919 /** 1920 * mlx5_eswitch_enable - Enable eswitch 1921 * @esw: Pointer to eswitch 1922 * @num_vfs: Enable eswitch switch for given number of VFs. 1923 * Caller must pass num_vfs > 0 when enabling eswitch for 1924 * vf vports. 1925 * mlx5_eswitch_enable() returns 0 on success or error code on failure. 1926 */ 1927 int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) 1928 { 1929 bool toggle_lag; 1930 int ret = 0; 1931 1932 if (!mlx5_esw_allowed(esw)) 1933 return 0; 1934 1935 devl_assert_locked(priv_to_devlink(esw->dev)); 1936 1937 toggle_lag = !mlx5_esw_is_fdb_created(esw); 1938 1939 if (toggle_lag) 1940 mlx5_lag_disable_change(esw->dev); 1941 1942 mlx5_eswitch_invalidate_wq(esw); 1943 mlx5_esw_reps_block(esw); 1944 1945 if (!mlx5_esw_is_fdb_created(esw)) { 1946 ret = mlx5_eswitch_enable_locked(esw, num_vfs); 1947 } else { 1948 enum mlx5_eswitch_vport_event vport_events; 1949 1950 vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ? 1951 MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE; 1952 /* If this is the ECPF the number of host VFs is managed via the 1953 * eswitch function change event handler, and any num_vfs provided 1954 * here are intended to be EC VFs. 1955 */ 1956 if (!mlx5_core_is_ecpf(esw->dev)) { 1957 ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events); 1958 if (!ret) 1959 esw->esw_funcs.num_vfs = num_vfs; 1960 } else if (mlx5_core_ec_sriov_enabled(esw->dev)) { 1961 ret = mlx5_eswitch_load_ec_vf_vports(esw, num_vfs, vport_events); 1962 if (!ret) 1963 esw->esw_funcs.num_ec_vfs = num_vfs; 1964 } 1965 } 1966 1967 mlx5_esw_reps_unblock(esw); 1968 1969 if (toggle_lag) 1970 mlx5_lag_enable_change(esw->dev); 1971 1972 return ret; 1973 } 1974 1975 /* When disabling sriov, free driver level resources. */ 1976 void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) 1977 { 1978 if (!mlx5_esw_allowed(esw)) 1979 return; 1980 1981 devl_assert_locked(priv_to_devlink(esw->dev)); 1982 /* If driver is unloaded, this function is called twice by remove_one() 1983 * and mlx5_unload(). Prevent the second call. 1984 */ 1985 if (!esw->esw_funcs.num_vfs && !esw->esw_funcs.num_ec_vfs && !clear_vf) 1986 return; 1987 1988 esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", 1989 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", 1990 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); 1991 1992 mlx5_eswitch_invalidate_wq(esw); 1993 mlx5_esw_reps_block(esw); 1994 1995 if (!mlx5_core_is_ecpf(esw->dev)) { 1996 mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); 1997 if (clear_vf) 1998 mlx5_eswitch_clear_vf_vports_info(esw); 1999 } else if (mlx5_core_ec_sriov_enabled(esw->dev)) { 2000 mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs); 2001 if (clear_vf) 2002 mlx5_eswitch_clear_ec_vf_vports_info(esw); 2003 } 2004 2005 mlx5_esw_reps_unblock(esw); 2006 2007 if (esw->mode == MLX5_ESWITCH_OFFLOADS) { 2008 struct devlink *devlink = priv_to_devlink(esw->dev); 2009 2010 devl_rate_nodes_destroy(devlink); 2011 } 2012 /* Destroy legacy fdb when disabling sriov in legacy mode. */ 2013 if (esw->mode == MLX5_ESWITCH_LEGACY) 2014 mlx5_eswitch_disable_locked(esw); 2015 2016 if (!mlx5_core_is_ecpf(esw->dev)) 2017 esw->esw_funcs.num_vfs = 0; 2018 else 2019 esw->esw_funcs.num_ec_vfs = 0; 2020 } 2021 2022 /* Free resources for corresponding eswitch mode. It is called by devlink 2023 * when changing eswitch mode or modprobe when unloading driver. 2024 */ 2025 void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw) 2026 { 2027 struct devlink *devlink = priv_to_devlink(esw->dev); 2028 2029 /* Notify eswitch users that it is exiting from current mode. 2030 * So that it can do necessary cleanup before the eswitch is disabled. 2031 */ 2032 mlx5_esw_mode_change_notify(esw, MLX5_ESWITCH_LEGACY); 2033 2034 mlx5_eq_notifier_unregister(esw->dev, &esw->nb); 2035 mlx5_eswitch_event_handler_unregister(esw); 2036 mlx5_eswitch_invalidate_wq(esw); 2037 2038 esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", 2039 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", 2040 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); 2041 2042 if (esw->fdb_table.flags & MLX5_ESW_FDB_CREATED) { 2043 esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED; 2044 if (esw->mode == MLX5_ESWITCH_OFFLOADS) 2045 esw_offloads_disable(esw); 2046 else if (esw->mode == MLX5_ESWITCH_LEGACY) 2047 esw_legacy_disable(esw); 2048 mlx5_esw_acls_ns_cleanup(esw); 2049 } 2050 2051 if (esw->mode == MLX5_ESWITCH_OFFLOADS) 2052 devl_rate_nodes_destroy(devlink); 2053 } 2054 2055 void mlx5_eswitch_disable(struct mlx5_eswitch *esw) 2056 { 2057 if (!mlx5_esw_allowed(esw)) 2058 return; 2059 2060 devl_assert_locked(priv_to_devlink(esw->dev)); 2061 mlx5_lag_disable_change(esw->dev); 2062 2063 mlx5_esw_reps_block(esw); 2064 mlx5_eswitch_disable_locked(esw); 2065 mlx5_esw_reps_unblock(esw); 2066 2067 esw->mode = MLX5_ESWITCH_LEGACY; 2068 mlx5_sd_eswitch_mode_set(esw->dev, MLX5_ESWITCH_LEGACY); 2069 mlx5_lag_enable_change(esw->dev); 2070 } 2071 2072 static int mlx5_esw_sf_max_pf_functions(struct mlx5_core_dev *dev, 2073 u16 vport_num, u16 *max_sfs, 2074 u16 *sf_base_id) 2075 { 2076 int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); 2077 void *query_ctx; 2078 void *hca_caps; 2079 int err; 2080 2081 query_ctx = kzalloc(query_out_sz, GFP_KERNEL); 2082 if (!query_ctx) 2083 return -ENOMEM; 2084 2085 err = mlx5_vport_get_other_func_general_cap(dev, vport_num, query_ctx); 2086 if (err) 2087 goto out_free; 2088 2089 hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); 2090 *max_sfs = MLX5_GET(cmd_hca_cap, hca_caps, max_num_sf); 2091 *sf_base_id = MLX5_GET(cmd_hca_cap, hca_caps, sf_base_id); 2092 2093 out_free: 2094 kfree(query_ctx); 2095 return err; 2096 } 2097 2098 int mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev *dev, u16 *max_sfs, 2099 u16 *sf_base_id) 2100 { 2101 if (!mlx5_core_is_ecpf(dev) || 2102 !mlx5_esw_host_functions_enabled(dev)) { 2103 *max_sfs = 0; 2104 return 0; 2105 } 2106 2107 return mlx5_esw_sf_max_pf_functions(dev, MLX5_VPORT_HOST_PF, max_sfs, 2108 sf_base_id); 2109 } 2110 2111 int mlx5_esw_sf_max_spf_functions(struct mlx5_core_dev *dev, int spf_idx, 2112 u16 *max_sfs, u16 *sf_base_id) 2113 { 2114 struct mlx5_eswitch *esw = dev->priv.eswitch; 2115 u16 vport_num; 2116 2117 if (!mlx5_esw_allowed(esw)) { 2118 *max_sfs = 0; 2119 return 0; 2120 } 2121 2122 if (spf_idx >= esw->esw_funcs.num_spfs) 2123 return -EINVAL; 2124 2125 vport_num = esw->esw_funcs.spfs[spf_idx].vport_num; 2126 return mlx5_esw_sf_max_pf_functions(dev, vport_num, max_sfs, 2127 sf_base_id); 2128 } 2129 2130 int mlx5_esw_get_num_spfs(struct mlx5_core_dev *dev) 2131 { 2132 struct mlx5_eswitch *esw = dev->priv.eswitch; 2133 2134 if (!mlx5_esw_allowed(esw)) 2135 return 0; 2136 2137 return esw->esw_funcs.num_spfs; 2138 } 2139 2140 int mlx5_esw_spf_get_host_number(struct mlx5_core_dev *dev, int spf_idx, 2141 u16 *host_number) 2142 { 2143 struct mlx5_eswitch *esw = dev->priv.eswitch; 2144 2145 if (!mlx5_esw_allowed(esw)) 2146 return -EPERM; 2147 2148 if (spf_idx >= esw->esw_funcs.num_spfs) 2149 return -EINVAL; 2150 2151 *host_number = esw->esw_funcs.spfs[spf_idx].host_number; 2152 return 0; 2153 } 2154 2155 u16 mlx5_esw_get_hpf_host_number(struct mlx5_core_dev *dev) 2156 { 2157 struct mlx5_eswitch *esw = dev->priv.eswitch; 2158 2159 if (!mlx5_esw_allowed(esw)) 2160 return 0; 2161 2162 return esw->esw_funcs.hpf_host_number; 2163 } 2164 2165 u16 mlx5_esw_get_hpf_pf_num(struct mlx5_core_dev *dev) 2166 { 2167 struct mlx5_eswitch *esw = dev->priv.eswitch; 2168 2169 if (mlx5_core_is_ecpf_esw_manager(dev) && 2170 MLX5_CAP_GEN(dev, query_host_net_function_v1)) 2171 return esw->esw_funcs.hpf_pf_num; 2172 2173 return PCI_FUNC(dev->pdev->devfn); 2174 } 2175 2176 u16 mlx5_esw_sf_controller_to_pfnum(struct mlx5_core_dev *dev, u32 controller) 2177 { 2178 struct mlx5_eswitch *esw = dev->priv.eswitch; 2179 struct mlx5_esw_functions *esw_funcs; 2180 int i; 2181 2182 if (!controller) 2183 return PCI_FUNC(dev->pdev->devfn); 2184 2185 esw_funcs = &esw->esw_funcs; 2186 for (i = 0; i < esw_funcs->num_spfs; i++) 2187 if (controller == esw_funcs->spfs[i].host_number + 1) 2188 return esw_funcs->spfs[i].pf_num; 2189 2190 return mlx5_esw_get_hpf_pf_num(dev); 2191 } 2192 2193 bool mlx5_esw_has_spf_sfs(struct mlx5_core_dev *dev) 2194 { 2195 struct mlx5_eswitch *esw = dev->priv.eswitch; 2196 2197 if (!mlx5_esw_allowed(esw)) 2198 return false; 2199 2200 return esw->esw_funcs.has_spf_sfs; 2201 } 2202 2203 static int mlx5_esw_hpf_info_init(struct mlx5_eswitch *esw) 2204 { 2205 struct mlx5_esw_pf_info host_pf_info; 2206 const u32 *query_host_out; 2207 2208 if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) 2209 return 0; 2210 2211 query_host_out = mlx5_esw_query_functions(esw->dev); 2212 if (IS_ERR(query_host_out)) 2213 return PTR_ERR(query_host_out); 2214 2215 /* Mark non local controller with non zero controller number. */ 2216 host_pf_info = mlx5_esw_get_host_pf_info(esw->dev, query_host_out); 2217 esw->esw_funcs.hpf_host_number = host_pf_info.host_number; 2218 esw->esw_funcs.hpf_pf_num = host_pf_info.pf_num; 2219 kvfree(query_host_out); 2220 return 0; 2221 } 2222 2223 int mlx5_esw_vport_alloc(struct mlx5_eswitch *esw, int index, u16 vport_num) 2224 { 2225 struct mlx5_vport *vport; 2226 int err; 2227 2228 vport = kzalloc_obj(*vport); 2229 if (!vport) 2230 return -ENOMEM; 2231 2232 vport->dev = esw->dev; 2233 vport->vport = vport_num; 2234 vport->index = index; 2235 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 2236 vport->vhca_id = MLX5_VHCA_ID_INVALID; 2237 INIT_WORK(&vport->vport_change_handler, esw_vport_change_handler); 2238 err = xa_insert(&esw->vports, vport_num, vport, GFP_KERNEL); 2239 if (err) 2240 goto insert_err; 2241 2242 esw->total_vports++; 2243 return 0; 2244 2245 insert_err: 2246 kfree(vport); 2247 return err; 2248 } 2249 2250 void mlx5_esw_vport_free(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 2251 { 2252 esw->total_vports--; 2253 xa_erase(&esw->vports, vport->vport); 2254 kfree(vport); 2255 } 2256 2257 static void mlx5_esw_spfs_cleanup(struct mlx5_eswitch *esw) 2258 { 2259 struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs; 2260 int i; 2261 2262 for (i = 0; i < esw_funcs->num_spfs; i++) 2263 mlx5_esw_destroy_esw_vport(esw->dev, 2264 esw_funcs->spfs[i].vport_num); 2265 2266 kfree(esw_funcs->spfs); 2267 esw_funcs->spfs = NULL; 2268 esw_funcs->num_spfs = 0; 2269 } 2270 2271 static int mlx5_esw_spfs_init(struct mlx5_eswitch *esw) 2272 { 2273 struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs; 2274 struct mlx5_core_dev *dev = esw->dev; 2275 int num_entries; 2276 const u8 *entry; 2277 const u32 *out; 2278 int err = 0; 2279 int pf_type; 2280 u16 vhca_id; 2281 int i; 2282 2283 if (!MLX5_CAP_GEN(dev, query_host_net_function_v1)) 2284 return 0; 2285 2286 out = mlx5_esw_query_functions(dev); 2287 if (IS_ERR(out)) 2288 return PTR_ERR(out); 2289 2290 num_entries = MLX5_GET(query_esw_functions_out, out, net_function_num); 2291 if (!num_entries) 2292 goto out_free; 2293 2294 esw_funcs->spfs = kcalloc(num_entries, sizeof(*esw_funcs->spfs), 2295 GFP_KERNEL); 2296 if (!esw_funcs->spfs) { 2297 err = -ENOMEM; 2298 goto out_free; 2299 } 2300 2301 entry = MLX5_ADDR_OF(query_esw_functions_out, out, net_function_params); 2302 2303 for (i = 0; i < num_entries; i++) { 2304 u16 vport_num; 2305 2306 pf_type = MLX5_GET(network_function_params, entry, pci_pf_type); 2307 if (pf_type != MLX5_PCI_PF_TYPE_SATELLITE_PF) { 2308 entry += MLX5_UN_SZ_BYTES(net_function_params); 2309 continue; 2310 } 2311 2312 if (!MLX5_GET(network_function_params, entry, 2313 esw_vport_manual)) { 2314 esw_warn(dev, "Satellite PF without esw_vport_manual is not supported\n"); 2315 entry += MLX5_UN_SZ_BYTES(net_function_params); 2316 continue; 2317 } 2318 2319 vhca_id = MLX5_GET(network_function_params, entry, vhca_id); 2320 2321 err = mlx5_esw_create_esw_vport(dev, vhca_id, &vport_num); 2322 if (err) { 2323 esw_warn(dev, "Failed to create satellite PF vport for vhca_id 0x%x, err %d\n", 2324 vhca_id, err); 2325 goto spfs_cleanup; 2326 } 2327 2328 esw_funcs->spfs[esw_funcs->num_spfs].vport_num = vport_num; 2329 esw_funcs->spfs[esw_funcs->num_spfs].vhca_id = vhca_id; 2330 esw_funcs->spfs[esw_funcs->num_spfs].host_number = 2331 MLX5_GET(network_function_params, entry, host_number); 2332 esw_funcs->spfs[esw_funcs->num_spfs].pf_num = 2333 MLX5_GET(network_function_params, entry, 2334 pci_device_function); 2335 esw_funcs->num_spfs++; 2336 2337 entry += MLX5_UN_SZ_BYTES(net_function_params); 2338 } 2339 2340 if (!esw_funcs->num_spfs) { 2341 kfree(esw_funcs->spfs); 2342 esw_funcs->spfs = NULL; 2343 } 2344 2345 kvfree(out); 2346 return 0; 2347 2348 spfs_cleanup: 2349 mlx5_esw_spfs_cleanup(esw); 2350 out_free: 2351 kvfree(out); 2352 return err; 2353 } 2354 2355 static void mlx5_esw_vports_cleanup(struct mlx5_eswitch *esw) 2356 { 2357 struct mlx5_vport *vport; 2358 unsigned long i; 2359 2360 mlx5_esw_spfs_cleanup(esw); 2361 esw->esw_funcs.has_spf_sfs = false; 2362 mlx5_esw_for_each_vport(esw, i, vport) 2363 mlx5_esw_vport_free(esw, vport); 2364 xa_destroy(&esw->vports); 2365 } 2366 2367 static int mlx5_esw_vports_init(struct mlx5_eswitch *esw) 2368 { 2369 struct mlx5_core_dev *dev = esw->dev; 2370 u16 max_sfs, base_sf_num; 2371 int idx = 0; 2372 int err; 2373 int i; 2374 2375 xa_init(&esw->vports); 2376 2377 err = mlx5_esw_hpf_info_init(esw); 2378 if (err) 2379 goto err; 2380 2381 if (mlx5_esw_host_functions_enabled(dev)) { 2382 err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_HOST_PF); 2383 if (err) 2384 goto err; 2385 if (esw->first_host_vport == MLX5_VPORT_HOST_PF) 2386 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN); 2387 idx++; 2388 for (i = 0; i < mlx5_core_max_vfs(dev); i++) { 2389 err = mlx5_esw_vport_alloc(esw, idx, idx); 2390 if (err) 2391 goto err; 2392 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_VF); 2393 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN); 2394 idx++; 2395 } 2396 } 2397 2398 base_sf_num = mlx5_sf_start_function_id(dev); 2399 for (i = 0; i < mlx5_sf_max_functions(dev); i++) { 2400 err = mlx5_esw_vport_alloc(esw, idx, base_sf_num + i); 2401 if (err) 2402 goto err; 2403 xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF); 2404 idx++; 2405 } 2406 2407 err = mlx5_esw_sf_max_hpf_functions(dev, &max_sfs, &base_sf_num); 2408 if (err) 2409 goto err; 2410 for (i = 0; i < max_sfs; i++) { 2411 err = mlx5_esw_vport_alloc(esw, idx, base_sf_num + i); 2412 if (err) 2413 goto err; 2414 xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF); 2415 idx++; 2416 } 2417 2418 err = mlx5_esw_spfs_init(esw); 2419 if (err) 2420 goto err; 2421 2422 for (i = 0; i < esw->esw_funcs.num_spfs; i++) { 2423 struct mlx5_vport *vport; 2424 u16 vport_num; 2425 2426 vport_num = esw->esw_funcs.spfs[i].vport_num; 2427 err = mlx5_esw_vport_alloc(esw, idx++, vport_num); 2428 if (err) 2429 goto err; 2430 vport = mlx5_eswitch_get_vport(esw, vport_num); 2431 vport->vhca_id = esw->esw_funcs.spfs[i].vhca_id; 2432 2433 err = mlx5_esw_sf_max_spf_functions(dev, i, 2434 &max_sfs, &base_sf_num); 2435 if (err) 2436 goto err; 2437 if (max_sfs) 2438 esw->esw_funcs.has_spf_sfs = true; 2439 for (int j = 0; j < max_sfs; j++) { 2440 err = mlx5_esw_vport_alloc(esw, idx, 2441 base_sf_num + j); 2442 if (err) 2443 goto err; 2444 xa_set_mark(&esw->vports, base_sf_num + j, 2445 MLX5_ESW_VPT_SF); 2446 idx++; 2447 } 2448 } 2449 2450 if (mlx5_core_ec_sriov_enabled(esw->dev)) { 2451 int ec_vf_base_num = mlx5_core_ec_vf_vport_base(dev); 2452 2453 for (i = 0; i < mlx5_core_max_ec_vfs(esw->dev); i++) { 2454 err = mlx5_esw_vport_alloc(esw, idx, ec_vf_base_num + i); 2455 if (err) 2456 goto err; 2457 idx++; 2458 } 2459 } 2460 2461 if (mlx5_ecpf_vport_exists(dev) || 2462 mlx5_core_is_ecpf_esw_manager(dev)) { 2463 err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_ECPF); 2464 if (err) 2465 goto err; 2466 idx++; 2467 } 2468 err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_UPLINK); 2469 if (err) 2470 goto err; 2471 2472 /* Adjacent vports or other dynamically create vports will use this */ 2473 esw->last_vport_idx = ++idx; 2474 return 0; 2475 2476 err: 2477 mlx5_esw_vports_cleanup(esw); 2478 return err; 2479 } 2480 2481 static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id, 2482 struct devlink_param_gset_ctx *ctx, 2483 struct netlink_ext_ack *extack) 2484 { 2485 struct mlx5_core_dev *dev = devlink_priv(devlink); 2486 2487 if (!MLX5_ESWITCH_MANAGER(dev)) 2488 return -EOPNOTSUPP; 2489 2490 if (ctx->val.vbool) 2491 return mlx5_lag_mpesw_enable(dev); 2492 2493 mlx5_lag_mpesw_disable(dev); 2494 return 0; 2495 } 2496 2497 static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id, 2498 struct devlink_param_gset_ctx *ctx, 2499 struct netlink_ext_ack *extack) 2500 { 2501 struct mlx5_core_dev *dev = devlink_priv(devlink); 2502 2503 ctx->val.vbool = mlx5_lag_is_mpesw(dev); 2504 return 0; 2505 } 2506 2507 static const struct devlink_param mlx5_eswitch_params[] = { 2508 DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT, 2509 "esw_multiport", DEVLINK_PARAM_TYPE_BOOL, 2510 BIT(DEVLINK_PARAM_CMODE_RUNTIME), 2511 mlx5_devlink_esw_multiport_get, 2512 mlx5_devlink_esw_multiport_set, NULL), 2513 }; 2514 2515 int mlx5_eswitch_init(struct mlx5_core_dev *dev) 2516 { 2517 struct mlx5_eswitch *esw; 2518 int err; 2519 2520 if (!MLX5_VPORT_MANAGER(dev) && !MLX5_ESWITCH_MANAGER(dev)) 2521 return 0; 2522 2523 esw = kzalloc_obj(*esw); 2524 if (!esw) 2525 return -ENOMEM; 2526 2527 err = devl_params_register(priv_to_devlink(dev), mlx5_eswitch_params, 2528 ARRAY_SIZE(mlx5_eswitch_params)); 2529 if (err) 2530 goto free_esw; 2531 2532 esw->dev = dev; 2533 dev->priv.eswitch = esw; 2534 esw->manager_vport = mlx5_eswitch_manager_vport(dev); 2535 esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev); 2536 2537 esw->debugfs_root = debugfs_create_dir("esw", mlx5_debugfs_get_dev_root(dev)); 2538 esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq"); 2539 if (!esw->work_queue) { 2540 err = -ENOMEM; 2541 goto abort; 2542 } 2543 2544 err = mlx5_esw_host_functions_enabled_query(esw); 2545 if (err) 2546 goto abort; 2547 2548 err = mlx5_esw_vports_init(esw); 2549 if (err) 2550 goto abort; 2551 2552 err = esw_offloads_init(esw); 2553 if (err) 2554 goto reps_err; 2555 2556 esw->mode = MLX5_ESWITCH_LEGACY; 2557 err = mlx5_esw_qos_init(esw); 2558 if (err) 2559 goto reps_err; 2560 2561 mutex_init(&esw->offloads.encap_tbl_lock); 2562 hash_init(esw->offloads.encap_tbl); 2563 mutex_init(&esw->offloads.decap_tbl_lock); 2564 hash_init(esw->offloads.decap_tbl); 2565 mlx5e_mod_hdr_tbl_init(&esw->offloads.mod_hdr); 2566 atomic64_set(&esw->offloads.num_flows, 0); 2567 ida_init(&esw->offloads.vport_metadata_ida); 2568 xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC); 2569 xa_init(&esw->vhca_type_map); 2570 mutex_init(&esw->state_lock); 2571 init_rwsem(&esw->mode_lock); 2572 refcount_set(&esw->qos.refcnt, 0); 2573 init_waitqueue_head(&esw->work_queue_wait); 2574 atomic_set(&esw->generation, 0); 2575 2576 esw->enabled_vports = 0; 2577 esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE; 2578 if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) && 2579 MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap)) 2580 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; 2581 else 2582 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; 2583 2584 esw_info(dev, 2585 "Total vports %d, per vport: max uc(%d) max mc(%d)\n", 2586 esw->total_vports, 2587 MLX5_MAX_UC_PER_VPORT(dev), 2588 MLX5_MAX_MC_PER_VPORT(dev)); 2589 return 0; 2590 2591 reps_err: 2592 mlx5_esw_vports_cleanup(esw); 2593 dev->priv.eswitch = NULL; 2594 abort: 2595 if (esw->work_queue) 2596 destroy_workqueue(esw->work_queue); 2597 debugfs_remove_recursive(esw->debugfs_root); 2598 devl_params_unregister(priv_to_devlink(dev), mlx5_eswitch_params, 2599 ARRAY_SIZE(mlx5_eswitch_params)); 2600 free_esw: 2601 kfree(esw); 2602 return err; 2603 } 2604 2605 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) 2606 { 2607 if (!esw) 2608 return; 2609 2610 esw_info(esw->dev, "cleanup\n"); 2611 2612 mlx5_eswitch_invalidate_wq(esw); 2613 destroy_workqueue(esw->work_queue); 2614 mlx5_esw_qos_cleanup(esw); 2615 WARN_ON(refcount_read(&esw->qos.refcnt)); 2616 mutex_destroy(&esw->state_lock); 2617 WARN_ON(!xa_empty(&esw->offloads.vhca_map)); 2618 xa_destroy(&esw->offloads.vhca_map); 2619 xa_destroy(&esw->vhca_type_map); 2620 ida_destroy(&esw->offloads.vport_metadata_ida); 2621 mlx5e_mod_hdr_tbl_destroy(&esw->offloads.mod_hdr); 2622 mutex_destroy(&esw->offloads.encap_tbl_lock); 2623 mutex_destroy(&esw->offloads.decap_tbl_lock); 2624 esw_offloads_cleanup(esw); 2625 esw->dev->priv.eswitch = NULL; 2626 mlx5_esw_vports_cleanup(esw); 2627 debugfs_remove_recursive(esw->debugfs_root); 2628 devl_params_unregister(priv_to_devlink(esw->dev), mlx5_eswitch_params, 2629 ARRAY_SIZE(mlx5_eswitch_params)); 2630 kfree(esw); 2631 } 2632 2633 /* Vport Administration */ 2634 static int 2635 mlx5_esw_set_vport_mac_locked(struct mlx5_eswitch *esw, 2636 struct mlx5_vport *evport, const u8 *mac) 2637 { 2638 u16 vport_num = evport->vport; 2639 u64 node_guid; 2640 int err = 0; 2641 2642 if (is_multicast_ether_addr(mac)) 2643 return -EINVAL; 2644 2645 if (evport->info.spoofchk && !is_valid_ether_addr(mac)) 2646 mlx5_core_warn(esw->dev, 2647 "Set invalid MAC while spoofchk is on, vport(%d)\n", 2648 vport_num); 2649 2650 err = mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, mac); 2651 if (err) { 2652 mlx5_core_warn(esw->dev, 2653 "Failed to mlx5_modify_nic_vport_mac vport(%d) err=(%d)\n", 2654 vport_num, err); 2655 return err; 2656 } 2657 2658 node_guid_gen_from_mac(&node_guid, mac); 2659 err = mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, node_guid); 2660 if (err) 2661 mlx5_core_warn(esw->dev, 2662 "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n", 2663 vport_num, err); 2664 2665 ether_addr_copy(evport->info.mac, mac); 2666 evport->info.node_guid = node_guid; 2667 if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) 2668 err = esw_acl_ingress_lgcy_setup(esw, evport); 2669 2670 return err; 2671 } 2672 2673 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, 2674 u16 vport, const u8 *mac) 2675 { 2676 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2677 int err = 0; 2678 2679 if (IS_ERR(evport)) 2680 return PTR_ERR(evport); 2681 2682 mutex_lock(&esw->state_lock); 2683 err = mlx5_esw_set_vport_mac_locked(esw, evport, mac); 2684 mutex_unlock(&esw->state_lock); 2685 return err; 2686 } 2687 2688 static bool mlx5_esw_check_port_type(struct mlx5_eswitch *esw, u16 vport_num, xa_mark_t mark) 2689 { 2690 return xa_get_mark(&esw->vports, vport_num, mark); 2691 } 2692 2693 bool mlx5_eswitch_is_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) 2694 { 2695 return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_VF); 2696 } 2697 2698 int mlx5_esw_spf_vport_to_idx(struct mlx5_eswitch *esw, u16 vport_num) 2699 { 2700 struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs; 2701 int i; 2702 2703 for (i = 0; i < esw_funcs->num_spfs; i++) { 2704 if (esw_funcs->spfs[i].vport_num == vport_num) 2705 return i; 2706 } 2707 2708 return -ENOENT; 2709 } 2710 2711 bool mlx5_esw_is_spf_vport(struct mlx5_eswitch *esw, u16 vport_num) 2712 { 2713 return mlx5_esw_spf_vport_to_idx(esw, vport_num) >= 0; 2714 } 2715 2716 bool mlx5_eswitch_is_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) 2717 { 2718 return vport_num == MLX5_VPORT_HOST_PF || 2719 mlx5_eswitch_is_vf_vport(esw, vport_num) || 2720 mlx5_esw_is_spf_vport(esw, vport_num); 2721 } 2722 2723 bool mlx5_esw_is_sf_vport(struct mlx5_eswitch *esw, u16 vport_num) 2724 { 2725 return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_SF); 2726 } 2727 2728 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, 2729 u16 vport, int link_state) 2730 { 2731 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2732 int opmod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT; 2733 int other_vport = 1; 2734 int err = 0; 2735 2736 if (!mlx5_esw_allowed(esw)) 2737 return -EPERM; 2738 if (IS_ERR(evport)) 2739 return PTR_ERR(evport); 2740 2741 if (vport == MLX5_VPORT_UPLINK) { 2742 opmod = MLX5_VPORT_STATE_OP_MOD_UPLINK; 2743 other_vport = 0; 2744 vport = 0; 2745 } 2746 mutex_lock(&esw->state_lock); 2747 if (esw->mode != MLX5_ESWITCH_LEGACY) { 2748 err = -EOPNOTSUPP; 2749 goto unlock; 2750 } 2751 2752 err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, other_vport, link_state); 2753 if (err) { 2754 mlx5_core_warn(esw->dev, "Failed to set vport %d link state, opmod = %d, err = %d", 2755 vport, opmod, err); 2756 goto unlock; 2757 } 2758 2759 evport->info.link_state = link_state; 2760 2761 unlock: 2762 mutex_unlock(&esw->state_lock); 2763 return err; 2764 } 2765 2766 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw, 2767 u16 vport, struct ifla_vf_info *ivi) 2768 { 2769 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2770 u32 max_rate, min_rate; 2771 2772 if (IS_ERR(evport)) 2773 return PTR_ERR(evport); 2774 2775 memset(ivi, 0, sizeof(*ivi)); 2776 ivi->vf = vport - 1; 2777 2778 mutex_lock(&esw->state_lock); 2779 2780 mlx5_query_nic_vport_mac_address(esw->dev, vport, true, 2781 evport->info.mac); 2782 ether_addr_copy(ivi->mac, evport->info.mac); 2783 ivi->linkstate = evport->info.link_state; 2784 ivi->vlan = evport->info.vlan; 2785 ivi->qos = evport->info.qos; 2786 ivi->spoofchk = evport->info.spoofchk; 2787 ivi->trusted = evport->info.trusted; 2788 2789 if (mlx5_esw_qos_get_vport_rate(evport, &max_rate, &min_rate)) { 2790 ivi->max_tx_rate = max_rate; 2791 ivi->min_tx_rate = min_rate; 2792 } 2793 mutex_unlock(&esw->state_lock); 2794 2795 return 0; 2796 } 2797 2798 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, 2799 u16 vport, u16 vlan, u8 qos, u8 set_flags) 2800 { 2801 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2802 bool vst_mode_steering = esw_vst_mode_is_steering(esw); 2803 int err = 0; 2804 2805 if (IS_ERR(evport)) 2806 return PTR_ERR(evport); 2807 if (vlan > 4095 || qos > 7) 2808 return -EINVAL; 2809 2810 if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering) { 2811 err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags); 2812 if (err) 2813 return err; 2814 } 2815 2816 evport->info.vlan = vlan; 2817 evport->info.qos = qos; 2818 if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) { 2819 err = esw_acl_ingress_lgcy_setup(esw, evport); 2820 if (err) 2821 return err; 2822 err = esw_acl_egress_lgcy_setup(esw, evport); 2823 } 2824 2825 return err; 2826 } 2827 2828 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, 2829 u16 vport_num, 2830 struct ifla_vf_stats *vf_stats) 2831 { 2832 struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); 2833 int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out); 2834 u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {}; 2835 struct mlx5_vport_drop_stats stats = {}; 2836 int err = 0; 2837 u32 *out; 2838 2839 if (IS_ERR(vport)) 2840 return PTR_ERR(vport); 2841 2842 out = kvzalloc(outlen, GFP_KERNEL); 2843 if (!out) 2844 return -ENOMEM; 2845 2846 MLX5_SET(query_vport_counter_in, in, opcode, 2847 MLX5_CMD_OP_QUERY_VPORT_COUNTER); 2848 MLX5_SET(query_vport_counter_in, in, op_mod, 0); 2849 MLX5_SET(query_vport_counter_in, in, vport_number, vport->vport); 2850 MLX5_SET(query_vport_counter_in, in, other_vport, 1); 2851 2852 err = mlx5_cmd_exec_inout(esw->dev, query_vport_counter, in, out); 2853 if (err) 2854 goto free_out; 2855 2856 #define MLX5_GET_CTR(p, x) \ 2857 MLX5_GET64(query_vport_counter_out, p, x) 2858 2859 memset(vf_stats, 0, sizeof(*vf_stats)); 2860 vf_stats->rx_packets = 2861 MLX5_GET_CTR(out, received_eth_unicast.packets) + 2862 MLX5_GET_CTR(out, received_ib_unicast.packets) + 2863 MLX5_GET_CTR(out, received_eth_multicast.packets) + 2864 MLX5_GET_CTR(out, received_ib_multicast.packets) + 2865 MLX5_GET_CTR(out, received_eth_broadcast.packets); 2866 2867 vf_stats->rx_bytes = 2868 MLX5_GET_CTR(out, received_eth_unicast.octets) + 2869 MLX5_GET_CTR(out, received_ib_unicast.octets) + 2870 MLX5_GET_CTR(out, received_eth_multicast.octets) + 2871 MLX5_GET_CTR(out, received_ib_multicast.octets) + 2872 MLX5_GET_CTR(out, received_eth_broadcast.octets); 2873 2874 vf_stats->tx_packets = 2875 MLX5_GET_CTR(out, transmitted_eth_unicast.packets) + 2876 MLX5_GET_CTR(out, transmitted_ib_unicast.packets) + 2877 MLX5_GET_CTR(out, transmitted_eth_multicast.packets) + 2878 MLX5_GET_CTR(out, transmitted_ib_multicast.packets) + 2879 MLX5_GET_CTR(out, transmitted_eth_broadcast.packets); 2880 2881 vf_stats->tx_bytes = 2882 MLX5_GET_CTR(out, transmitted_eth_unicast.octets) + 2883 MLX5_GET_CTR(out, transmitted_ib_unicast.octets) + 2884 MLX5_GET_CTR(out, transmitted_eth_multicast.octets) + 2885 MLX5_GET_CTR(out, transmitted_ib_multicast.octets) + 2886 MLX5_GET_CTR(out, transmitted_eth_broadcast.octets); 2887 2888 vf_stats->multicast = 2889 MLX5_GET_CTR(out, received_eth_multicast.packets) + 2890 MLX5_GET_CTR(out, received_ib_multicast.packets); 2891 2892 vf_stats->broadcast = 2893 MLX5_GET_CTR(out, received_eth_broadcast.packets); 2894 2895 err = mlx5_esw_query_vport_drop_stats(esw->dev, vport, &stats); 2896 if (err) 2897 goto free_out; 2898 vf_stats->rx_dropped = stats.rx_dropped; 2899 vf_stats->tx_dropped = stats.tx_dropped; 2900 2901 free_out: 2902 kvfree(out); 2903 return err; 2904 } 2905 2906 u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev) 2907 { 2908 struct mlx5_eswitch *esw = dev->priv.eswitch; 2909 2910 return mlx5_esw_allowed(esw) ? esw->mode : MLX5_ESWITCH_LEGACY; 2911 } 2912 EXPORT_SYMBOL_GPL(mlx5_eswitch_mode); 2913 2914 enum devlink_eswitch_encap_mode 2915 mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev) 2916 { 2917 struct mlx5_eswitch *esw; 2918 2919 esw = dev->priv.eswitch; 2920 return (mlx5_eswitch_mode(dev) == MLX5_ESWITCH_OFFLOADS) ? esw->offloads.encap : 2921 DEVLINK_ESWITCH_ENCAP_MODE_NONE; 2922 } 2923 EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode); 2924 2925 bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0, 2926 struct mlx5_core_dev *dev1) 2927 { 2928 return (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS && 2929 dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS); 2930 } 2931 2932 int mlx5_esw_event_notifier_register(struct mlx5_core_dev *dev, 2933 struct notifier_block *nb) 2934 { 2935 return blocking_notifier_chain_register(&dev->priv.esw_n_head, nb); 2936 } 2937 2938 void mlx5_esw_event_notifier_unregister(struct mlx5_core_dev *dev, 2939 struct notifier_block *nb) 2940 { 2941 blocking_notifier_chain_unregister(&dev->priv.esw_n_head, nb); 2942 } 2943 2944 /** 2945 * mlx5_esw_hold() - Try to take a read lock on esw mode lock. 2946 * @mdev: mlx5 core device. 2947 * 2948 * Should be called by esw resources callers. 2949 * 2950 * Return: true on success or false. 2951 */ 2952 bool mlx5_esw_hold(struct mlx5_core_dev *mdev) 2953 { 2954 struct mlx5_eswitch *esw = mdev->priv.eswitch; 2955 2956 /* e.g. VF doesn't have eswitch so nothing to do */ 2957 if (!mlx5_esw_allowed(esw)) 2958 return true; 2959 2960 if (down_read_trylock(&esw->mode_lock) != 0) { 2961 if (esw->eswitch_operation_in_progress) { 2962 up_read(&esw->mode_lock); 2963 return false; 2964 } 2965 return true; 2966 } 2967 2968 return false; 2969 } 2970 2971 /** 2972 * mlx5_esw_release() - Release a read lock on esw mode lock. 2973 * @mdev: mlx5 core device. 2974 */ 2975 void mlx5_esw_release(struct mlx5_core_dev *mdev) 2976 { 2977 struct mlx5_eswitch *esw = mdev->priv.eswitch; 2978 2979 if (mlx5_esw_allowed(esw)) 2980 up_read(&esw->mode_lock); 2981 } 2982 2983 /** 2984 * mlx5_esw_get() - Increase esw user count. 2985 * @mdev: mlx5 core device. 2986 */ 2987 void mlx5_esw_get(struct mlx5_core_dev *mdev) 2988 { 2989 struct mlx5_eswitch *esw = mdev->priv.eswitch; 2990 2991 if (mlx5_esw_allowed(esw)) 2992 atomic64_inc(&esw->user_count); 2993 } 2994 2995 /** 2996 * mlx5_esw_put() - Decrease esw user count. 2997 * @mdev: mlx5 core device. 2998 */ 2999 void mlx5_esw_put(struct mlx5_core_dev *mdev) 3000 { 3001 struct mlx5_eswitch *esw = mdev->priv.eswitch; 3002 3003 if (mlx5_esw_allowed(esw)) 3004 atomic64_dec_if_positive(&esw->user_count); 3005 } 3006 3007 /** 3008 * mlx5_esw_try_lock() - Take a write lock on esw mode lock. 3009 * @esw: eswitch device. 3010 * 3011 * Should be called by esw mode change routine. 3012 * 3013 * Return: 3014 * * 0 - esw mode if successfully locked and refcount is 0. 3015 * * -EBUSY - refcount is not 0. 3016 * * -EINVAL - In the middle of switching mode or lock is already held. 3017 */ 3018 int mlx5_esw_try_lock(struct mlx5_eswitch *esw) 3019 { 3020 if (down_write_trylock(&esw->mode_lock) == 0) 3021 return -EINVAL; 3022 3023 if (esw->eswitch_operation_in_progress || 3024 atomic64_read(&esw->user_count) > 0) { 3025 up_write(&esw->mode_lock); 3026 return -EBUSY; 3027 } 3028 3029 return esw->mode; 3030 } 3031 3032 int mlx5_esw_lock(struct mlx5_eswitch *esw) 3033 { 3034 down_write(&esw->mode_lock); 3035 3036 if (esw->eswitch_operation_in_progress) { 3037 up_write(&esw->mode_lock); 3038 return -EBUSY; 3039 } 3040 3041 return 0; 3042 } 3043 3044 /** 3045 * mlx5_esw_unlock() - Release write lock on esw mode lock 3046 * @esw: eswitch device. 3047 */ 3048 void mlx5_esw_unlock(struct mlx5_eswitch *esw) 3049 { 3050 up_write(&esw->mode_lock); 3051 } 3052 3053 /** 3054 * mlx5_eswitch_get_total_vports - Get total vports of the eswitch 3055 * 3056 * @dev: Pointer to core device 3057 * 3058 * mlx5_eswitch_get_total_vports returns total number of eswitch vports. 3059 */ 3060 u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev) 3061 { 3062 struct mlx5_eswitch *esw; 3063 3064 esw = dev->priv.eswitch; 3065 return mlx5_esw_allowed(esw) ? esw->total_vports : 0; 3066 } 3067 EXPORT_SYMBOL_GPL(mlx5_eswitch_get_total_vports); 3068 3069 /** 3070 * mlx5_eswitch_get_core_dev - Get the mdev device 3071 * @esw : eswitch device. 3072 * 3073 * Return the mellanox core device which manages the eswitch. 3074 */ 3075 struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw) 3076 { 3077 return mlx5_esw_allowed(esw) ? esw->dev : NULL; 3078 } 3079 EXPORT_SYMBOL(mlx5_eswitch_get_core_dev); 3080 3081 bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev) 3082 { 3083 struct mlx5_eswitch *esw = dev->priv.eswitch; 3084 3085 if (!mlx5_esw_allowed(esw)) 3086 return true; 3087 3088 mutex_lock(&esw->state_lock); 3089 if (esw->enabled_ipsec_vf_count) { 3090 mutex_unlock(&esw->state_lock); 3091 return false; 3092 } 3093 3094 dev->num_ipsec_offloads++; 3095 mutex_unlock(&esw->state_lock); 3096 return true; 3097 } 3098 3099 void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev) 3100 { 3101 struct mlx5_eswitch *esw = dev->priv.eswitch; 3102 3103 if (!mlx5_esw_allowed(esw)) 3104 /* Failure means no eswitch => core dev is not a PF */ 3105 return; 3106 3107 mutex_lock(&esw->state_lock); 3108 dev->num_ipsec_offloads--; 3109 mutex_unlock(&esw->state_lock); 3110 } 3111 3112 bool mlx5_esw_host_functions_enabled(const struct mlx5_core_dev *dev) 3113 { 3114 if (!dev->priv.eswitch) 3115 return true; 3116 3117 return !dev->priv.eswitch->esw_funcs.host_funcs_disabled; 3118 } 3119