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 mlx5_eswitch_check(const struct mlx5_core_dev * dev)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 __mlx5_devlink_eswitch_get(struct devlink * devlink,bool check)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 mlx5_devlink_eswitch_get(struct devlink * devlink)96 mlx5_devlink_eswitch_get(struct devlink *devlink) 97 { 98 return __mlx5_devlink_eswitch_get(devlink, true); 99 } 100 mlx5_devlink_eswitch_nocheck_get(struct devlink * devlink)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 mlx5_eswitch_get_vport(struct mlx5_eswitch * esw,u16 vport_num)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 arm_vport_context_events_cmd(struct mlx5_core_dev * dev,u16 vport,u32 events_mask)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 */ mlx5_eswitch_modify_esw_vport_context(struct mlx5_core_dev * dev,u16 vport,bool other_vport,void * in)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 modify_esw_vport_cvlan(struct mlx5_core_dev * dev,u16 vport,u16 vlan,u8 qos,u8 set_flags)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 * __esw_fdb_set_vport_rule(struct mlx5_eswitch * esw,u16 vport,bool rx_rule,u8 mac_c[ETH_ALEN],u8 mac_v[ETH_ALEN])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(sizeof(*spec), GFP_KERNEL); 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(%ld)\n", 261 dmac_v, dmac_c, vport, PTR_ERR(flow_rule)); 262 flow_rule = NULL; 263 } 264 265 kvfree(spec); 266 return flow_rule; 267 } 268 269 static struct mlx5_flow_handle * esw_fdb_set_vport_rule(struct mlx5_eswitch * esw,u8 mac[ETH_ALEN],u16 vport)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 * esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch * esw,u16 vport)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 * esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch * esw,u16 vport)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 esw_add_uc_addr(struct mlx5_eswitch * esw,struct vport_addr * vaddr)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 esw_del_uc_addr(struct mlx5_eswitch * esw,struct vport_addr * vaddr)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 update_allmulti_vports(struct mlx5_eswitch * esw,struct vport_addr * vaddr,struct esw_mc_addr * esw_mc)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 esw_add_mc_addr(struct mlx5_eswitch * esw,struct vport_addr * vaddr)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 esw_del_mc_addr(struct mlx5_eswitch * esw,struct vport_addr * vaddr)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 */ esw_apply_vport_addr_list(struct mlx5_eswitch * esw,struct mlx5_vport * vport,int list_type)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 */ esw_update_vport_addr_list(struct mlx5_eswitch * esw,struct mlx5_vport * vport,int list_type)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]; 537 struct l2addr_node *node; 538 struct vport_addr *addr; 539 struct hlist_head *hash; 540 struct hlist_node *tmp; 541 int size; 542 int err; 543 int hi; 544 int i; 545 546 size = is_uc ? MLX5_MAX_UC_PER_VPORT(esw->dev) : 547 MLX5_MAX_MC_PER_VPORT(esw->dev); 548 549 mac_list = kcalloc(size, ETH_ALEN, GFP_KERNEL); 550 if (!mac_list) 551 return; 552 553 hash = is_uc ? vport->uc_list : vport->mc_list; 554 555 for_each_l2hash_node(node, tmp, hash, hi) { 556 addr = container_of(node, struct vport_addr, node); 557 addr->action = MLX5_ACTION_DEL; 558 } 559 560 if (!vport->enabled) 561 goto out; 562 563 err = mlx5_query_nic_vport_mac_list(esw->dev, vport->vport, list_type, 564 mac_list, &size); 565 if (err) 566 goto out; 567 esw_debug(esw->dev, "vport[%d] context update %s list size (%d)\n", 568 vport->vport, is_uc ? "UC" : "MC", size); 569 570 for (i = 0; i < size; i++) { 571 if (is_uc && !is_valid_ether_addr(mac_list[i])) 572 continue; 573 574 if (!is_uc && !is_multicast_ether_addr(mac_list[i])) 575 continue; 576 577 addr = l2addr_hash_find(hash, mac_list[i], struct vport_addr); 578 if (addr) { 579 addr->action = MLX5_ACTION_NONE; 580 /* If this mac was previously added because of allmulti 581 * promiscuous rx mode, its now converted to be original 582 * vport mac. 583 */ 584 if (addr->mc_promisc) { 585 struct esw_mc_addr *esw_mc = 586 l2addr_hash_find(esw->mc_table, 587 mac_list[i], 588 struct esw_mc_addr); 589 if (!esw_mc) { 590 esw_warn(esw->dev, 591 "Failed to MAC(%pM) in mcast DB\n", 592 mac_list[i]); 593 continue; 594 } 595 esw_mc->refcnt++; 596 addr->mc_promisc = false; 597 } 598 continue; 599 } 600 601 addr = l2addr_hash_add(hash, mac_list[i], struct vport_addr, 602 GFP_KERNEL); 603 if (!addr) { 604 esw_warn(esw->dev, 605 "Failed to add MAC(%pM) to vport[%d] DB\n", 606 mac_list[i], vport->vport); 607 continue; 608 } 609 addr->vport = vport->vport; 610 addr->action = MLX5_ACTION_ADD; 611 } 612 out: 613 kfree(mac_list); 614 } 615 616 /* Sync vport UC/MC list from vport context 617 * Must be called after esw_update_vport_addr_list 618 */ esw_update_vport_mc_promisc(struct mlx5_eswitch * esw,struct mlx5_vport * vport)619 static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, 620 struct mlx5_vport *vport) 621 { 622 struct l2addr_node *node; 623 struct vport_addr *addr; 624 struct hlist_head *hash; 625 struct hlist_node *tmp; 626 int hi; 627 628 hash = vport->mc_list; 629 630 for_each_l2hash_node(node, tmp, esw->mc_table, hi) { 631 u8 *mac = node->addr; 632 633 addr = l2addr_hash_find(hash, mac, struct vport_addr); 634 if (addr) { 635 if (addr->action == MLX5_ACTION_DEL) 636 addr->action = MLX5_ACTION_NONE; 637 continue; 638 } 639 addr = l2addr_hash_add(hash, mac, struct vport_addr, 640 GFP_KERNEL); 641 if (!addr) { 642 esw_warn(esw->dev, 643 "Failed to add allmulti MAC(%pM) to vport[%d] DB\n", 644 mac, vport->vport); 645 continue; 646 } 647 addr->vport = vport->vport; 648 addr->action = MLX5_ACTION_ADD; 649 addr->mc_promisc = true; 650 } 651 } 652 653 /* Apply vport rx mode to HW FDB table */ esw_apply_vport_rx_mode(struct mlx5_eswitch * esw,struct mlx5_vport * vport,bool promisc,bool mc_promisc)654 static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, 655 struct mlx5_vport *vport, 656 bool promisc, bool mc_promisc) 657 { 658 struct esw_mc_addr *allmulti_addr = &esw->mc_promisc; 659 660 if (IS_ERR_OR_NULL(vport->allmulti_rule) != mc_promisc) 661 goto promisc; 662 663 if (mc_promisc) { 664 vport->allmulti_rule = 665 esw_fdb_set_vport_allmulti_rule(esw, vport->vport); 666 if (!allmulti_addr->uplink_rule) 667 allmulti_addr->uplink_rule = 668 esw_fdb_set_vport_allmulti_rule(esw, 669 MLX5_VPORT_UPLINK); 670 allmulti_addr->refcnt++; 671 } else if (vport->allmulti_rule) { 672 mlx5_del_flow_rules(vport->allmulti_rule); 673 vport->allmulti_rule = NULL; 674 675 if (--allmulti_addr->refcnt > 0) 676 goto promisc; 677 678 if (allmulti_addr->uplink_rule) 679 mlx5_del_flow_rules(allmulti_addr->uplink_rule); 680 allmulti_addr->uplink_rule = NULL; 681 } 682 683 promisc: 684 if (IS_ERR_OR_NULL(vport->promisc_rule) != promisc) 685 return; 686 687 if (promisc) { 688 vport->promisc_rule = 689 esw_fdb_set_vport_promisc_rule(esw, vport->vport); 690 } else if (vport->promisc_rule) { 691 mlx5_del_flow_rules(vport->promisc_rule); 692 vport->promisc_rule = NULL; 693 } 694 } 695 696 /* Sync vport rx mode from vport context */ esw_update_vport_rx_mode(struct mlx5_eswitch * esw,struct mlx5_vport * vport)697 static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw, 698 struct mlx5_vport *vport) 699 { 700 int promisc_all = 0; 701 int promisc_uc = 0; 702 int promisc_mc = 0; 703 int err; 704 705 err = mlx5_query_nic_vport_promisc(esw->dev, 706 vport->vport, 707 &promisc_uc, 708 &promisc_mc, 709 &promisc_all); 710 if (err) 711 return; 712 esw_debug(esw->dev, "vport[%d] context update rx mode promisc_all=%d, all_multi=%d\n", 713 vport->vport, promisc_all, promisc_mc); 714 715 if (!vport->info.trusted || !vport->enabled) { 716 promisc_uc = 0; 717 promisc_mc = 0; 718 promisc_all = 0; 719 } 720 721 esw_apply_vport_rx_mode(esw, vport, promisc_all, 722 (promisc_all || promisc_mc)); 723 } 724 esw_vport_change_handle_locked(struct mlx5_vport * vport)725 void esw_vport_change_handle_locked(struct mlx5_vport *vport) 726 { 727 struct mlx5_core_dev *dev = vport->dev; 728 struct mlx5_eswitch *esw = dev->priv.eswitch; 729 u8 mac[ETH_ALEN]; 730 731 if (!MLX5_CAP_GEN(dev, log_max_l2_table)) 732 return; 733 734 mlx5_query_nic_vport_mac_address(dev, vport->vport, true, mac); 735 esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n", 736 vport->vport, mac); 737 738 if (vport->enabled_events & MLX5_VPORT_UC_ADDR_CHANGE) { 739 esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC); 740 esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC); 741 } 742 743 if (vport->enabled_events & MLX5_VPORT_MC_ADDR_CHANGE) 744 esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC); 745 746 if (vport->enabled_events & MLX5_VPORT_PROMISC_CHANGE) { 747 esw_update_vport_rx_mode(esw, vport); 748 if (!IS_ERR_OR_NULL(vport->allmulti_rule)) 749 esw_update_vport_mc_promisc(esw, vport); 750 } 751 752 if (vport->enabled_events & (MLX5_VPORT_PROMISC_CHANGE | MLX5_VPORT_MC_ADDR_CHANGE)) 753 esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC); 754 755 esw_debug(esw->dev, "vport[%d] Context Changed: Done\n", vport->vport); 756 if (vport->enabled) 757 arm_vport_context_events_cmd(dev, vport->vport, 758 vport->enabled_events); 759 } 760 esw_vport_change_handler(struct work_struct * work)761 static void esw_vport_change_handler(struct work_struct *work) 762 { 763 struct mlx5_vport *vport = 764 container_of(work, struct mlx5_vport, vport_change_handler); 765 struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 766 767 mutex_lock(&esw->state_lock); 768 esw_vport_change_handle_locked(vport); 769 mutex_unlock(&esw->state_lock); 770 } 771 node_guid_gen_from_mac(u64 * node_guid,const u8 * mac)772 static void node_guid_gen_from_mac(u64 *node_guid, const u8 *mac) 773 { 774 ((u8 *)node_guid)[7] = mac[0]; 775 ((u8 *)node_guid)[6] = mac[1]; 776 ((u8 *)node_guid)[5] = mac[2]; 777 ((u8 *)node_guid)[4] = 0xff; 778 ((u8 *)node_guid)[3] = 0xfe; 779 ((u8 *)node_guid)[2] = mac[3]; 780 ((u8 *)node_guid)[1] = mac[4]; 781 ((u8 *)node_guid)[0] = mac[5]; 782 } 783 esw_vport_setup_acl(struct mlx5_eswitch * esw,struct mlx5_vport * vport)784 static int esw_vport_setup_acl(struct mlx5_eswitch *esw, 785 struct mlx5_vport *vport) 786 { 787 if (esw->mode == MLX5_ESWITCH_LEGACY) 788 return esw_legacy_vport_acl_setup(esw, vport); 789 else 790 return esw_vport_create_offloads_acl_tables(esw, vport); 791 } 792 esw_vport_cleanup_acl(struct mlx5_eswitch * esw,struct mlx5_vport * vport)793 static void esw_vport_cleanup_acl(struct mlx5_eswitch *esw, 794 struct mlx5_vport *vport) 795 { 796 if (esw->mode == MLX5_ESWITCH_LEGACY) 797 esw_legacy_vport_acl_cleanup(esw, vport); 798 else 799 esw_vport_destroy_offloads_acl_tables(esw, vport); 800 } 801 mlx5_esw_vport_caps_get(struct mlx5_eswitch * esw,struct mlx5_vport * vport)802 static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 803 { 804 int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); 805 void *query_ctx; 806 void *hca_caps; 807 int err; 808 809 if (!MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) 810 return 0; 811 812 query_ctx = kzalloc(query_out_sz, GFP_KERNEL); 813 if (!query_ctx) 814 return -ENOMEM; 815 816 err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx, 817 MLX5_CAP_GENERAL); 818 if (err) 819 goto out_free; 820 821 hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); 822 vport->info.roce_enabled = MLX5_GET(cmd_hca_cap, hca_caps, roce); 823 824 if (!MLX5_CAP_GEN_MAX(esw->dev, hca_cap_2)) 825 goto out_free; 826 827 memset(query_ctx, 0, query_out_sz); 828 err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx, 829 MLX5_CAP_GENERAL_2); 830 if (err) 831 goto out_free; 832 833 hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); 834 vport->info.mig_enabled = MLX5_GET(cmd_hca_cap_2, hca_caps, migratable); 835 836 err = mlx5_esw_ipsec_vf_offload_get(esw->dev, vport); 837 out_free: 838 kfree(query_ctx); 839 return err; 840 } 841 esw_vport_setup(struct mlx5_eswitch * esw,struct mlx5_vport * vport)842 static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 843 { 844 bool vst_mode_steering = esw_vst_mode_is_steering(esw); 845 u16 vport_num = vport->vport; 846 int flags; 847 int err; 848 849 err = esw_vport_setup_acl(esw, vport); 850 if (err) 851 return err; 852 853 if (mlx5_esw_is_manager_vport(esw, vport_num)) 854 return 0; 855 856 err = mlx5_esw_vport_caps_get(esw, vport); 857 if (err) 858 goto err_caps; 859 860 mlx5_modify_vport_admin_state(esw->dev, 861 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, 862 vport_num, 1, 863 vport->info.link_state); 864 865 /* Host PF has its own mac/guid. */ 866 if (vport_num) { 867 mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, 868 vport->info.mac); 869 mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, 870 vport->info.node_guid); 871 } 872 873 flags = (vport->info.vlan || vport->info.qos) ? 874 SET_VLAN_STRIP | SET_VLAN_INSERT : 0; 875 if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering) 876 modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan, 877 vport->info.qos, flags); 878 879 return 0; 880 881 err_caps: 882 esw_vport_cleanup_acl(esw, vport); 883 return err; 884 } 885 886 /* Don't cleanup vport->info, it's needed to restore vport configuration */ esw_vport_cleanup(struct mlx5_eswitch * esw,struct mlx5_vport * vport)887 static void esw_vport_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 888 { 889 u16 vport_num = vport->vport; 890 891 if (!mlx5_esw_is_manager_vport(esw, vport_num)) 892 mlx5_modify_vport_admin_state(esw->dev, 893 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, 894 vport_num, 1, 895 MLX5_VPORT_ADMIN_STATE_DOWN); 896 897 mlx5_esw_qos_vport_disable(esw, vport); 898 esw_vport_cleanup_acl(esw, vport); 899 } 900 mlx5_esw_vport_enable(struct mlx5_eswitch * esw,struct mlx5_vport * vport,enum mlx5_eswitch_vport_event enabled_events)901 int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport, 902 enum mlx5_eswitch_vport_event enabled_events) 903 { 904 u16 vport_num = vport->vport; 905 int ret; 906 907 mutex_lock(&esw->state_lock); 908 WARN_ON(vport->enabled); 909 910 esw_debug(esw->dev, "Enabling VPORT(%d)\n", vport_num); 911 912 ret = esw_vport_setup(esw, vport); 913 if (ret) 914 goto done; 915 916 /* Sync with current vport context */ 917 vport->enabled_events = enabled_events; 918 vport->enabled = true; 919 if (vport->vport != MLX5_VPORT_PF && 920 (vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled)) 921 esw->enabled_ipsec_vf_count++; 922 923 /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well 924 * in smartNIC as it's a vport group manager. 925 */ 926 if (mlx5_esw_is_manager_vport(esw, vport_num) || 927 (!vport_num && mlx5_core_is_ecpf(esw->dev))) 928 vport->info.trusted = true; 929 930 if (!mlx5_esw_is_manager_vport(esw, vport_num) && 931 MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) { 932 ret = mlx5_esw_vport_vhca_id_set(esw, vport_num); 933 if (ret) 934 goto err_vhca_mapping; 935 } 936 937 /* External controller host PF has factory programmed MAC. 938 * Read it from the device. 939 */ 940 if (mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF) 941 mlx5_query_nic_vport_mac_address(esw->dev, vport_num, true, vport->info.mac); 942 943 esw_vport_change_handle_locked(vport); 944 945 esw->enabled_vports++; 946 esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num); 947 done: 948 mutex_unlock(&esw->state_lock); 949 return ret; 950 951 err_vhca_mapping: 952 esw_vport_cleanup(esw, vport); 953 mutex_unlock(&esw->state_lock); 954 return ret; 955 } 956 mlx5_esw_vport_disable(struct mlx5_eswitch * esw,struct mlx5_vport * vport)957 void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 958 { 959 u16 vport_num = vport->vport; 960 961 mutex_lock(&esw->state_lock); 962 963 if (!vport->enabled) 964 goto done; 965 966 esw_debug(esw->dev, "Disabling vport(%d)\n", vport_num); 967 /* Mark this vport as disabled to discard new events */ 968 vport->enabled = false; 969 970 /* Disable events from this vport */ 971 if (MLX5_CAP_GEN(esw->dev, log_max_l2_table)) 972 arm_vport_context_events_cmd(esw->dev, vport_num, 0); 973 974 if (!mlx5_esw_is_manager_vport(esw, vport_num) && 975 MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) 976 mlx5_esw_vport_vhca_id_clear(esw, vport_num); 977 978 if (vport->vport != MLX5_VPORT_PF && 979 (vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled)) 980 esw->enabled_ipsec_vf_count--; 981 982 /* We don't assume VFs will cleanup after themselves. 983 * Calling vport change handler while vport is disabled will cleanup 984 * the vport resources. 985 */ 986 esw_vport_change_handle_locked(vport); 987 vport->enabled_events = 0; 988 esw_apply_vport_rx_mode(esw, vport, false, false); 989 esw_vport_cleanup(esw, vport); 990 esw->enabled_vports--; 991 992 done: 993 mutex_unlock(&esw->state_lock); 994 } 995 eswitch_vport_event(struct notifier_block * nb,unsigned long type,void * data)996 static int eswitch_vport_event(struct notifier_block *nb, 997 unsigned long type, void *data) 998 { 999 struct mlx5_eswitch *esw = mlx5_nb_cof(nb, struct mlx5_eswitch, nb); 1000 struct mlx5_eqe *eqe = data; 1001 struct mlx5_vport *vport; 1002 u16 vport_num; 1003 1004 vport_num = be16_to_cpu(eqe->data.vport_change.vport_num); 1005 vport = mlx5_eswitch_get_vport(esw, vport_num); 1006 if (!IS_ERR(vport)) 1007 queue_work(esw->work_queue, &vport->vport_change_handler); 1008 return NOTIFY_OK; 1009 } 1010 1011 /** 1012 * mlx5_esw_query_functions - Returns raw output about functions state 1013 * @dev: Pointer to device to query 1014 * 1015 * mlx5_esw_query_functions() allocates and returns functions changed 1016 * raw output memory pointer from device on success. Otherwise returns ERR_PTR. 1017 * Caller must free the memory using kvfree() when valid pointer is returned. 1018 */ mlx5_esw_query_functions(struct mlx5_core_dev * dev)1019 const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev) 1020 { 1021 int outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out); 1022 u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {}; 1023 u32 *out; 1024 int err; 1025 1026 out = kvzalloc(outlen, GFP_KERNEL); 1027 if (!out) 1028 return ERR_PTR(-ENOMEM); 1029 1030 MLX5_SET(query_esw_functions_in, in, opcode, 1031 MLX5_CMD_OP_QUERY_ESW_FUNCTIONS); 1032 1033 err = mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); 1034 if (!err) 1035 return out; 1036 1037 kvfree(out); 1038 return ERR_PTR(err); 1039 } 1040 mlx5_eswitch_event_handler_register(struct mlx5_eswitch * esw)1041 static void mlx5_eswitch_event_handler_register(struct mlx5_eswitch *esw) 1042 { 1043 if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) { 1044 MLX5_NB_INIT(&esw->esw_funcs.nb, mlx5_esw_funcs_changed_handler, 1045 ESW_FUNCTIONS_CHANGED); 1046 mlx5_eq_notifier_register(esw->dev, &esw->esw_funcs.nb); 1047 } 1048 } 1049 mlx5_eswitch_event_handler_unregister(struct mlx5_eswitch * esw)1050 static void mlx5_eswitch_event_handler_unregister(struct mlx5_eswitch *esw) 1051 { 1052 if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) 1053 mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb); 1054 1055 flush_workqueue(esw->work_queue); 1056 } 1057 mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch * esw)1058 static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw) 1059 { 1060 struct mlx5_vport *vport; 1061 unsigned long i; 1062 1063 mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) { 1064 memset(&vport->qos, 0, sizeof(vport->qos)); 1065 memset(&vport->info, 0, sizeof(vport->info)); 1066 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 1067 } 1068 } 1069 mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch * esw)1070 static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw) 1071 { 1072 struct mlx5_vport *vport; 1073 unsigned long i; 1074 1075 mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) { 1076 memset(&vport->qos, 0, sizeof(vport->qos)); 1077 memset(&vport->info, 0, sizeof(vport->info)); 1078 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 1079 } 1080 } 1081 mlx5_eswitch_load_vport(struct mlx5_eswitch * esw,struct mlx5_vport * vport,enum mlx5_eswitch_vport_event enabled_events)1082 static int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport, 1083 enum mlx5_eswitch_vport_event enabled_events) 1084 { 1085 int err; 1086 1087 err = mlx5_esw_vport_enable(esw, vport, enabled_events); 1088 if (err) 1089 return err; 1090 1091 err = mlx5_esw_offloads_load_rep(esw, vport); 1092 if (err) 1093 goto err_rep; 1094 1095 return err; 1096 1097 err_rep: 1098 mlx5_esw_vport_disable(esw, vport); 1099 return err; 1100 } 1101 mlx5_eswitch_unload_vport(struct mlx5_eswitch * esw,struct mlx5_vport * vport)1102 static void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 1103 { 1104 mlx5_esw_offloads_unload_rep(esw, vport); 1105 mlx5_esw_vport_disable(esw, vport); 1106 } 1107 mlx5_eswitch_load_pf_vf_vport(struct mlx5_eswitch * esw,u16 vport_num,enum mlx5_eswitch_vport_event enabled_events)1108 static int mlx5_eswitch_load_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num, 1109 enum mlx5_eswitch_vport_event enabled_events) 1110 { 1111 struct mlx5_vport *vport; 1112 int err; 1113 1114 vport = mlx5_eswitch_get_vport(esw, vport_num); 1115 if (IS_ERR(vport)) 1116 return PTR_ERR(vport); 1117 1118 err = mlx5_esw_offloads_init_pf_vf_rep(esw, vport); 1119 if (err) 1120 return err; 1121 1122 err = mlx5_eswitch_load_vport(esw, vport, enabled_events); 1123 if (err) 1124 goto err_load; 1125 return 0; 1126 1127 err_load: 1128 mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport); 1129 return err; 1130 } 1131 mlx5_eswitch_unload_pf_vf_vport(struct mlx5_eswitch * esw,u16 vport_num)1132 static void mlx5_eswitch_unload_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) 1133 { 1134 struct mlx5_vport *vport; 1135 1136 vport = mlx5_eswitch_get_vport(esw, vport_num); 1137 if (IS_ERR(vport)) 1138 return; 1139 1140 mlx5_eswitch_unload_vport(esw, vport); 1141 mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport); 1142 } 1143 mlx5_eswitch_load_sf_vport(struct mlx5_eswitch * esw,u16 vport_num,enum mlx5_eswitch_vport_event enabled_events,struct mlx5_devlink_port * dl_port,u32 controller,u32 sfnum)1144 int mlx5_eswitch_load_sf_vport(struct mlx5_eswitch *esw, u16 vport_num, 1145 enum mlx5_eswitch_vport_event enabled_events, 1146 struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum) 1147 { 1148 struct mlx5_vport *vport; 1149 int err; 1150 1151 vport = mlx5_eswitch_get_vport(esw, vport_num); 1152 if (IS_ERR(vport)) 1153 return PTR_ERR(vport); 1154 1155 err = mlx5_esw_offloads_init_sf_rep(esw, vport, dl_port, controller, sfnum); 1156 if (err) 1157 return err; 1158 1159 err = mlx5_eswitch_load_vport(esw, vport, enabled_events); 1160 if (err) 1161 goto err_load; 1162 1163 return 0; 1164 1165 err_load: 1166 mlx5_esw_offloads_cleanup_sf_rep(esw, vport); 1167 return err; 1168 } 1169 mlx5_eswitch_unload_sf_vport(struct mlx5_eswitch * esw,u16 vport_num)1170 void mlx5_eswitch_unload_sf_vport(struct mlx5_eswitch *esw, u16 vport_num) 1171 { 1172 struct mlx5_vport *vport; 1173 1174 vport = mlx5_eswitch_get_vport(esw, vport_num); 1175 if (IS_ERR(vport)) 1176 return; 1177 1178 mlx5_eswitch_unload_vport(esw, vport); 1179 mlx5_esw_offloads_cleanup_sf_rep(esw, vport); 1180 } 1181 mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch * esw,u16 num_vfs)1182 void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs) 1183 { 1184 struct mlx5_vport *vport; 1185 unsigned long i; 1186 1187 mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) { 1188 if (!vport->enabled) 1189 continue; 1190 mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport); 1191 } 1192 } 1193 mlx5_eswitch_unload_ec_vf_vports(struct mlx5_eswitch * esw,u16 num_ec_vfs)1194 static void mlx5_eswitch_unload_ec_vf_vports(struct mlx5_eswitch *esw, 1195 u16 num_ec_vfs) 1196 { 1197 struct mlx5_vport *vport; 1198 unsigned long i; 1199 1200 mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { 1201 if (!vport->enabled) 1202 continue; 1203 mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport); 1204 } 1205 } 1206 mlx5_eswitch_load_vf_vports(struct mlx5_eswitch * esw,u16 num_vfs,enum mlx5_eswitch_vport_event enabled_events)1207 int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, 1208 enum mlx5_eswitch_vport_event enabled_events) 1209 { 1210 struct mlx5_vport *vport; 1211 unsigned long i; 1212 int err; 1213 1214 mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) { 1215 err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events); 1216 if (err) 1217 goto vf_err; 1218 } 1219 1220 return 0; 1221 1222 vf_err: 1223 mlx5_eswitch_unload_vf_vports(esw, num_vfs); 1224 return err; 1225 } 1226 mlx5_eswitch_load_ec_vf_vports(struct mlx5_eswitch * esw,u16 num_ec_vfs,enum mlx5_eswitch_vport_event enabled_events)1227 static int mlx5_eswitch_load_ec_vf_vports(struct mlx5_eswitch *esw, u16 num_ec_vfs, 1228 enum mlx5_eswitch_vport_event enabled_events) 1229 { 1230 struct mlx5_vport *vport; 1231 unsigned long i; 1232 int err; 1233 1234 mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { 1235 err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events); 1236 if (err) 1237 goto vf_err; 1238 } 1239 1240 return 0; 1241 1242 vf_err: 1243 mlx5_eswitch_unload_ec_vf_vports(esw, num_ec_vfs); 1244 return err; 1245 } 1246 host_pf_enable_hca(struct mlx5_core_dev * dev)1247 static int host_pf_enable_hca(struct mlx5_core_dev *dev) 1248 { 1249 if (!mlx5_core_is_ecpf(dev)) 1250 return 0; 1251 1252 /* Once vport and representor are ready, take out the external host PF 1253 * out of initializing state. Enabling HCA clears the iser->initializing 1254 * bit and host PF driver loading can progress. 1255 */ 1256 return mlx5_cmd_host_pf_enable_hca(dev); 1257 } 1258 host_pf_disable_hca(struct mlx5_core_dev * dev)1259 static void host_pf_disable_hca(struct mlx5_core_dev *dev) 1260 { 1261 if (!mlx5_core_is_ecpf(dev)) 1262 return; 1263 1264 mlx5_cmd_host_pf_disable_hca(dev); 1265 } 1266 1267 /* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs 1268 * whichever are present on the eswitch. 1269 */ 1270 int mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch * esw,enum mlx5_eswitch_vport_event enabled_events)1271 mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, 1272 enum mlx5_eswitch_vport_event enabled_events) 1273 { 1274 bool pf_needed; 1275 int ret; 1276 1277 pf_needed = mlx5_core_is_ecpf_esw_manager(esw->dev) || 1278 esw->mode == MLX5_ESWITCH_LEGACY; 1279 1280 /* Enable PF vport */ 1281 if (pf_needed) { 1282 ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_PF, 1283 enabled_events); 1284 if (ret) 1285 return ret; 1286 } 1287 1288 /* Enable external host PF HCA */ 1289 ret = host_pf_enable_hca(esw->dev); 1290 if (ret) 1291 goto pf_hca_err; 1292 1293 /* Enable ECPF vport */ 1294 if (mlx5_ecpf_vport_exists(esw->dev)) { 1295 ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_ECPF, enabled_events); 1296 if (ret) 1297 goto ecpf_err; 1298 if (mlx5_core_ec_sriov_enabled(esw->dev)) { 1299 ret = mlx5_eswitch_load_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs, 1300 enabled_events); 1301 if (ret) 1302 goto ec_vf_err; 1303 } 1304 } 1305 1306 /* Enable VF vports */ 1307 ret = mlx5_eswitch_load_vf_vports(esw, esw->esw_funcs.num_vfs, 1308 enabled_events); 1309 if (ret) 1310 goto vf_err; 1311 return 0; 1312 1313 vf_err: 1314 if (mlx5_core_ec_sriov_enabled(esw->dev)) 1315 mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs); 1316 ec_vf_err: 1317 if (mlx5_ecpf_vport_exists(esw->dev)) 1318 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF); 1319 ecpf_err: 1320 host_pf_disable_hca(esw->dev); 1321 pf_hca_err: 1322 if (pf_needed) 1323 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_PF); 1324 return ret; 1325 } 1326 1327 /* mlx5_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs 1328 * whichever are previously enabled on the eswitch. 1329 */ mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch * esw)1330 void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw) 1331 { 1332 mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); 1333 1334 if (mlx5_ecpf_vport_exists(esw->dev)) { 1335 if (mlx5_core_ec_sriov_enabled(esw->dev)) 1336 mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_vfs); 1337 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF); 1338 } 1339 1340 host_pf_disable_hca(esw->dev); 1341 1342 if (mlx5_core_is_ecpf_esw_manager(esw->dev) || 1343 esw->mode == MLX5_ESWITCH_LEGACY) 1344 mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_PF); 1345 } 1346 mlx5_eswitch_get_devlink_param(struct mlx5_eswitch * esw)1347 static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw) 1348 { 1349 struct devlink *devlink = priv_to_devlink(esw->dev); 1350 union devlink_param_value val; 1351 int err; 1352 1353 err = devl_param_driverinit_value_get(devlink, 1354 MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 1355 &val); 1356 if (!err) { 1357 esw->params.large_group_num = val.vu32; 1358 } else { 1359 esw_warn(esw->dev, 1360 "Devlink can't get param fdb_large_groups, uses default (%d).\n", 1361 ESW_OFFLOADS_DEFAULT_NUM_GROUPS); 1362 esw->params.large_group_num = ESW_OFFLOADS_DEFAULT_NUM_GROUPS; 1363 } 1364 } 1365 1366 static void mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch * esw,int num_vfs)1367 mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs) 1368 { 1369 const u32 *out; 1370 1371 if (num_vfs < 0) 1372 return; 1373 1374 if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) { 1375 esw->esw_funcs.num_vfs = num_vfs; 1376 return; 1377 } 1378 1379 out = mlx5_esw_query_functions(esw->dev); 1380 if (IS_ERR(out)) 1381 return; 1382 1383 esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out, 1384 host_params_context.host_num_of_vfs); 1385 if (mlx5_core_ec_sriov_enabled(esw->dev)) 1386 esw->esw_funcs.num_ec_vfs = num_vfs; 1387 1388 kvfree(out); 1389 } 1390 mlx5_esw_mode_change_notify(struct mlx5_eswitch * esw,u16 mode)1391 static void mlx5_esw_mode_change_notify(struct mlx5_eswitch *esw, u16 mode) 1392 { 1393 struct mlx5_esw_event_info info = {}; 1394 1395 info.new_mode = mode; 1396 1397 blocking_notifier_call_chain(&esw->n_head, 0, &info); 1398 } 1399 mlx5_esw_acls_ns_init(struct mlx5_eswitch * esw)1400 static int mlx5_esw_acls_ns_init(struct mlx5_eswitch *esw) 1401 { 1402 struct mlx5_core_dev *dev = esw->dev; 1403 int total_vports; 1404 int err; 1405 1406 if (esw->flags & MLX5_ESWITCH_VPORT_ACL_NS_CREATED) 1407 return 0; 1408 1409 total_vports = mlx5_eswitch_get_total_vports(dev); 1410 1411 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) { 1412 err = mlx5_fs_egress_acls_init(dev, total_vports); 1413 if (err) 1414 return err; 1415 } else { 1416 esw_warn(dev, "egress ACL is not supported by FW\n"); 1417 } 1418 1419 if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) { 1420 err = mlx5_fs_ingress_acls_init(dev, total_vports); 1421 if (err) 1422 goto err; 1423 } else { 1424 esw_warn(dev, "ingress ACL is not supported by FW\n"); 1425 } 1426 esw->flags |= MLX5_ESWITCH_VPORT_ACL_NS_CREATED; 1427 return 0; 1428 1429 err: 1430 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) 1431 mlx5_fs_egress_acls_cleanup(dev); 1432 return err; 1433 } 1434 mlx5_esw_acls_ns_cleanup(struct mlx5_eswitch * esw)1435 static void mlx5_esw_acls_ns_cleanup(struct mlx5_eswitch *esw) 1436 { 1437 struct mlx5_core_dev *dev = esw->dev; 1438 1439 esw->flags &= ~MLX5_ESWITCH_VPORT_ACL_NS_CREATED; 1440 if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) 1441 mlx5_fs_ingress_acls_cleanup(dev); 1442 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) 1443 mlx5_fs_egress_acls_cleanup(dev); 1444 } 1445 1446 /** 1447 * mlx5_eswitch_enable_locked - Enable eswitch 1448 * @esw: Pointer to eswitch 1449 * @num_vfs: Enable eswitch for given number of VFs. This is optional. 1450 * Valid value are 0, > 0 and MLX5_ESWITCH_IGNORE_NUM_VFS. 1451 * Caller should pass num_vfs > 0 when enabling eswitch for 1452 * vf vports. Caller should pass num_vfs = 0, when eswitch 1453 * is enabled without sriov VFs or when caller 1454 * is unaware of the sriov state of the host PF on ECPF based 1455 * eswitch. Caller should pass < 0 when num_vfs should be 1456 * completely ignored. This is typically the case when eswitch 1457 * is enabled without sriov regardless of PF/ECPF system. 1458 * mlx5_eswitch_enable_locked() Enables eswitch in either legacy or offloads 1459 * mode. If num_vfs >=0 is provided, it setup VF related eswitch vports. 1460 * It returns 0 on success or error code on failure. 1461 */ mlx5_eswitch_enable_locked(struct mlx5_eswitch * esw,int num_vfs)1462 int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs) 1463 { 1464 int err; 1465 1466 devl_assert_locked(priv_to_devlink(esw->dev)); 1467 1468 if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) { 1469 esw_warn(esw->dev, "FDB is not supported, aborting ...\n"); 1470 return -EOPNOTSUPP; 1471 } 1472 1473 mlx5_eswitch_get_devlink_param(esw); 1474 1475 err = mlx5_esw_acls_ns_init(esw); 1476 if (err) 1477 return err; 1478 1479 mlx5_eswitch_update_num_of_vfs(esw, num_vfs); 1480 1481 MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE); 1482 mlx5_eq_notifier_register(esw->dev, &esw->nb); 1483 1484 if (esw->mode == MLX5_ESWITCH_LEGACY) { 1485 err = esw_legacy_enable(esw); 1486 } else { 1487 mlx5_rescan_drivers(esw->dev); 1488 err = esw_offloads_enable(esw); 1489 } 1490 1491 if (err) 1492 goto err_esw_enable; 1493 1494 esw->fdb_table.flags |= MLX5_ESW_FDB_CREATED; 1495 1496 mlx5_eswitch_event_handler_register(esw); 1497 1498 esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", 1499 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", 1500 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); 1501 1502 mlx5_esw_mode_change_notify(esw, esw->mode); 1503 1504 return 0; 1505 1506 err_esw_enable: 1507 mlx5_eq_notifier_unregister(esw->dev, &esw->nb); 1508 mlx5_esw_acls_ns_cleanup(esw); 1509 return err; 1510 } 1511 1512 /** 1513 * mlx5_eswitch_enable - Enable eswitch 1514 * @esw: Pointer to eswitch 1515 * @num_vfs: Enable eswitch switch for given number of VFs. 1516 * Caller must pass num_vfs > 0 when enabling eswitch for 1517 * vf vports. 1518 * mlx5_eswitch_enable() returns 0 on success or error code on failure. 1519 */ mlx5_eswitch_enable(struct mlx5_eswitch * esw,int num_vfs)1520 int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) 1521 { 1522 bool toggle_lag; 1523 int ret = 0; 1524 1525 if (!mlx5_esw_allowed(esw)) 1526 return 0; 1527 1528 devl_assert_locked(priv_to_devlink(esw->dev)); 1529 1530 toggle_lag = !mlx5_esw_is_fdb_created(esw); 1531 1532 if (toggle_lag) 1533 mlx5_lag_disable_change(esw->dev); 1534 1535 if (!mlx5_esw_is_fdb_created(esw)) { 1536 ret = mlx5_eswitch_enable_locked(esw, num_vfs); 1537 } else { 1538 enum mlx5_eswitch_vport_event vport_events; 1539 1540 vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ? 1541 MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE; 1542 /* If this is the ECPF the number of host VFs is managed via the 1543 * eswitch function change event handler, and any num_vfs provided 1544 * here are intended to be EC VFs. 1545 */ 1546 if (!mlx5_core_is_ecpf(esw->dev)) { 1547 ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events); 1548 if (!ret) 1549 esw->esw_funcs.num_vfs = num_vfs; 1550 } else if (mlx5_core_ec_sriov_enabled(esw->dev)) { 1551 ret = mlx5_eswitch_load_ec_vf_vports(esw, num_vfs, vport_events); 1552 if (!ret) 1553 esw->esw_funcs.num_ec_vfs = num_vfs; 1554 } 1555 } 1556 1557 if (toggle_lag) 1558 mlx5_lag_enable_change(esw->dev); 1559 1560 return ret; 1561 } 1562 1563 /* When disabling sriov, free driver level resources. */ mlx5_eswitch_disable_sriov(struct mlx5_eswitch * esw,bool clear_vf)1564 void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) 1565 { 1566 if (!mlx5_esw_allowed(esw)) 1567 return; 1568 1569 devl_assert_locked(priv_to_devlink(esw->dev)); 1570 /* If driver is unloaded, this function is called twice by remove_one() 1571 * and mlx5_unload(). Prevent the second call. 1572 */ 1573 if (!esw->esw_funcs.num_vfs && !esw->esw_funcs.num_ec_vfs && !clear_vf) 1574 return; 1575 1576 esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", 1577 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", 1578 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); 1579 1580 if (!mlx5_core_is_ecpf(esw->dev)) { 1581 mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); 1582 if (clear_vf) 1583 mlx5_eswitch_clear_vf_vports_info(esw); 1584 } else if (mlx5_core_ec_sriov_enabled(esw->dev)) { 1585 mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs); 1586 if (clear_vf) 1587 mlx5_eswitch_clear_ec_vf_vports_info(esw); 1588 } 1589 1590 if (esw->mode == MLX5_ESWITCH_OFFLOADS) { 1591 struct devlink *devlink = priv_to_devlink(esw->dev); 1592 1593 devl_rate_nodes_destroy(devlink); 1594 } 1595 /* Destroy legacy fdb when disabling sriov in legacy mode. */ 1596 if (esw->mode == MLX5_ESWITCH_LEGACY) 1597 mlx5_eswitch_disable_locked(esw); 1598 1599 if (!mlx5_core_is_ecpf(esw->dev)) 1600 esw->esw_funcs.num_vfs = 0; 1601 else 1602 esw->esw_funcs.num_ec_vfs = 0; 1603 } 1604 1605 /* Free resources for corresponding eswitch mode. It is called by devlink 1606 * when changing eswitch mode or modprobe when unloading driver. 1607 */ mlx5_eswitch_disable_locked(struct mlx5_eswitch * esw)1608 void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw) 1609 { 1610 struct devlink *devlink = priv_to_devlink(esw->dev); 1611 1612 /* Notify eswitch users that it is exiting from current mode. 1613 * So that it can do necessary cleanup before the eswitch is disabled. 1614 */ 1615 mlx5_esw_mode_change_notify(esw, MLX5_ESWITCH_LEGACY); 1616 1617 mlx5_eq_notifier_unregister(esw->dev, &esw->nb); 1618 mlx5_eswitch_event_handler_unregister(esw); 1619 1620 esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", 1621 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", 1622 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); 1623 1624 if (esw->fdb_table.flags & MLX5_ESW_FDB_CREATED) { 1625 esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED; 1626 if (esw->mode == MLX5_ESWITCH_OFFLOADS) 1627 esw_offloads_disable(esw); 1628 else if (esw->mode == MLX5_ESWITCH_LEGACY) 1629 esw_legacy_disable(esw); 1630 mlx5_esw_acls_ns_cleanup(esw); 1631 } 1632 1633 if (esw->mode == MLX5_ESWITCH_OFFLOADS) 1634 devl_rate_nodes_destroy(devlink); 1635 } 1636 mlx5_eswitch_disable(struct mlx5_eswitch * esw)1637 void mlx5_eswitch_disable(struct mlx5_eswitch *esw) 1638 { 1639 if (!mlx5_esw_allowed(esw)) 1640 return; 1641 1642 devl_assert_locked(priv_to_devlink(esw->dev)); 1643 mlx5_lag_disable_change(esw->dev); 1644 mlx5_eswitch_disable_locked(esw); 1645 esw->mode = MLX5_ESWITCH_LEGACY; 1646 mlx5_lag_enable_change(esw->dev); 1647 } 1648 mlx5_query_hca_cap_host_pf(struct mlx5_core_dev * dev,void * out)1649 static int mlx5_query_hca_cap_host_pf(struct mlx5_core_dev *dev, void *out) 1650 { 1651 u16 opmod = (MLX5_CAP_GENERAL << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01); 1652 u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {}; 1653 1654 MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 1655 MLX5_SET(query_hca_cap_in, in, op_mod, opmod); 1656 MLX5_SET(query_hca_cap_in, in, function_id, MLX5_VPORT_PF); 1657 MLX5_SET(query_hca_cap_in, in, other_function, true); 1658 return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out); 1659 } 1660 mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev * dev,u16 * max_sfs,u16 * sf_base_id)1661 int mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev *dev, u16 *max_sfs, u16 *sf_base_id) 1662 1663 { 1664 int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); 1665 void *query_ctx; 1666 void *hca_caps; 1667 int err; 1668 1669 if (!mlx5_core_is_ecpf(dev)) { 1670 *max_sfs = 0; 1671 return 0; 1672 } 1673 1674 query_ctx = kzalloc(query_out_sz, GFP_KERNEL); 1675 if (!query_ctx) 1676 return -ENOMEM; 1677 1678 err = mlx5_query_hca_cap_host_pf(dev, query_ctx); 1679 if (err) 1680 goto out_free; 1681 1682 hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); 1683 *max_sfs = MLX5_GET(cmd_hca_cap, hca_caps, max_num_sf); 1684 *sf_base_id = MLX5_GET(cmd_hca_cap, hca_caps, sf_base_id); 1685 1686 out_free: 1687 kfree(query_ctx); 1688 return err; 1689 } 1690 mlx5_esw_vport_alloc(struct mlx5_eswitch * esw,int index,u16 vport_num)1691 static int mlx5_esw_vport_alloc(struct mlx5_eswitch *esw, 1692 int index, u16 vport_num) 1693 { 1694 struct mlx5_vport *vport; 1695 int err; 1696 1697 vport = kzalloc(sizeof(*vport), GFP_KERNEL); 1698 if (!vport) 1699 return -ENOMEM; 1700 1701 vport->dev = esw->dev; 1702 vport->vport = vport_num; 1703 vport->index = index; 1704 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 1705 INIT_WORK(&vport->vport_change_handler, esw_vport_change_handler); 1706 err = xa_insert(&esw->vports, vport_num, vport, GFP_KERNEL); 1707 if (err) 1708 goto insert_err; 1709 1710 esw->total_vports++; 1711 return 0; 1712 1713 insert_err: 1714 kfree(vport); 1715 return err; 1716 } 1717 mlx5_esw_vport_free(struct mlx5_eswitch * esw,struct mlx5_vport * vport)1718 static void mlx5_esw_vport_free(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 1719 { 1720 xa_erase(&esw->vports, vport->vport); 1721 kfree(vport); 1722 } 1723 mlx5_esw_vports_cleanup(struct mlx5_eswitch * esw)1724 static void mlx5_esw_vports_cleanup(struct mlx5_eswitch *esw) 1725 { 1726 struct mlx5_vport *vport; 1727 unsigned long i; 1728 1729 mlx5_esw_for_each_vport(esw, i, vport) 1730 mlx5_esw_vport_free(esw, vport); 1731 xa_destroy(&esw->vports); 1732 } 1733 mlx5_esw_vports_init(struct mlx5_eswitch * esw)1734 static int mlx5_esw_vports_init(struct mlx5_eswitch *esw) 1735 { 1736 struct mlx5_core_dev *dev = esw->dev; 1737 u16 max_host_pf_sfs; 1738 u16 base_sf_num; 1739 int idx = 0; 1740 int err; 1741 int i; 1742 1743 xa_init(&esw->vports); 1744 1745 err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_PF); 1746 if (err) 1747 goto err; 1748 if (esw->first_host_vport == MLX5_VPORT_PF) 1749 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN); 1750 idx++; 1751 1752 for (i = 0; i < mlx5_core_max_vfs(dev); i++) { 1753 err = mlx5_esw_vport_alloc(esw, idx, idx); 1754 if (err) 1755 goto err; 1756 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_VF); 1757 xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN); 1758 idx++; 1759 } 1760 base_sf_num = mlx5_sf_start_function_id(dev); 1761 for (i = 0; i < mlx5_sf_max_functions(dev); i++) { 1762 err = mlx5_esw_vport_alloc(esw, idx, base_sf_num + i); 1763 if (err) 1764 goto err; 1765 xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF); 1766 idx++; 1767 } 1768 1769 err = mlx5_esw_sf_max_hpf_functions(dev, &max_host_pf_sfs, &base_sf_num); 1770 if (err) 1771 goto err; 1772 for (i = 0; i < max_host_pf_sfs; i++) { 1773 err = mlx5_esw_vport_alloc(esw, idx, base_sf_num + i); 1774 if (err) 1775 goto err; 1776 xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF); 1777 idx++; 1778 } 1779 1780 if (mlx5_core_ec_sriov_enabled(esw->dev)) { 1781 int ec_vf_base_num = mlx5_core_ec_vf_vport_base(dev); 1782 1783 for (i = 0; i < mlx5_core_max_ec_vfs(esw->dev); i++) { 1784 err = mlx5_esw_vport_alloc(esw, idx, ec_vf_base_num + i); 1785 if (err) 1786 goto err; 1787 idx++; 1788 } 1789 } 1790 1791 if (mlx5_ecpf_vport_exists(dev) || 1792 mlx5_core_is_ecpf_esw_manager(dev)) { 1793 err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_ECPF); 1794 if (err) 1795 goto err; 1796 idx++; 1797 } 1798 err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_UPLINK); 1799 if (err) 1800 goto err; 1801 return 0; 1802 1803 err: 1804 mlx5_esw_vports_cleanup(esw); 1805 return err; 1806 } 1807 mlx5_devlink_esw_multiport_set(struct devlink * devlink,u32 id,struct devlink_param_gset_ctx * ctx,struct netlink_ext_ack * extack)1808 static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id, 1809 struct devlink_param_gset_ctx *ctx, 1810 struct netlink_ext_ack *extack) 1811 { 1812 struct mlx5_core_dev *dev = devlink_priv(devlink); 1813 1814 if (!MLX5_ESWITCH_MANAGER(dev)) 1815 return -EOPNOTSUPP; 1816 1817 if (ctx->val.vbool) 1818 return mlx5_lag_mpesw_enable(dev); 1819 1820 mlx5_lag_mpesw_disable(dev); 1821 return 0; 1822 } 1823 mlx5_devlink_esw_multiport_get(struct devlink * devlink,u32 id,struct devlink_param_gset_ctx * ctx)1824 static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id, 1825 struct devlink_param_gset_ctx *ctx) 1826 { 1827 struct mlx5_core_dev *dev = devlink_priv(devlink); 1828 1829 ctx->val.vbool = mlx5_lag_is_mpesw(dev); 1830 return 0; 1831 } 1832 1833 static const struct devlink_param mlx5_eswitch_params[] = { 1834 DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT, 1835 "esw_multiport", DEVLINK_PARAM_TYPE_BOOL, 1836 BIT(DEVLINK_PARAM_CMODE_RUNTIME), 1837 mlx5_devlink_esw_multiport_get, 1838 mlx5_devlink_esw_multiport_set, NULL), 1839 }; 1840 mlx5_eswitch_init(struct mlx5_core_dev * dev)1841 int mlx5_eswitch_init(struct mlx5_core_dev *dev) 1842 { 1843 struct mlx5_eswitch *esw; 1844 int err; 1845 1846 if (!MLX5_VPORT_MANAGER(dev) && !MLX5_ESWITCH_MANAGER(dev)) 1847 return 0; 1848 1849 esw = kzalloc(sizeof(*esw), GFP_KERNEL); 1850 if (!esw) 1851 return -ENOMEM; 1852 1853 err = devl_params_register(priv_to_devlink(dev), mlx5_eswitch_params, 1854 ARRAY_SIZE(mlx5_eswitch_params)); 1855 if (err) 1856 goto free_esw; 1857 1858 esw->dev = dev; 1859 esw->manager_vport = mlx5_eswitch_manager_vport(dev); 1860 esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev); 1861 1862 esw->debugfs_root = debugfs_create_dir("esw", mlx5_debugfs_get_dev_root(dev)); 1863 esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq"); 1864 if (!esw->work_queue) { 1865 err = -ENOMEM; 1866 goto abort; 1867 } 1868 1869 err = mlx5_esw_vports_init(esw); 1870 if (err) 1871 goto abort; 1872 1873 dev->priv.eswitch = esw; 1874 err = esw_offloads_init(esw); 1875 if (err) 1876 goto reps_err; 1877 1878 mutex_init(&esw->offloads.encap_tbl_lock); 1879 hash_init(esw->offloads.encap_tbl); 1880 mutex_init(&esw->offloads.decap_tbl_lock); 1881 hash_init(esw->offloads.decap_tbl); 1882 mlx5e_mod_hdr_tbl_init(&esw->offloads.mod_hdr); 1883 atomic64_set(&esw->offloads.num_flows, 0); 1884 ida_init(&esw->offloads.vport_metadata_ida); 1885 xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC); 1886 mutex_init(&esw->state_lock); 1887 init_rwsem(&esw->mode_lock); 1888 refcount_set(&esw->qos.refcnt, 0); 1889 1890 esw->enabled_vports = 0; 1891 esw->mode = MLX5_ESWITCH_LEGACY; 1892 esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE; 1893 if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) && 1894 MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap)) 1895 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; 1896 else 1897 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; 1898 BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head); 1899 1900 esw_info(dev, 1901 "Total vports %d, per vport: max uc(%d) max mc(%d)\n", 1902 esw->total_vports, 1903 MLX5_MAX_UC_PER_VPORT(dev), 1904 MLX5_MAX_MC_PER_VPORT(dev)); 1905 return 0; 1906 1907 reps_err: 1908 mlx5_esw_vports_cleanup(esw); 1909 dev->priv.eswitch = NULL; 1910 abort: 1911 if (esw->work_queue) 1912 destroy_workqueue(esw->work_queue); 1913 debugfs_remove_recursive(esw->debugfs_root); 1914 devl_params_unregister(priv_to_devlink(dev), mlx5_eswitch_params, 1915 ARRAY_SIZE(mlx5_eswitch_params)); 1916 free_esw: 1917 kfree(esw); 1918 return err; 1919 } 1920 mlx5_eswitch_cleanup(struct mlx5_eswitch * esw)1921 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) 1922 { 1923 if (!esw) 1924 return; 1925 1926 esw_info(esw->dev, "cleanup\n"); 1927 1928 destroy_workqueue(esw->work_queue); 1929 WARN_ON(refcount_read(&esw->qos.refcnt)); 1930 mutex_destroy(&esw->state_lock); 1931 WARN_ON(!xa_empty(&esw->offloads.vhca_map)); 1932 xa_destroy(&esw->offloads.vhca_map); 1933 ida_destroy(&esw->offloads.vport_metadata_ida); 1934 mlx5e_mod_hdr_tbl_destroy(&esw->offloads.mod_hdr); 1935 mutex_destroy(&esw->offloads.encap_tbl_lock); 1936 mutex_destroy(&esw->offloads.decap_tbl_lock); 1937 esw_offloads_cleanup(esw); 1938 esw->dev->priv.eswitch = NULL; 1939 mlx5_esw_vports_cleanup(esw); 1940 debugfs_remove_recursive(esw->debugfs_root); 1941 devl_params_unregister(priv_to_devlink(esw->dev), mlx5_eswitch_params, 1942 ARRAY_SIZE(mlx5_eswitch_params)); 1943 kfree(esw); 1944 } 1945 1946 /* Vport Administration */ 1947 static int mlx5_esw_set_vport_mac_locked(struct mlx5_eswitch * esw,struct mlx5_vport * evport,const u8 * mac)1948 mlx5_esw_set_vport_mac_locked(struct mlx5_eswitch *esw, 1949 struct mlx5_vport *evport, const u8 *mac) 1950 { 1951 u16 vport_num = evport->vport; 1952 u64 node_guid; 1953 int err = 0; 1954 1955 if (is_multicast_ether_addr(mac)) 1956 return -EINVAL; 1957 1958 if (evport->info.spoofchk && !is_valid_ether_addr(mac)) 1959 mlx5_core_warn(esw->dev, 1960 "Set invalid MAC while spoofchk is on, vport(%d)\n", 1961 vport_num); 1962 1963 err = mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, mac); 1964 if (err) { 1965 mlx5_core_warn(esw->dev, 1966 "Failed to mlx5_modify_nic_vport_mac vport(%d) err=(%d)\n", 1967 vport_num, err); 1968 return err; 1969 } 1970 1971 node_guid_gen_from_mac(&node_guid, mac); 1972 err = mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, node_guid); 1973 if (err) 1974 mlx5_core_warn(esw->dev, 1975 "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n", 1976 vport_num, err); 1977 1978 ether_addr_copy(evport->info.mac, mac); 1979 evport->info.node_guid = node_guid; 1980 if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) 1981 err = esw_acl_ingress_lgcy_setup(esw, evport); 1982 1983 return err; 1984 } 1985 mlx5_eswitch_set_vport_mac(struct mlx5_eswitch * esw,u16 vport,const u8 * mac)1986 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, 1987 u16 vport, const u8 *mac) 1988 { 1989 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 1990 int err = 0; 1991 1992 if (IS_ERR(evport)) 1993 return PTR_ERR(evport); 1994 1995 mutex_lock(&esw->state_lock); 1996 err = mlx5_esw_set_vport_mac_locked(esw, evport, mac); 1997 mutex_unlock(&esw->state_lock); 1998 return err; 1999 } 2000 mlx5_esw_check_port_type(struct mlx5_eswitch * esw,u16 vport_num,xa_mark_t mark)2001 static bool mlx5_esw_check_port_type(struct mlx5_eswitch *esw, u16 vport_num, xa_mark_t mark) 2002 { 2003 return xa_get_mark(&esw->vports, vport_num, mark); 2004 } 2005 mlx5_eswitch_is_vf_vport(struct mlx5_eswitch * esw,u16 vport_num)2006 bool mlx5_eswitch_is_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) 2007 { 2008 return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_VF); 2009 } 2010 mlx5_eswitch_is_pf_vf_vport(struct mlx5_eswitch * esw,u16 vport_num)2011 bool mlx5_eswitch_is_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) 2012 { 2013 return vport_num == MLX5_VPORT_PF || 2014 mlx5_eswitch_is_vf_vport(esw, vport_num); 2015 } 2016 mlx5_esw_is_sf_vport(struct mlx5_eswitch * esw,u16 vport_num)2017 bool mlx5_esw_is_sf_vport(struct mlx5_eswitch *esw, u16 vport_num) 2018 { 2019 return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_SF); 2020 } 2021 mlx5_eswitch_set_vport_state(struct mlx5_eswitch * esw,u16 vport,int link_state)2022 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, 2023 u16 vport, int link_state) 2024 { 2025 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2026 int opmod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT; 2027 int other_vport = 1; 2028 int err = 0; 2029 2030 if (!mlx5_esw_allowed(esw)) 2031 return -EPERM; 2032 if (IS_ERR(evport)) 2033 return PTR_ERR(evport); 2034 2035 if (vport == MLX5_VPORT_UPLINK) { 2036 opmod = MLX5_VPORT_STATE_OP_MOD_UPLINK; 2037 other_vport = 0; 2038 vport = 0; 2039 } 2040 mutex_lock(&esw->state_lock); 2041 if (esw->mode != MLX5_ESWITCH_LEGACY) { 2042 err = -EOPNOTSUPP; 2043 goto unlock; 2044 } 2045 2046 err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, other_vport, link_state); 2047 if (err) { 2048 mlx5_core_warn(esw->dev, "Failed to set vport %d link state, opmod = %d, err = %d", 2049 vport, opmod, err); 2050 goto unlock; 2051 } 2052 2053 evport->info.link_state = link_state; 2054 2055 unlock: 2056 mutex_unlock(&esw->state_lock); 2057 return err; 2058 } 2059 mlx5_eswitch_get_vport_config(struct mlx5_eswitch * esw,u16 vport,struct ifla_vf_info * ivi)2060 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw, 2061 u16 vport, struct ifla_vf_info *ivi) 2062 { 2063 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2064 2065 if (IS_ERR(evport)) 2066 return PTR_ERR(evport); 2067 2068 memset(ivi, 0, sizeof(*ivi)); 2069 ivi->vf = vport - 1; 2070 2071 mutex_lock(&esw->state_lock); 2072 ether_addr_copy(ivi->mac, evport->info.mac); 2073 ivi->linkstate = evport->info.link_state; 2074 ivi->vlan = evport->info.vlan; 2075 ivi->qos = evport->info.qos; 2076 ivi->spoofchk = evport->info.spoofchk; 2077 ivi->trusted = evport->info.trusted; 2078 if (evport->qos.enabled) { 2079 ivi->min_tx_rate = evport->qos.min_rate; 2080 ivi->max_tx_rate = evport->qos.max_rate; 2081 } 2082 mutex_unlock(&esw->state_lock); 2083 2084 return 0; 2085 } 2086 __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch * esw,u16 vport,u16 vlan,u8 qos,u8 set_flags)2087 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, 2088 u16 vport, u16 vlan, u8 qos, u8 set_flags) 2089 { 2090 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2091 bool vst_mode_steering = esw_vst_mode_is_steering(esw); 2092 int err = 0; 2093 2094 if (IS_ERR(evport)) 2095 return PTR_ERR(evport); 2096 if (vlan > 4095 || qos > 7) 2097 return -EINVAL; 2098 2099 if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering) { 2100 err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags); 2101 if (err) 2102 return err; 2103 } 2104 2105 evport->info.vlan = vlan; 2106 evport->info.qos = qos; 2107 if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) { 2108 err = esw_acl_ingress_lgcy_setup(esw, evport); 2109 if (err) 2110 return err; 2111 err = esw_acl_egress_lgcy_setup(esw, evport); 2112 } 2113 2114 return err; 2115 } 2116 mlx5_eswitch_get_vport_stats(struct mlx5_eswitch * esw,u16 vport_num,struct ifla_vf_stats * vf_stats)2117 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, 2118 u16 vport_num, 2119 struct ifla_vf_stats *vf_stats) 2120 { 2121 struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); 2122 int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out); 2123 u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {}; 2124 struct mlx5_vport_drop_stats stats = {}; 2125 int err = 0; 2126 u32 *out; 2127 2128 if (IS_ERR(vport)) 2129 return PTR_ERR(vport); 2130 2131 out = kvzalloc(outlen, GFP_KERNEL); 2132 if (!out) 2133 return -ENOMEM; 2134 2135 MLX5_SET(query_vport_counter_in, in, opcode, 2136 MLX5_CMD_OP_QUERY_VPORT_COUNTER); 2137 MLX5_SET(query_vport_counter_in, in, op_mod, 0); 2138 MLX5_SET(query_vport_counter_in, in, vport_number, vport->vport); 2139 MLX5_SET(query_vport_counter_in, in, other_vport, 1); 2140 2141 err = mlx5_cmd_exec_inout(esw->dev, query_vport_counter, in, out); 2142 if (err) 2143 goto free_out; 2144 2145 #define MLX5_GET_CTR(p, x) \ 2146 MLX5_GET64(query_vport_counter_out, p, x) 2147 2148 memset(vf_stats, 0, sizeof(*vf_stats)); 2149 vf_stats->rx_packets = 2150 MLX5_GET_CTR(out, received_eth_unicast.packets) + 2151 MLX5_GET_CTR(out, received_ib_unicast.packets) + 2152 MLX5_GET_CTR(out, received_eth_multicast.packets) + 2153 MLX5_GET_CTR(out, received_ib_multicast.packets) + 2154 MLX5_GET_CTR(out, received_eth_broadcast.packets); 2155 2156 vf_stats->rx_bytes = 2157 MLX5_GET_CTR(out, received_eth_unicast.octets) + 2158 MLX5_GET_CTR(out, received_ib_unicast.octets) + 2159 MLX5_GET_CTR(out, received_eth_multicast.octets) + 2160 MLX5_GET_CTR(out, received_ib_multicast.octets) + 2161 MLX5_GET_CTR(out, received_eth_broadcast.octets); 2162 2163 vf_stats->tx_packets = 2164 MLX5_GET_CTR(out, transmitted_eth_unicast.packets) + 2165 MLX5_GET_CTR(out, transmitted_ib_unicast.packets) + 2166 MLX5_GET_CTR(out, transmitted_eth_multicast.packets) + 2167 MLX5_GET_CTR(out, transmitted_ib_multicast.packets) + 2168 MLX5_GET_CTR(out, transmitted_eth_broadcast.packets); 2169 2170 vf_stats->tx_bytes = 2171 MLX5_GET_CTR(out, transmitted_eth_unicast.octets) + 2172 MLX5_GET_CTR(out, transmitted_ib_unicast.octets) + 2173 MLX5_GET_CTR(out, transmitted_eth_multicast.octets) + 2174 MLX5_GET_CTR(out, transmitted_ib_multicast.octets) + 2175 MLX5_GET_CTR(out, transmitted_eth_broadcast.octets); 2176 2177 vf_stats->multicast = 2178 MLX5_GET_CTR(out, received_eth_multicast.packets) + 2179 MLX5_GET_CTR(out, received_ib_multicast.packets); 2180 2181 vf_stats->broadcast = 2182 MLX5_GET_CTR(out, received_eth_broadcast.packets); 2183 2184 err = mlx5_esw_query_vport_drop_stats(esw->dev, vport, &stats); 2185 if (err) 2186 goto free_out; 2187 vf_stats->rx_dropped = stats.rx_dropped; 2188 vf_stats->tx_dropped = stats.tx_dropped; 2189 2190 free_out: 2191 kvfree(out); 2192 return err; 2193 } 2194 mlx5_eswitch_mode(const struct mlx5_core_dev * dev)2195 u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev) 2196 { 2197 struct mlx5_eswitch *esw = dev->priv.eswitch; 2198 2199 return mlx5_esw_allowed(esw) ? esw->mode : MLX5_ESWITCH_LEGACY; 2200 } 2201 EXPORT_SYMBOL_GPL(mlx5_eswitch_mode); 2202 2203 enum devlink_eswitch_encap_mode mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev * dev)2204 mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev) 2205 { 2206 struct mlx5_eswitch *esw; 2207 2208 esw = dev->priv.eswitch; 2209 return (mlx5_eswitch_mode(dev) == MLX5_ESWITCH_OFFLOADS) ? esw->offloads.encap : 2210 DEVLINK_ESWITCH_ENCAP_MODE_NONE; 2211 } 2212 EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode); 2213 mlx5_esw_multipath_prereq(struct mlx5_core_dev * dev0,struct mlx5_core_dev * dev1)2214 bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0, 2215 struct mlx5_core_dev *dev1) 2216 { 2217 return (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS && 2218 dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS); 2219 } 2220 mlx5_esw_event_notifier_register(struct mlx5_eswitch * esw,struct notifier_block * nb)2221 int mlx5_esw_event_notifier_register(struct mlx5_eswitch *esw, struct notifier_block *nb) 2222 { 2223 return blocking_notifier_chain_register(&esw->n_head, nb); 2224 } 2225 mlx5_esw_event_notifier_unregister(struct mlx5_eswitch * esw,struct notifier_block * nb)2226 void mlx5_esw_event_notifier_unregister(struct mlx5_eswitch *esw, struct notifier_block *nb) 2227 { 2228 blocking_notifier_chain_unregister(&esw->n_head, nb); 2229 } 2230 2231 /** 2232 * mlx5_esw_hold() - Try to take a read lock on esw mode lock. 2233 * @mdev: mlx5 core device. 2234 * 2235 * Should be called by esw resources callers. 2236 * 2237 * Return: true on success or false. 2238 */ mlx5_esw_hold(struct mlx5_core_dev * mdev)2239 bool mlx5_esw_hold(struct mlx5_core_dev *mdev) 2240 { 2241 struct mlx5_eswitch *esw = mdev->priv.eswitch; 2242 2243 /* e.g. VF doesn't have eswitch so nothing to do */ 2244 if (!mlx5_esw_allowed(esw)) 2245 return true; 2246 2247 if (down_read_trylock(&esw->mode_lock) != 0) { 2248 if (esw->eswitch_operation_in_progress) { 2249 up_read(&esw->mode_lock); 2250 return false; 2251 } 2252 return true; 2253 } 2254 2255 return false; 2256 } 2257 2258 /** 2259 * mlx5_esw_release() - Release a read lock on esw mode lock. 2260 * @mdev: mlx5 core device. 2261 */ mlx5_esw_release(struct mlx5_core_dev * mdev)2262 void mlx5_esw_release(struct mlx5_core_dev *mdev) 2263 { 2264 struct mlx5_eswitch *esw = mdev->priv.eswitch; 2265 2266 if (mlx5_esw_allowed(esw)) 2267 up_read(&esw->mode_lock); 2268 } 2269 2270 /** 2271 * mlx5_esw_get() - Increase esw user count. 2272 * @mdev: mlx5 core device. 2273 */ mlx5_esw_get(struct mlx5_core_dev * mdev)2274 void mlx5_esw_get(struct mlx5_core_dev *mdev) 2275 { 2276 struct mlx5_eswitch *esw = mdev->priv.eswitch; 2277 2278 if (mlx5_esw_allowed(esw)) 2279 atomic64_inc(&esw->user_count); 2280 } 2281 2282 /** 2283 * mlx5_esw_put() - Decrease esw user count. 2284 * @mdev: mlx5 core device. 2285 */ mlx5_esw_put(struct mlx5_core_dev * mdev)2286 void mlx5_esw_put(struct mlx5_core_dev *mdev) 2287 { 2288 struct mlx5_eswitch *esw = mdev->priv.eswitch; 2289 2290 if (mlx5_esw_allowed(esw)) 2291 atomic64_dec_if_positive(&esw->user_count); 2292 } 2293 2294 /** 2295 * mlx5_esw_try_lock() - Take a write lock on esw mode lock. 2296 * @esw: eswitch device. 2297 * 2298 * Should be called by esw mode change routine. 2299 * 2300 * Return: 2301 * * 0 - esw mode if successfully locked and refcount is 0. 2302 * * -EBUSY - refcount is not 0. 2303 * * -EINVAL - In the middle of switching mode or lock is already held. 2304 */ mlx5_esw_try_lock(struct mlx5_eswitch * esw)2305 int mlx5_esw_try_lock(struct mlx5_eswitch *esw) 2306 { 2307 if (down_write_trylock(&esw->mode_lock) == 0) 2308 return -EINVAL; 2309 2310 if (esw->eswitch_operation_in_progress || 2311 atomic64_read(&esw->user_count) > 0) { 2312 up_write(&esw->mode_lock); 2313 return -EBUSY; 2314 } 2315 2316 return esw->mode; 2317 } 2318 mlx5_esw_lock(struct mlx5_eswitch * esw)2319 int mlx5_esw_lock(struct mlx5_eswitch *esw) 2320 { 2321 down_write(&esw->mode_lock); 2322 2323 if (esw->eswitch_operation_in_progress) { 2324 up_write(&esw->mode_lock); 2325 return -EBUSY; 2326 } 2327 2328 return 0; 2329 } 2330 2331 /** 2332 * mlx5_esw_unlock() - Release write lock on esw mode lock 2333 * @esw: eswitch device. 2334 */ mlx5_esw_unlock(struct mlx5_eswitch * esw)2335 void mlx5_esw_unlock(struct mlx5_eswitch *esw) 2336 { 2337 up_write(&esw->mode_lock); 2338 } 2339 2340 /** 2341 * mlx5_eswitch_get_total_vports - Get total vports of the eswitch 2342 * 2343 * @dev: Pointer to core device 2344 * 2345 * mlx5_eswitch_get_total_vports returns total number of eswitch vports. 2346 */ mlx5_eswitch_get_total_vports(const struct mlx5_core_dev * dev)2347 u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev) 2348 { 2349 struct mlx5_eswitch *esw; 2350 2351 esw = dev->priv.eswitch; 2352 return mlx5_esw_allowed(esw) ? esw->total_vports : 0; 2353 } 2354 EXPORT_SYMBOL_GPL(mlx5_eswitch_get_total_vports); 2355 2356 /** 2357 * mlx5_eswitch_get_core_dev - Get the mdev device 2358 * @esw : eswitch device. 2359 * 2360 * Return the mellanox core device which manages the eswitch. 2361 */ mlx5_eswitch_get_core_dev(struct mlx5_eswitch * esw)2362 struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw) 2363 { 2364 return mlx5_esw_allowed(esw) ? esw->dev : NULL; 2365 } 2366 EXPORT_SYMBOL(mlx5_eswitch_get_core_dev); 2367 mlx5_eswitch_block_ipsec(struct mlx5_core_dev * dev)2368 bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev) 2369 { 2370 struct mlx5_eswitch *esw = dev->priv.eswitch; 2371 2372 if (!mlx5_esw_allowed(esw)) 2373 return true; 2374 2375 mutex_lock(&esw->state_lock); 2376 if (esw->enabled_ipsec_vf_count) { 2377 mutex_unlock(&esw->state_lock); 2378 return false; 2379 } 2380 2381 dev->num_ipsec_offloads++; 2382 mutex_unlock(&esw->state_lock); 2383 return true; 2384 } 2385 mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev * dev)2386 void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev) 2387 { 2388 struct mlx5_eswitch *esw = dev->priv.eswitch; 2389 2390 if (!mlx5_esw_allowed(esw)) 2391 /* Failure means no eswitch => core dev is not a PF */ 2392 return; 2393 2394 mutex_lock(&esw->state_lock); 2395 dev->num_ipsec_offloads--; 2396 mutex_unlock(&esw->state_lock); 2397 } 2398