File Index
Files and directories
Sign in
FILE

eswitch.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c C
   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
  53enum {
  54	MLX5_ACTION_NONE = 0,
  55	MLX5_ACTION_ADD  = 1,
  56	MLX5_ACTION_DEL  = 2,
  57};
  58
  59/* Vport UC/MC hash node */
  60struct 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
  70static 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
  81static 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
  95struct mlx5_eswitch *__must_check
  96mlx5_devlink_eswitch_get(struct devlink *devlink)
  97{
  98	return __mlx5_devlink_eswitch_get(devlink, true);
  99}
 100
 101struct mlx5_eswitch *mlx5_devlink_eswitch_nocheck_get(struct devlink *devlink)
 102{
 103	return __mlx5_devlink_eswitch_get(devlink, false);
 104}
 105
 106struct mlx5_vport *__must_check
 107mlx5_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
 122static 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 */
 153int 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
 163static 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 */
 206static 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(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(%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
 269static struct mlx5_flow_handle *
 270esw_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
 278static struct mlx5_flow_handle *
 279esw_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
 291static struct mlx5_flow_handle *
 292esw_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 */
 303typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
 304				 struct vport_addr *vaddr);
 305
 306static 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
 327fdb_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
 339static 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
 358fdb_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
 366static 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
 415static 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
 439add:
 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
 455static 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 */
 498static 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 */
 532static 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	}
 612out:
 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 */
 619static 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 */
 654static 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
 683promisc:
 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 */
 697static 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
 725void 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
 761static 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
 772static 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
 784static 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
 793static 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
 802static 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	vport->vhca_id = MLX5_GET(cmd_hca_cap, hca_caps, vhca_id);
 824
 825	if (!MLX5_CAP_GEN_MAX(esw->dev, hca_cap_2))
 826		goto out_free;
 827
 828	memset(query_ctx, 0, query_out_sz);
 829	err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx,
 830					    MLX5_CAP_GENERAL_2);
 831	if (err)
 832		goto out_free;
 833
 834	hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
 835	vport->info.mig_enabled = MLX5_GET(cmd_hca_cap_2, hca_caps, migratable);
 836
 837	err = mlx5_esw_ipsec_vf_offload_get(esw->dev, vport);
 838out_free:
 839	kfree(query_ctx);
 840	return err;
 841}
 842
 843bool mlx5_esw_vport_vhca_id(struct mlx5_eswitch *esw, u16 vportn, u16 *vhca_id)
 844{
 845	struct mlx5_vport *vport;
 846
 847	vport = mlx5_eswitch_get_vport(esw, vportn);
 848	if (IS_ERR(vport) || MLX5_VPORT_INVAL_VHCA_ID(vport))
 849		return false;
 850
 851	*vhca_id = vport->vhca_id;
 852	return true;
 853}
 854
 855static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
 856{
 857	bool vst_mode_steering = esw_vst_mode_is_steering(esw);
 858	u16 vport_num = vport->vport;
 859	int flags;
 860	int err;
 861
 862	err = esw_vport_setup_acl(esw, vport);
 863	if (err)
 864		return err;
 865
 866	if (mlx5_esw_is_manager_vport(esw, vport_num))
 867		return 0;
 868
 869	err = mlx5_esw_vport_caps_get(esw, vport);
 870	if (err)
 871		goto err_caps;
 872
 873	mlx5_modify_vport_admin_state(esw->dev,
 874				      MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
 875				      vport_num, 1,
 876				      vport->info.link_state);
 877
 878	mlx5_query_nic_vport_mac_address(esw->dev, vport_num, true,
 879					 vport->info.mac);
 880	mlx5_query_nic_vport_node_guid(esw->dev, vport_num, true,
 881				       &vport->info.node_guid);
 882
 883	flags = (vport->info.vlan || vport->info.qos) ?
 884		SET_VLAN_STRIP | SET_VLAN_INSERT : 0;
 885	if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering)
 886		modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan,
 887				       vport->info.qos, flags);
 888
 889	return 0;
 890
 891err_caps:
 892	esw_vport_cleanup_acl(esw, vport);
 893	return err;
 894}
 895
 896/* Don't cleanup vport->info, it's needed to restore vport configuration */
 897static void esw_vport_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
 898{
 899	u16 vport_num = vport->vport;
 900
 901	if (!mlx5_esw_is_manager_vport(esw, vport_num))
 902		mlx5_modify_vport_admin_state(esw->dev,
 903					      MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
 904					      vport_num, 1,
 905					      MLX5_VPORT_ADMIN_STATE_DOWN);
 906
 907	mlx5_esw_qos_vport_disable(vport);
 908	esw_vport_cleanup_acl(esw, vport);
 909}
 910
 911int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
 912			  enum mlx5_eswitch_vport_event enabled_events)
 913{
 914	u16 vport_num = vport->vport;
 915	int ret;
 916
 917	mutex_lock(&esw->state_lock);
 918	WARN_ON(vport->enabled);
 919
 920	esw_debug(esw->dev, "Enabling VPORT(%d)\n", vport_num);
 921
 922	ret = esw_vport_setup(esw, vport);
 923	if (ret)
 924		goto done;
 925
 926	/* Sync with current vport context */
 927	vport->enabled_events = enabled_events;
 928	vport->enabled = true;
 929	if (vport->vport != MLX5_VPORT_PF &&
 930	    (vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled))
 931		esw->enabled_ipsec_vf_count++;
 932
 933	/* Esw manager is trusted by default. Host PF (vport 0) is trusted as well
 934	 * in smartNIC as it's a vport group manager.
 935	 */
 936	if (mlx5_esw_is_manager_vport(esw, vport_num) ||
 937	    (!vport_num && mlx5_core_is_ecpf(esw->dev)))
 938		vport->info.trusted = true;
 939
 940	if (!mlx5_esw_is_manager_vport(esw, vport_num) &&
 941	    MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) {
 942		ret = mlx5_esw_vport_vhca_id_map(esw, vport);
 943		if (ret)
 944			goto err_vhca_mapping;
 945	}
 946
 947	esw_vport_change_handle_locked(vport);
 948
 949	esw->enabled_vports++;
 950	esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num);
 951done:
 952	mutex_unlock(&esw->state_lock);
 953	return ret;
 954
 955err_vhca_mapping:
 956	esw_vport_cleanup(esw, vport);
 957	mutex_unlock(&esw->state_lock);
 958	return ret;
 959}
 960
 961void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
 962{
 963	u16 vport_num = vport->vport;
 964
 965	mutex_lock(&esw->state_lock);
 966
 967	if (!vport->enabled)
 968		goto done;
 969
 970	esw_debug(esw->dev, "Disabling vport(%d)\n", vport_num);
 971	/* Mark this vport as disabled to discard new events */
 972	vport->enabled = false;
 973
 974	/* Disable events from this vport */
 975	if (MLX5_CAP_GEN(esw->dev, log_max_l2_table))
 976		arm_vport_context_events_cmd(esw->dev, vport_num, 0);
 977
 978	if (!mlx5_esw_is_manager_vport(esw, vport_num) &&
 979	    MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
 980		mlx5_esw_vport_vhca_id_unmap(esw, vport);
 981
 982	if (vport->vport != MLX5_VPORT_PF &&
 983	    (vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled))
 984		esw->enabled_ipsec_vf_count--;
 985
 986	/* We don't assume VFs will cleanup after themselves.
 987	 * Calling vport change handler while vport is disabled will cleanup
 988	 * the vport resources.
 989	 */
 990	esw_vport_change_handle_locked(vport);
 991	vport->enabled_events = 0;
 992	esw_apply_vport_rx_mode(esw, vport, false, false);
 993	esw_vport_cleanup(esw, vport);
 994	esw->enabled_vports--;
 995
 996done:
 997	mutex_unlock(&esw->state_lock);
 998}
 999
1000static int eswitch_vport_event(struct notifier_block *nb,
1001			       unsigned long type, void *data)
1002{
1003	struct mlx5_eswitch *esw = mlx5_nb_cof(nb, struct mlx5_eswitch, nb);
1004	struct mlx5_eqe *eqe = data;
1005	struct mlx5_vport *vport;
1006	u16 vport_num;
1007
1008	vport_num = be16_to_cpu(eqe->data.vport_change.vport_num);
1009	vport = mlx5_eswitch_get_vport(esw, vport_num);
1010	if (!IS_ERR(vport))
1011		queue_work(esw->work_queue, &vport->vport_change_handler);
1012	return NOTIFY_OK;
1013}
1014
1015/**
1016 * mlx5_esw_query_functions - Returns raw output about functions state
1017 * @dev:	Pointer to device to query
1018 *
1019 * mlx5_esw_query_functions() allocates and returns functions changed
1020 * raw output memory pointer from device on success. Otherwise returns ERR_PTR.
1021 * Caller must free the memory using kvfree() when valid pointer is returned.
1022 */
1023const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
1024{
1025	int outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out);
1026	u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {};
1027	u32 *out;
1028	int err;
1029
1030	out = kvzalloc(outlen, GFP_KERNEL);
1031	if (!out)
1032		return ERR_PTR(-ENOMEM);
1033
1034	MLX5_SET(query_esw_functions_in, in, opcode,
1035		 MLX5_CMD_OP_QUERY_ESW_FUNCTIONS);
1036
1037	err = mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
1038	if (!err)
1039		return out;
1040
1041	kvfree(out);
1042	return ERR_PTR(err);
1043}
1044
1045static int mlx5_esw_host_functions_enabled_query(struct mlx5_eswitch *esw)
1046{
1047	const u32 *query_host_out;
1048
1049	if (!mlx5_core_is_ecpf_esw_manager(esw->dev))
1050		return 0;
1051
1052	query_host_out = mlx5_esw_query_functions(esw->dev);
1053	if (IS_ERR(query_host_out))
1054		return PTR_ERR(query_host_out);
1055
1056	esw->esw_funcs.host_funcs_disabled =
1057		MLX5_GET(query_esw_functions_out, query_host_out,
1058			 host_params_context.host_pf_not_exist);
1059
1060	kvfree(query_host_out);
1061	return 0;
1062}
1063
1064static void mlx5_eswitch_event_handler_register(struct mlx5_eswitch *esw)
1065{
1066	if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) {
1067		MLX5_NB_INIT(&esw->esw_funcs.nb, mlx5_esw_funcs_changed_handler,
1068			     ESW_FUNCTIONS_CHANGED);
1069		mlx5_eq_notifier_register(esw->dev, &esw->esw_funcs.nb);
1070	}
1071}
1072
1073static void mlx5_eswitch_event_handler_unregister(struct mlx5_eswitch *esw)
1074{
1075	if (esw->mode == MLX5_ESWITCH_OFFLOADS &&
1076	    mlx5_eswitch_is_funcs_handler(esw->dev)) {
1077		mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb);
1078		atomic_inc(&esw->esw_funcs.generation);
1079	}
1080}
1081
1082static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
1083{
1084	struct mlx5_vport *vport;
1085	unsigned long i;
1086
1087	mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
1088		mlx5_esw_qos_vport_qos_free(vport);
1089		memset(&vport->info, 0, sizeof(vport->info));
1090		vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
1091	}
1092}
1093
1094static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw)
1095{
1096	struct mlx5_vport *vport;
1097	unsigned long i;
1098
1099	mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) {
1100		mlx5_esw_qos_vport_qos_free(vport);
1101		memset(&vport->info, 0, sizeof(vport->info));
1102		vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
1103	}
1104}
1105
1106static int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
1107				   enum mlx5_eswitch_vport_event enabled_events)
1108{
1109	int err;
1110
1111	err = mlx5_esw_vport_enable(esw, vport, enabled_events);
1112	if (err)
1113		return err;
1114
1115	err = mlx5_esw_offloads_load_rep(esw, vport);
1116	if (err)
1117		goto err_rep;
1118
1119	return err;
1120
1121err_rep:
1122	mlx5_esw_vport_disable(esw, vport);
1123	return err;
1124}
1125
1126static void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
1127{
1128	mlx5_esw_offloads_unload_rep(esw, vport);
1129	mlx5_esw_vport_disable(esw, vport);
1130}
1131
1132static int mlx5_eswitch_load_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num,
1133					 enum mlx5_eswitch_vport_event enabled_events)
1134{
1135	struct mlx5_vport *vport;
1136	int err;
1137
1138	vport = mlx5_eswitch_get_vport(esw, vport_num);
1139	if (IS_ERR(vport))
1140		return PTR_ERR(vport);
1141
1142	err = mlx5_esw_offloads_init_pf_vf_rep(esw, vport);
1143	if (err)
1144		return err;
1145
1146	err = mlx5_eswitch_load_vport(esw, vport, enabled_events);
1147	if (err)
1148		goto err_load;
1149	return 0;
1150
1151err_load:
1152	mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport);
1153	return err;
1154}
1155
1156static void mlx5_eswitch_unload_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num)
1157{
1158	struct mlx5_vport *vport;
1159
1160	vport = mlx5_eswitch_get_vport(esw, vport_num);
1161	if (IS_ERR(vport))
1162		return;
1163
1164	mlx5_eswitch_unload_vport(esw, vport);
1165	mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport);
1166}
1167
1168int mlx5_eswitch_load_sf_vport(struct mlx5_eswitch *esw, u16 vport_num,
1169			       enum mlx5_eswitch_vport_event enabled_events,
1170			       struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum)
1171{
1172	struct mlx5_vport *vport;
1173	int err;
1174
1175	vport = mlx5_eswitch_get_vport(esw, vport_num);
1176	if (IS_ERR(vport))
1177		return PTR_ERR(vport);
1178
1179	err = mlx5_esw_offloads_init_sf_rep(esw, vport, dl_port, controller, sfnum);
1180	if (err)
1181		return err;
1182
1183	err = mlx5_eswitch_load_vport(esw, vport, enabled_events);
1184	if (err)
1185		goto err_load;
1186
1187	return 0;
1188
1189err_load:
1190	mlx5_esw_offloads_cleanup_sf_rep(esw, vport);
1191	return err;
1192}
1193
1194void mlx5_eswitch_unload_sf_vport(struct mlx5_eswitch *esw, u16 vport_num)
1195{
1196	struct mlx5_vport *vport;
1197
1198	vport = mlx5_eswitch_get_vport(esw, vport_num);
1199	if (IS_ERR(vport))
1200		return;
1201
1202	mlx5_eswitch_unload_vport(esw, vport);
1203	mlx5_esw_offloads_cleanup_sf_rep(esw, vport);
1204}
1205
1206void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs)
1207{
1208	struct mlx5_vport *vport;
1209	unsigned long i;
1210
1211	mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) {
1212		/* Adjacent VFs are unloaded separately */
1213		if (!vport->enabled || vport->adjacent)
1214			continue;
1215		mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport);
1216	}
1217}
1218
1219static void mlx5_eswitch_unload_ec_vf_vports(struct mlx5_eswitch *esw,
1220					     u16 num_ec_vfs)
1221{
1222	struct mlx5_vport *vport;
1223	unsigned long i;
1224
1225	mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) {
1226		if (!vport->enabled)
1227			continue;
1228		mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport);
1229	}
1230}
1231
1232static void mlx5_eswitch_unload_adj_vf_vports(struct mlx5_eswitch *esw)
1233{
1234	struct mlx5_vport *vport;
1235	unsigned long i;
1236
1237	mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) {
1238		if (!vport->enabled || !vport->adjacent)
1239			continue;
1240		mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport);
1241	}
1242}
1243
1244static int
1245mlx5_eswitch_load_adj_vf_vports(struct mlx5_eswitch *esw,
1246				enum mlx5_eswitch_vport_event enabled_events)
1247{
1248	struct mlx5_vport *vport;
1249	unsigned long i;
1250	int err;
1251
1252	mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) {
1253		if (!vport->adjacent)
1254			continue;
1255		err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport,
1256						    enabled_events);
1257		if (err)
1258			goto unload_adj_vf_vport;
1259	}
1260
1261	return 0;
1262
1263unload_adj_vf_vport:
1264	mlx5_eswitch_unload_adj_vf_vports(esw);
1265	return err;
1266}
1267
1268int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs,
1269				enum mlx5_eswitch_vport_event enabled_events)
1270{
1271	struct mlx5_vport *vport;
1272	unsigned long i;
1273	int err;
1274
1275	mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) {
1276		err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events);
1277		if (err)
1278			goto vf_err;
1279	}
1280
1281	return 0;
1282
1283vf_err:
1284	mlx5_eswitch_unload_vf_vports(esw, num_vfs);
1285	return err;
1286}
1287
1288static int mlx5_eswitch_load_ec_vf_vports(struct mlx5_eswitch *esw, u16 num_ec_vfs,
1289					  enum mlx5_eswitch_vport_event enabled_events)
1290{
1291	struct mlx5_vport *vport;
1292	unsigned long i;
1293	int err;
1294
1295	mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) {
1296		err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events);
1297		if (err)
1298			goto vf_err;
1299	}
1300
1301	return 0;
1302
1303vf_err:
1304	mlx5_eswitch_unload_ec_vf_vports(esw, num_ec_vfs);
1305	return err;
1306}
1307
1308static int host_pf_enable_hca(struct mlx5_core_dev *dev)
1309{
1310	if (!mlx5_core_is_ecpf(dev))
1311		return 0;
1312
1313	/* Once vport and representor are ready, take out the external host PF
1314	 * out of initializing state. Enabling HCA clears the iser->initializing
1315	 * bit and host PF driver loading can progress.
1316	 */
1317	return mlx5_cmd_host_pf_enable_hca(dev);
1318}
1319
1320static void host_pf_disable_hca(struct mlx5_core_dev *dev)
1321{
1322	if (!mlx5_core_is_ecpf(dev))
1323		return;
1324
1325	mlx5_cmd_host_pf_disable_hca(dev);
1326}
1327
1328/* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs
1329 * whichever are present on the eswitch.
1330 */
1331int
1332mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
1333				 enum mlx5_eswitch_vport_event enabled_events)
1334{
1335	bool pf_needed;
1336	int ret;
1337
1338	pf_needed = mlx5_core_is_ecpf_esw_manager(esw->dev) ||
1339		    esw->mode == MLX5_ESWITCH_LEGACY;
1340
1341	/* Enable PF vport */
1342	if (pf_needed && mlx5_esw_host_functions_enabled(esw->dev)) {
1343		ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_PF,
1344						    enabled_events);
1345		if (ret)
1346			return ret;
1347	}
1348
1349	if (mlx5_esw_host_functions_enabled(esw->dev)) {
1350		/* Enable external host PF HCA */
1351		ret = host_pf_enable_hca(esw->dev);
1352		if (ret)
1353			goto pf_hca_err;
1354	}
1355
1356	/* Enable ECPF vport */
1357	if (mlx5_ecpf_vport_exists(esw->dev)) {
1358		ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_ECPF, enabled_events);
1359		if (ret)
1360			goto ecpf_err;
1361	}
1362
1363	/* Enable ECVF vports */
1364	if (mlx5_core_ec_sriov_enabled(esw->dev)) {
1365		ret = mlx5_eswitch_load_ec_vf_vports(esw,
1366						     esw->esw_funcs.num_ec_vfs,
1367						     enabled_events);
1368		if (ret)
1369			goto ec_vf_err;
1370	}
1371
1372	/* Enable VF vports */
1373	ret = mlx5_eswitch_load_vf_vports(esw, esw->esw_funcs.num_vfs,
1374					  enabled_events);
1375	if (ret)
1376		goto vf_err;
1377
1378	/* Enable adjacent VF vports */
1379	ret = mlx5_eswitch_load_adj_vf_vports(esw, enabled_events);
1380	if (ret)
1381		goto unload_vf_vports;
1382
1383	return 0;
1384
1385unload_vf_vports:
1386	mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
1387vf_err:
1388	if (mlx5_core_ec_sriov_enabled(esw->dev))
1389		mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs);
1390ec_vf_err:
1391	if (mlx5_ecpf_vport_exists(esw->dev))
1392		mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF);
1393ecpf_err:
1394	if (mlx5_esw_host_functions_enabled(esw->dev))
1395		host_pf_disable_hca(esw->dev);
1396pf_hca_err:
1397	if (pf_needed && mlx5_esw_host_functions_enabled(esw->dev))
1398		mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_PF);
1399	return ret;
1400}
1401
1402/* mlx5_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs
1403 * whichever are previously enabled on the eswitch.
1404 */
1405void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw)
1406{
1407	mlx5_eswitch_unload_adj_vf_vports(esw);
1408
1409	mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
1410
1411	if (mlx5_core_ec_sriov_enabled(esw->dev))
1412		mlx5_eswitch_unload_ec_vf_vports(esw,
1413						 esw->esw_funcs.num_ec_vfs);
1414
1415	if (mlx5_ecpf_vport_exists(esw->dev)) {
1416		mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF);
1417	}
1418
1419	if (mlx5_esw_host_functions_enabled(esw->dev))
1420		host_pf_disable_hca(esw->dev);
1421
1422	if ((mlx5_core_is_ecpf_esw_manager(esw->dev) ||
1423	     esw->mode == MLX5_ESWITCH_LEGACY) &&
1424	    mlx5_esw_host_functions_enabled(esw->dev))
1425		mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_PF);
1426}
1427
1428static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw)
1429{
1430	struct devlink *devlink = priv_to_devlink(esw->dev);
1431	union devlink_param_value val;
1432	int err;
1433
1434	err = devl_param_driverinit_value_get(devlink,
1435					      MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
1436					      &val);
1437	if (!err) {
1438		esw->params.large_group_num = val.vu32;
1439	} else {
1440		esw_warn(esw->dev,
1441			 "Devlink can't get param fdb_large_groups, uses default (%d).\n",
1442			 ESW_OFFLOADS_DEFAULT_NUM_GROUPS);
1443		esw->params.large_group_num = ESW_OFFLOADS_DEFAULT_NUM_GROUPS;
1444	}
1445}
1446
1447static void
1448mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs)
1449{
1450	const u32 *out;
1451
1452	if (num_vfs < 0)
1453		return;
1454
1455	if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1456		esw->esw_funcs.num_vfs = num_vfs;
1457		return;
1458	}
1459
1460	out = mlx5_esw_query_functions(esw->dev);
1461	if (IS_ERR(out))
1462		return;
1463
1464	esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out,
1465					  host_params_context.host_num_of_vfs);
1466	if (mlx5_core_ec_sriov_enabled(esw->dev))
1467		esw->esw_funcs.num_ec_vfs = num_vfs;
1468
1469	kvfree(out);
1470}
1471
1472static void mlx5_esw_mode_change_notify(struct mlx5_eswitch *esw, u16 mode)
1473{
1474	struct mlx5_esw_event_info info = {};
1475
1476	info.new_mode = mode;
1477
1478	blocking_notifier_call_chain(&esw->dev->priv.esw_n_head, 0, &info);
1479}
1480
1481static int mlx5_esw_egress_acls_init(struct mlx5_core_dev *dev)
1482{
1483	struct mlx5_flow_steering *steering = dev->priv.steering;
1484	int total_vports = mlx5_eswitch_get_total_vports(dev);
1485	int err;
1486	int i;
1487
1488	for (i = 0; i < total_vports; i++) {
1489		err = mlx5_fs_vport_egress_acl_ns_add(steering, i);
1490		if (err)
1491			goto acl_ns_remove;
1492	}
1493	return 0;
1494
1495acl_ns_remove:
1496	while (i--)
1497		mlx5_fs_vport_egress_acl_ns_remove(steering, i);
1498	return err;
1499}
1500
1501static void mlx5_esw_egress_acls_cleanup(struct mlx5_core_dev *dev)
1502{
1503	struct mlx5_flow_steering *steering = dev->priv.steering;
1504	int total_vports = mlx5_eswitch_get_total_vports(dev);
1505	int i;
1506
1507	for (i = total_vports - 1; i >= 0; i--)
1508		mlx5_fs_vport_egress_acl_ns_remove(steering, i);
1509}
1510
1511static int mlx5_esw_ingress_acls_init(struct mlx5_core_dev *dev)
1512{
1513	struct mlx5_flow_steering *steering = dev->priv.steering;
1514	int total_vports = mlx5_eswitch_get_total_vports(dev);
1515	int err;
1516	int i;
1517
1518	for (i = 0; i < total_vports; i++) {
1519		err = mlx5_fs_vport_ingress_acl_ns_add(steering, i);
1520		if (err)
1521			goto acl_ns_remove;
1522	}
1523	return 0;
1524
1525acl_ns_remove:
1526	while (i--)
1527		mlx5_fs_vport_ingress_acl_ns_remove(steering, i);
1528	return err;
1529}
1530
1531static void mlx5_esw_ingress_acls_cleanup(struct mlx5_core_dev *dev)
1532{
1533	struct mlx5_flow_steering *steering = dev->priv.steering;
1534	int total_vports = mlx5_eswitch_get_total_vports(dev);
1535	int i;
1536
1537	for (i = total_vports - 1; i >= 0; i--)
1538		mlx5_fs_vport_ingress_acl_ns_remove(steering, i);
1539}
1540
1541static int mlx5_esw_acls_ns_init(struct mlx5_eswitch *esw)
1542{
1543	struct mlx5_core_dev *dev = esw->dev;
1544	int err;
1545
1546	if (esw->flags & MLX5_ESWITCH_VPORT_ACL_NS_CREATED)
1547		return 0;
1548
1549	if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
1550		err = mlx5_esw_egress_acls_init(dev);
1551		if (err)
1552			return err;
1553	} else {
1554		esw_warn(dev, "egress ACL is not supported by FW\n");
1555	}
1556
1557	if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
1558		err = mlx5_esw_ingress_acls_init(dev);
1559		if (err)
1560			goto err;
1561	} else {
1562		esw_warn(dev, "ingress ACL is not supported by FW\n");
1563	}
1564	esw->flags |= MLX5_ESWITCH_VPORT_ACL_NS_CREATED;
1565	return 0;
1566
1567err:
1568	if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
1569		mlx5_esw_egress_acls_cleanup(dev);
1570	return err;
1571}
1572
1573static void mlx5_esw_acls_ns_cleanup(struct mlx5_eswitch *esw)
1574{
1575	struct mlx5_core_dev *dev = esw->dev;
1576
1577	esw->flags &= ~MLX5_ESWITCH_VPORT_ACL_NS_CREATED;
1578	if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support))
1579		mlx5_esw_ingress_acls_cleanup(dev);
1580	if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
1581		mlx5_esw_egress_acls_cleanup(dev);
1582}
1583
1584/**
1585 * mlx5_eswitch_enable_locked - Enable eswitch
1586 * @esw:	Pointer to eswitch
1587 * @num_vfs:	Enable eswitch for given number of VFs. This is optional.
1588 *		Valid value are 0, > 0 and MLX5_ESWITCH_IGNORE_NUM_VFS.
1589 *		Caller should pass num_vfs > 0 when enabling eswitch for
1590 *		vf vports. Caller should pass num_vfs = 0, when eswitch
1591 *		is enabled without sriov VFs or when caller
1592 *		is unaware of the sriov state of the host PF on ECPF based
1593 *		eswitch. Caller should pass < 0 when num_vfs should be
1594 *		completely ignored. This is typically the case when eswitch
1595 *		is enabled without sriov regardless of PF/ECPF system.
1596 * mlx5_eswitch_enable_locked() Enables eswitch in either legacy or offloads
1597 * mode. If num_vfs >=0 is provided, it setup VF related eswitch vports.
1598 * It returns 0 on success or error code on failure.
1599 */
1600int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs)
1601{
1602	int err;
1603
1604	devl_assert_locked(priv_to_devlink(esw->dev));
1605
1606	if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
1607		esw_warn(esw->dev, "FDB is not supported, aborting ...\n");
1608		return -EOPNOTSUPP;
1609	}
1610
1611	mlx5_eswitch_get_devlink_param(esw);
1612
1613	err = mlx5_esw_acls_ns_init(esw);
1614	if (err)
1615		return err;
1616
1617	mlx5_eswitch_update_num_of_vfs(esw, num_vfs);
1618
1619	MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE);
1620	mlx5_eq_notifier_register(esw->dev, &esw->nb);
1621
1622	err = mlx5_esw_qos_init(esw);
1623	if (err)
1624		goto err_esw_init;
1625
1626	if (esw->mode == MLX5_ESWITCH_LEGACY) {
1627		err = esw_legacy_enable(esw);
1628	} else {
1629		err = esw_offloads_enable(esw);
1630	}
1631
1632	if (err)
1633		goto err_esw_init;
1634
1635	esw->fdb_table.flags |= MLX5_ESW_FDB_CREATED;
1636
1637	mlx5_eswitch_event_handler_register(esw);
1638
1639	esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n",
1640		 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
1641		 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports);
1642
1643	mlx5_esw_mode_change_notify(esw, esw->mode);
1644
1645	return 0;
1646
1647err_esw_init:
1648	mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
1649	mlx5_esw_acls_ns_cleanup(esw);
1650	return err;
1651}
1652
1653/**
1654 * mlx5_eswitch_enable - Enable eswitch
1655 * @esw:	Pointer to eswitch
1656 * @num_vfs:	Enable eswitch switch for given number of VFs.
1657 *		Caller must pass num_vfs > 0 when enabling eswitch for
1658 *		vf vports.
1659 * mlx5_eswitch_enable() returns 0 on success or error code on failure.
1660 */
1661int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
1662{
1663	bool toggle_lag;
1664	int ret = 0;
1665
1666	if (!mlx5_esw_allowed(esw))
1667		return 0;
1668
1669	devl_assert_locked(priv_to_devlink(esw->dev));
1670
1671	toggle_lag = !mlx5_esw_is_fdb_created(esw);
1672
1673	if (toggle_lag)
1674		mlx5_lag_disable_change(esw->dev);
1675
1676	if (!mlx5_esw_is_fdb_created(esw)) {
1677		ret = mlx5_eswitch_enable_locked(esw, num_vfs);
1678	} else {
1679		enum mlx5_eswitch_vport_event vport_events;
1680
1681		vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ?
1682					MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE;
1683		/* If this is the ECPF the number of host VFs is managed via the
1684		 * eswitch function change event handler, and any num_vfs provided
1685		 * here are intended to be EC VFs.
1686		 */
1687		if (!mlx5_core_is_ecpf(esw->dev)) {
1688			ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events);
1689			if (!ret)
1690				esw->esw_funcs.num_vfs = num_vfs;
1691		} else if (mlx5_core_ec_sriov_enabled(esw->dev)) {
1692			ret = mlx5_eswitch_load_ec_vf_vports(esw, num_vfs, vport_events);
1693			if (!ret)
1694				esw->esw_funcs.num_ec_vfs = num_vfs;
1695		}
1696	}
1697
1698	if (toggle_lag)
1699		mlx5_lag_enable_change(esw->dev);
1700
1701	return ret;
1702}
1703
1704/* When disabling sriov, free driver level resources. */
1705void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
1706{
1707	if (!mlx5_esw_allowed(esw))
1708		return;
1709
1710	devl_assert_locked(priv_to_devlink(esw->dev));
1711	/* If driver is unloaded, this function is called twice by remove_one()
1712	 * and mlx5_unload(). Prevent the second call.
1713	 */
1714	if (!esw->esw_funcs.num_vfs && !esw->esw_funcs.num_ec_vfs && !clear_vf)
1715		return;
1716
1717	esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n",
1718		 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
1719		 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports);
1720
1721	if (!mlx5_core_is_ecpf(esw->dev)) {
1722		mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
1723		if (clear_vf)
1724			mlx5_eswitch_clear_vf_vports_info(esw);
1725	} else if (mlx5_core_ec_sriov_enabled(esw->dev)) {
1726		mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs);
1727		if (clear_vf)
1728			mlx5_eswitch_clear_ec_vf_vports_info(esw);
1729	}
1730
1731	if (esw->mode == MLX5_ESWITCH_OFFLOADS) {
1732		struct devlink *devlink = priv_to_devlink(esw->dev);
1733
1734		devl_rate_nodes_destroy(devlink);
1735	}
1736	/* Destroy legacy fdb when disabling sriov in legacy mode. */
1737	if (esw->mode == MLX5_ESWITCH_LEGACY)
1738		mlx5_eswitch_disable_locked(esw);
1739
1740	if (!mlx5_core_is_ecpf(esw->dev))
1741		esw->esw_funcs.num_vfs = 0;
1742	else
1743		esw->esw_funcs.num_ec_vfs = 0;
1744}
1745
1746/* Free resources for corresponding eswitch mode. It is called by devlink
1747 * when changing eswitch mode or modprobe when unloading driver.
1748 */
1749void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw)
1750{
1751	struct devlink *devlink = priv_to_devlink(esw->dev);
1752
1753	/* Notify eswitch users that it is exiting from current mode.
1754	 * So that it can do necessary cleanup before the eswitch is disabled.
1755	 */
1756	mlx5_esw_mode_change_notify(esw, MLX5_ESWITCH_LEGACY);
1757
1758	mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
1759	mlx5_eswitch_event_handler_unregister(esw);
1760
1761	esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n",
1762		 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
1763		 esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports);
1764
1765	if (esw->fdb_table.flags & MLX5_ESW_FDB_CREATED) {
1766		esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED;
1767		if (esw->mode == MLX5_ESWITCH_OFFLOADS)
1768			esw_offloads_disable(esw);
1769		else if (esw->mode == MLX5_ESWITCH_LEGACY)
1770			esw_legacy_disable(esw);
1771		mlx5_esw_acls_ns_cleanup(esw);
1772	}
1773
1774	if (esw->mode == MLX5_ESWITCH_OFFLOADS)
1775		devl_rate_nodes_destroy(devlink);
1776}
1777
1778void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
1779{
1780	if (!mlx5_esw_allowed(esw))
1781		return;
1782
1783	devl_assert_locked(priv_to_devlink(esw->dev));
1784	mlx5_lag_disable_change(esw->dev);
1785	mlx5_eswitch_disable_locked(esw);
1786	esw->mode = MLX5_ESWITCH_LEGACY;
1787	mlx5_lag_enable_change(esw->dev);
1788}
1789
1790static int mlx5_query_hca_cap_host_pf(struct mlx5_core_dev *dev, void *out)
1791{
1792	u16 opmod = (MLX5_CAP_GENERAL << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01);
1793	u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {};
1794
1795	MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
1796	MLX5_SET(query_hca_cap_in, in, op_mod, opmod);
1797	MLX5_SET(query_hca_cap_in, in, function_id, MLX5_VPORT_PF);
1798	MLX5_SET(query_hca_cap_in, in, other_function, true);
1799	return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out);
1800}
1801
1802int mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev *dev, u16 *max_sfs, u16 *sf_base_id)
1803
1804{
1805	int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
1806	void *query_ctx;
1807	void *hca_caps;
1808	int err;
1809
1810	if (!mlx5_core_is_ecpf(dev) ||
1811	    !mlx5_esw_host_functions_enabled(dev)) {
1812		*max_sfs = 0;
1813		return 0;
1814	}
1815
1816	query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
1817	if (!query_ctx)
1818		return -ENOMEM;
1819
1820	err = mlx5_query_hca_cap_host_pf(dev, query_ctx);
1821	if (err)
1822		goto out_free;
1823
1824	hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
1825	*max_sfs = MLX5_GET(cmd_hca_cap, hca_caps, max_num_sf);
1826	*sf_base_id = MLX5_GET(cmd_hca_cap, hca_caps, sf_base_id);
1827
1828out_free:
1829	kfree(query_ctx);
1830	return err;
1831}
1832
1833int mlx5_esw_vport_alloc(struct mlx5_eswitch *esw, int index, u16 vport_num)
1834{
1835	struct mlx5_vport *vport;
1836	int err;
1837
1838	vport = kzalloc(sizeof(*vport), GFP_KERNEL);
1839	if (!vport)
1840		return -ENOMEM;
1841
1842	vport->dev = esw->dev;
1843	vport->vport = vport_num;
1844	vport->index = index;
1845	vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
1846	vport->vhca_id = MLX5_VHCA_ID_INVALID;
1847	INIT_WORK(&vport->vport_change_handler, esw_vport_change_handler);
1848	err = xa_insert(&esw->vports, vport_num, vport, GFP_KERNEL);
1849	if (err)
1850		goto insert_err;
1851
1852	esw->total_vports++;
1853	return 0;
1854
1855insert_err:
1856	kfree(vport);
1857	return err;
1858}
1859
1860void mlx5_esw_vport_free(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
1861{
1862	esw->total_vports--;
1863	xa_erase(&esw->vports, vport->vport);
1864	kfree(vport);
1865}
1866
1867static void mlx5_esw_vports_cleanup(struct mlx5_eswitch *esw)
1868{
1869	struct mlx5_vport *vport;
1870	unsigned long i;
1871
1872	mlx5_esw_for_each_vport(esw, i, vport)
1873		mlx5_esw_vport_free(esw, vport);
1874	xa_destroy(&esw->vports);
1875}
1876
1877static int mlx5_esw_vports_init(struct mlx5_eswitch *esw)
1878{
1879	struct mlx5_core_dev *dev = esw->dev;
1880	u16 max_host_pf_sfs;
1881	u16 base_sf_num;
1882	int idx = 0;
1883	int err;
1884	int i;
1885
1886	xa_init(&esw->vports);
1887
1888	if (mlx5_esw_host_functions_enabled(dev)) {
1889		err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_PF);
1890		if (err)
1891			goto err;
1892		if (esw->first_host_vport == MLX5_VPORT_PF)
1893			xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN);
1894		idx++;
1895		for (i = 0; i < mlx5_core_max_vfs(dev); i++) {
1896			err = mlx5_esw_vport_alloc(esw, idx, idx);
1897			if (err)
1898				goto err;
1899			xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_VF);
1900			xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN);
1901			idx++;
1902		}
1903	}
1904
1905	base_sf_num = mlx5_sf_start_function_id(dev);
1906	for (i = 0; i < mlx5_sf_max_functions(dev); i++) {
1907		err = mlx5_esw_vport_alloc(esw, idx, base_sf_num + i);
1908		if (err)
1909			goto err;
1910		xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF);
1911		idx++;
1912	}
1913
1914	err = mlx5_esw_sf_max_hpf_functions(dev, &max_host_pf_sfs, &base_sf_num);
1915	if (err)
1916		goto err;
1917	for (i = 0; i < max_host_pf_sfs; i++) {
1918		err = mlx5_esw_vport_alloc(esw, idx, base_sf_num + i);
1919		if (err)
1920			goto err;
1921		xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF);
1922		idx++;
1923	}
1924
1925	if (mlx5_core_ec_sriov_enabled(esw->dev)) {
1926		int ec_vf_base_num = mlx5_core_ec_vf_vport_base(dev);
1927
1928		for (i = 0; i < mlx5_core_max_ec_vfs(esw->dev); i++) {
1929			err = mlx5_esw_vport_alloc(esw, idx, ec_vf_base_num + i);
1930			if (err)
1931				goto err;
1932			idx++;
1933		}
1934	}
1935
1936	if (mlx5_ecpf_vport_exists(dev) ||
1937	    mlx5_core_is_ecpf_esw_manager(dev)) {
1938		err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_ECPF);
1939		if (err)
1940			goto err;
1941		idx++;
1942	}
1943	err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_UPLINK);
1944	if (err)
1945		goto err;
1946
1947	/* Adjacent vports or other dynamically create vports will use this */
1948	esw->last_vport_idx = ++idx;
1949	return 0;
1950
1951err:
1952	mlx5_esw_vports_cleanup(esw);
1953	return err;
1954}
1955
1956static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id,
1957					  struct devlink_param_gset_ctx *ctx,
1958					  struct netlink_ext_ack *extack)
1959{
1960	struct mlx5_core_dev *dev = devlink_priv(devlink);
1961
1962	if (!MLX5_ESWITCH_MANAGER(dev))
1963		return -EOPNOTSUPP;
1964
1965	if (ctx->val.vbool)
1966		return mlx5_lag_mpesw_enable(dev);
1967
1968	mlx5_lag_mpesw_disable(dev);
1969	return 0;
1970}
1971
1972static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id,
1973					  struct devlink_param_gset_ctx *ctx,
1974					  struct netlink_ext_ack *extack)
1975{
1976	struct mlx5_core_dev *dev = devlink_priv(devlink);
1977
1978	ctx->val.vbool = mlx5_lag_is_mpesw(dev);
1979	return 0;
1980}
1981
1982static const struct devlink_param mlx5_eswitch_params[] = {
1983	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT,
1984			     "esw_multiport", DEVLINK_PARAM_TYPE_BOOL,
1985			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
1986			     mlx5_devlink_esw_multiport_get,
1987			     mlx5_devlink_esw_multiport_set, NULL),
1988};
1989
1990int mlx5_eswitch_init(struct mlx5_core_dev *dev)
1991{
1992	struct mlx5_eswitch *esw;
1993	int err;
1994
1995	if (!MLX5_VPORT_MANAGER(dev) && !MLX5_ESWITCH_MANAGER(dev))
1996		return 0;
1997
1998	esw = kzalloc(sizeof(*esw), GFP_KERNEL);
1999	if (!esw)
2000		return -ENOMEM;
2001
2002	err = devl_params_register(priv_to_devlink(dev), mlx5_eswitch_params,
2003				   ARRAY_SIZE(mlx5_eswitch_params));
2004	if (err)
2005		goto free_esw;
2006
2007	esw->dev = dev;
2008	dev->priv.eswitch = esw;
2009	esw->manager_vport = mlx5_eswitch_manager_vport(dev);
2010	esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev);
2011
2012	esw->debugfs_root = debugfs_create_dir("esw", mlx5_debugfs_get_dev_root(dev));
2013	esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq");
2014	if (!esw->work_queue) {
2015		err = -ENOMEM;
2016		goto abort;
2017	}
2018
2019	err = mlx5_esw_host_functions_enabled_query(esw);
2020	if (err)
2021		goto abort;
2022
2023	err = mlx5_esw_vports_init(esw);
2024	if (err)
2025		goto abort;
2026
2027	err = esw_offloads_init(esw);
2028	if (err)
2029		goto reps_err;
2030
2031	esw->mode = MLX5_ESWITCH_LEGACY;
2032	err = mlx5_esw_qos_init(esw);
2033	if (err)
2034		goto reps_err;
2035
2036	mutex_init(&esw->offloads.encap_tbl_lock);
2037	hash_init(esw->offloads.encap_tbl);
2038	mutex_init(&esw->offloads.decap_tbl_lock);
2039	hash_init(esw->offloads.decap_tbl);
2040	mlx5e_mod_hdr_tbl_init(&esw->offloads.mod_hdr);
2041	atomic64_set(&esw->offloads.num_flows, 0);
2042	ida_init(&esw->offloads.vport_metadata_ida);
2043	xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC);
2044	mutex_init(&esw->state_lock);
2045	init_rwsem(&esw->mode_lock);
2046	refcount_set(&esw->qos.refcnt, 0);
2047
2048	esw->enabled_vports = 0;
2049	esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
2050	if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) &&
2051	    MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
2052		esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
2053	else
2054		esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
2055
2056	esw_info(dev,
2057		 "Total vports %d, per vport: max uc(%d) max mc(%d)\n",
2058		 esw->total_vports,
2059		 MLX5_MAX_UC_PER_VPORT(dev),
2060		 MLX5_MAX_MC_PER_VPORT(dev));
2061	return 0;
2062
2063reps_err:
2064	mlx5_esw_vports_cleanup(esw);
2065	dev->priv.eswitch = NULL;
2066abort:
2067	if (esw->work_queue)
2068		destroy_workqueue(esw->work_queue);
2069	debugfs_remove_recursive(esw->debugfs_root);
2070	devl_params_unregister(priv_to_devlink(dev), mlx5_eswitch_params,
2071			       ARRAY_SIZE(mlx5_eswitch_params));
2072free_esw:
2073	kfree(esw);
2074	return err;
2075}
2076
2077void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
2078{
2079	if (!esw)
2080		return;
2081
2082	esw_info(esw->dev, "cleanup\n");
2083
2084	mlx5_esw_qos_cleanup(esw);
2085	destroy_workqueue(esw->work_queue);
2086	WARN_ON(refcount_read(&esw->qos.refcnt));
2087	mutex_destroy(&esw->state_lock);
2088	WARN_ON(!xa_empty(&esw->offloads.vhca_map));
2089	xa_destroy(&esw->offloads.vhca_map);
2090	ida_destroy(&esw->offloads.vport_metadata_ida);
2091	mlx5e_mod_hdr_tbl_destroy(&esw->offloads.mod_hdr);
2092	mutex_destroy(&esw->offloads.encap_tbl_lock);
2093	mutex_destroy(&esw->offloads.decap_tbl_lock);
2094	esw_offloads_cleanup(esw);
2095	esw->dev->priv.eswitch = NULL;
2096	mlx5_esw_vports_cleanup(esw);
2097	debugfs_remove_recursive(esw->debugfs_root);
2098	devl_params_unregister(priv_to_devlink(esw->dev), mlx5_eswitch_params,
2099			       ARRAY_SIZE(mlx5_eswitch_params));
2100	kfree(esw);
2101}
2102
2103/* Vport Administration */
2104static int
2105mlx5_esw_set_vport_mac_locked(struct mlx5_eswitch *esw,
2106			      struct mlx5_vport *evport, const u8 *mac)
2107{
2108	u16 vport_num = evport->vport;
2109	u64 node_guid;
2110	int err = 0;
2111
2112	if (is_multicast_ether_addr(mac))
2113		return -EINVAL;
2114
2115	if (evport->info.spoofchk && !is_valid_ether_addr(mac))
2116		mlx5_core_warn(esw->dev,
2117			       "Set invalid MAC while spoofchk is on, vport(%d)\n",
2118			       vport_num);
2119
2120	err = mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, mac);
2121	if (err) {
2122		mlx5_core_warn(esw->dev,
2123			       "Failed to mlx5_modify_nic_vport_mac vport(%d) err=(%d)\n",
2124			       vport_num, err);
2125		return err;
2126	}
2127
2128	node_guid_gen_from_mac(&node_guid, mac);
2129	err = mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, node_guid);
2130	if (err)
2131		mlx5_core_warn(esw->dev,
2132			       "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n",
2133			       vport_num, err);
2134
2135	ether_addr_copy(evport->info.mac, mac);
2136	evport->info.node_guid = node_guid;
2137	if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
2138		err = esw_acl_ingress_lgcy_setup(esw, evport);
2139
2140	return err;
2141}
2142
2143int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
2144			       u16 vport, const u8 *mac)
2145{
2146	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2147	int err = 0;
2148
2149	if (IS_ERR(evport))
2150		return PTR_ERR(evport);
2151
2152	mutex_lock(&esw->state_lock);
2153	err = mlx5_esw_set_vport_mac_locked(esw, evport, mac);
2154	mutex_unlock(&esw->state_lock);
2155	return err;
2156}
2157
2158static bool mlx5_esw_check_port_type(struct mlx5_eswitch *esw, u16 vport_num, xa_mark_t mark)
2159{
2160	return xa_get_mark(&esw->vports, vport_num, mark);
2161}
2162
2163bool mlx5_eswitch_is_vf_vport(struct mlx5_eswitch *esw, u16 vport_num)
2164{
2165	return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_VF);
2166}
2167
2168bool mlx5_eswitch_is_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num)
2169{
2170	return vport_num == MLX5_VPORT_PF ||
2171		mlx5_eswitch_is_vf_vport(esw, vport_num);
2172}
2173
2174bool mlx5_esw_is_sf_vport(struct mlx5_eswitch *esw, u16 vport_num)
2175{
2176	return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_SF);
2177}
2178
2179int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
2180				 u16 vport, int link_state)
2181{
2182	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2183	int opmod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT;
2184	int other_vport = 1;
2185	int err = 0;
2186
2187	if (!mlx5_esw_allowed(esw))
2188		return -EPERM;
2189	if (IS_ERR(evport))
2190		return PTR_ERR(evport);
2191
2192	if (vport == MLX5_VPORT_UPLINK) {
2193		opmod = MLX5_VPORT_STATE_OP_MOD_UPLINK;
2194		other_vport = 0;
2195		vport = 0;
2196	}
2197	mutex_lock(&esw->state_lock);
2198	if (esw->mode != MLX5_ESWITCH_LEGACY) {
2199		err = -EOPNOTSUPP;
2200		goto unlock;
2201	}
2202
2203	err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, other_vport, link_state);
2204	if (err) {
2205		mlx5_core_warn(esw->dev, "Failed to set vport %d link state, opmod = %d, err = %d",
2206			       vport, opmod, err);
2207		goto unlock;
2208	}
2209
2210	evport->info.link_state = link_state;
2211
2212unlock:
2213	mutex_unlock(&esw->state_lock);
2214	return err;
2215}
2216
2217int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
2218				  u16 vport, struct ifla_vf_info *ivi)
2219{
2220	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2221	u32 max_rate, min_rate;
2222
2223	if (IS_ERR(evport))
2224		return PTR_ERR(evport);
2225
2226	memset(ivi, 0, sizeof(*ivi));
2227	ivi->vf = vport - 1;
2228
2229	mutex_lock(&esw->state_lock);
2230
2231	mlx5_query_nic_vport_mac_address(esw->dev, vport, true,
2232					 evport->info.mac);
2233	ether_addr_copy(ivi->mac, evport->info.mac);
2234	ivi->linkstate = evport->info.link_state;
2235	ivi->vlan = evport->info.vlan;
2236	ivi->qos = evport->info.qos;
2237	ivi->spoofchk = evport->info.spoofchk;
2238	ivi->trusted = evport->info.trusted;
2239
2240	if (mlx5_esw_qos_get_vport_rate(evport, &max_rate, &min_rate)) {
2241		ivi->max_tx_rate = max_rate;
2242		ivi->min_tx_rate = min_rate;
2243	}
2244	mutex_unlock(&esw->state_lock);
2245
2246	return 0;
2247}
2248
2249int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
2250				  u16 vport, u16 vlan, u8 qos, u8 set_flags)
2251{
2252	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2253	bool vst_mode_steering = esw_vst_mode_is_steering(esw);
2254	int err = 0;
2255
2256	if (IS_ERR(evport))
2257		return PTR_ERR(evport);
2258	if (vlan > 4095 || qos > 7)
2259		return -EINVAL;
2260
2261	if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering) {
2262		err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags);
2263		if (err)
2264			return err;
2265	}
2266
2267	evport->info.vlan = vlan;
2268	evport->info.qos = qos;
2269	if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) {
2270		err = esw_acl_ingress_lgcy_setup(esw, evport);
2271		if (err)
2272			return err;
2273		err = esw_acl_egress_lgcy_setup(esw, evport);
2274	}
2275
2276	return err;
2277}
2278
2279int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
2280				 u16 vport_num,
2281				 struct ifla_vf_stats *vf_stats)
2282{
2283	struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
2284	int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out);
2285	u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {};
2286	struct mlx5_vport_drop_stats stats = {};
2287	int err = 0;
2288	u32 *out;
2289
2290	if (IS_ERR(vport))
2291		return PTR_ERR(vport);
2292
2293	out = kvzalloc(outlen, GFP_KERNEL);
2294	if (!out)
2295		return -ENOMEM;
2296
2297	MLX5_SET(query_vport_counter_in, in, opcode,
2298		 MLX5_CMD_OP_QUERY_VPORT_COUNTER);
2299	MLX5_SET(query_vport_counter_in, in, op_mod, 0);
2300	MLX5_SET(query_vport_counter_in, in, vport_number, vport->vport);
2301	MLX5_SET(query_vport_counter_in, in, other_vport, 1);
2302
2303	err = mlx5_cmd_exec_inout(esw->dev, query_vport_counter, in, out);
2304	if (err)
2305		goto free_out;
2306
2307	#define MLX5_GET_CTR(p, x) \
2308		MLX5_GET64(query_vport_counter_out, p, x)
2309
2310	memset(vf_stats, 0, sizeof(*vf_stats));
2311	vf_stats->rx_packets =
2312		MLX5_GET_CTR(out, received_eth_unicast.packets) +
2313		MLX5_GET_CTR(out, received_ib_unicast.packets) +
2314		MLX5_GET_CTR(out, received_eth_multicast.packets) +
2315		MLX5_GET_CTR(out, received_ib_multicast.packets) +
2316		MLX5_GET_CTR(out, received_eth_broadcast.packets);
2317
2318	vf_stats->rx_bytes =
2319		MLX5_GET_CTR(out, received_eth_unicast.octets) +
2320		MLX5_GET_CTR(out, received_ib_unicast.octets) +
2321		MLX5_GET_CTR(out, received_eth_multicast.octets) +
2322		MLX5_GET_CTR(out, received_ib_multicast.octets) +
2323		MLX5_GET_CTR(out, received_eth_broadcast.octets);
2324
2325	vf_stats->tx_packets =
2326		MLX5_GET_CTR(out, transmitted_eth_unicast.packets) +
2327		MLX5_GET_CTR(out, transmitted_ib_unicast.packets) +
2328		MLX5_GET_CTR(out, transmitted_eth_multicast.packets) +
2329		MLX5_GET_CTR(out, transmitted_ib_multicast.packets) +
2330		MLX5_GET_CTR(out, transmitted_eth_broadcast.packets);
2331
2332	vf_stats->tx_bytes =
2333		MLX5_GET_CTR(out, transmitted_eth_unicast.octets) +
2334		MLX5_GET_CTR(out, transmitted_ib_unicast.octets) +
2335		MLX5_GET_CTR(out, transmitted_eth_multicast.octets) +
2336		MLX5_GET_CTR(out, transmitted_ib_multicast.octets) +
2337		MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
2338
2339	vf_stats->multicast =
2340		MLX5_GET_CTR(out, received_eth_multicast.packets) +
2341		MLX5_GET_CTR(out, received_ib_multicast.packets);
2342
2343	vf_stats->broadcast =
2344		MLX5_GET_CTR(out, received_eth_broadcast.packets);
2345
2346	err = mlx5_esw_query_vport_drop_stats(esw->dev, vport, &stats);
2347	if (err)
2348		goto free_out;
2349	vf_stats->rx_dropped = stats.rx_dropped;
2350	vf_stats->tx_dropped = stats.tx_dropped;
2351
2352free_out:
2353	kvfree(out);
2354	return err;
2355}
2356
2357u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev)
2358{
2359	struct mlx5_eswitch *esw = dev->priv.eswitch;
2360
2361	return mlx5_esw_allowed(esw) ? esw->mode : MLX5_ESWITCH_LEGACY;
2362}
2363EXPORT_SYMBOL_GPL(mlx5_eswitch_mode);
2364
2365enum devlink_eswitch_encap_mode
2366mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev)
2367{
2368	struct mlx5_eswitch *esw;
2369
2370	esw = dev->priv.eswitch;
2371	return (mlx5_eswitch_mode(dev) == MLX5_ESWITCH_OFFLOADS)  ? esw->offloads.encap :
2372		DEVLINK_ESWITCH_ENCAP_MODE_NONE;
2373}
2374EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);
2375
2376bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
2377			       struct mlx5_core_dev *dev1)
2378{
2379	return (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS &&
2380		dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS);
2381}
2382
2383int mlx5_esw_event_notifier_register(struct mlx5_core_dev *dev,
2384				     struct notifier_block *nb)
2385{
2386	return blocking_notifier_chain_register(&dev->priv.esw_n_head, nb);
2387}
2388
2389void mlx5_esw_event_notifier_unregister(struct mlx5_core_dev *dev,
2390					struct notifier_block *nb)
2391{
2392	blocking_notifier_chain_unregister(&dev->priv.esw_n_head, nb);
2393}
2394
2395/**
2396 * mlx5_esw_hold() - Try to take a read lock on esw mode lock.
2397 * @mdev: mlx5 core device.
2398 *
2399 * Should be called by esw resources callers.
2400 *
2401 * Return: true on success or false.
2402 */
2403bool mlx5_esw_hold(struct mlx5_core_dev *mdev)
2404{
2405	struct mlx5_eswitch *esw = mdev->priv.eswitch;
2406
2407	/* e.g. VF doesn't have eswitch so nothing to do */
2408	if (!mlx5_esw_allowed(esw))
2409		return true;
2410
2411	if (down_read_trylock(&esw->mode_lock) != 0) {
2412		if (esw->eswitch_operation_in_progress) {
2413			up_read(&esw->mode_lock);
2414			return false;
2415		}
2416		return true;
2417	}
2418
2419	return false;
2420}
2421
2422/**
2423 * mlx5_esw_release() - Release a read lock on esw mode lock.
2424 * @mdev: mlx5 core device.
2425 */
2426void mlx5_esw_release(struct mlx5_core_dev *mdev)
2427{
2428	struct mlx5_eswitch *esw = mdev->priv.eswitch;
2429
2430	if (mlx5_esw_allowed(esw))
2431		up_read(&esw->mode_lock);
2432}
2433
2434/**
2435 * mlx5_esw_get() - Increase esw user count.
2436 * @mdev: mlx5 core device.
2437 */
2438void mlx5_esw_get(struct mlx5_core_dev *mdev)
2439{
2440	struct mlx5_eswitch *esw = mdev->priv.eswitch;
2441
2442	if (mlx5_esw_allowed(esw))
2443		atomic64_inc(&esw->user_count);
2444}
2445
2446/**
2447 * mlx5_esw_put() - Decrease esw user count.
2448 * @mdev: mlx5 core device.
2449 */
2450void mlx5_esw_put(struct mlx5_core_dev *mdev)
2451{
2452	struct mlx5_eswitch *esw = mdev->priv.eswitch;
2453
2454	if (mlx5_esw_allowed(esw))
2455		atomic64_dec_if_positive(&esw->user_count);
2456}
2457
2458/**
2459 * mlx5_esw_try_lock() - Take a write lock on esw mode lock.
2460 * @esw: eswitch device.
2461 *
2462 * Should be called by esw mode change routine.
2463 *
2464 * Return:
2465 * * 0       - esw mode if successfully locked and refcount is 0.
2466 * * -EBUSY  - refcount is not 0.
2467 * * -EINVAL - In the middle of switching mode or lock is already held.
2468 */
2469int mlx5_esw_try_lock(struct mlx5_eswitch *esw)
2470{
2471	if (down_write_trylock(&esw->mode_lock) == 0)
2472		return -EINVAL;
2473
2474	if (esw->eswitch_operation_in_progress ||
2475	    atomic64_read(&esw->user_count) > 0) {
2476		up_write(&esw->mode_lock);
2477		return -EBUSY;
2478	}
2479
2480	return esw->mode;
2481}
2482
2483int mlx5_esw_lock(struct mlx5_eswitch *esw)
2484{
2485	down_write(&esw->mode_lock);
2486
2487	if (esw->eswitch_operation_in_progress) {
2488		up_write(&esw->mode_lock);
2489		return -EBUSY;
2490	}
2491
2492	return 0;
2493}
2494
2495/**
2496 * mlx5_esw_unlock() - Release write lock on esw mode lock
2497 * @esw: eswitch device.
2498 */
2499void mlx5_esw_unlock(struct mlx5_eswitch *esw)
2500{
2501	up_write(&esw->mode_lock);
2502}
2503
2504/**
2505 * mlx5_eswitch_get_total_vports - Get total vports of the eswitch
2506 *
2507 * @dev: Pointer to core device
2508 *
2509 * mlx5_eswitch_get_total_vports returns total number of eswitch vports.
2510 */
2511u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev)
2512{
2513	struct mlx5_eswitch *esw;
2514
2515	esw = dev->priv.eswitch;
2516	return mlx5_esw_allowed(esw) ? esw->total_vports : 0;
2517}
2518EXPORT_SYMBOL_GPL(mlx5_eswitch_get_total_vports);
2519
2520/**
2521 * mlx5_eswitch_get_core_dev - Get the mdev device
2522 * @esw : eswitch device.
2523 *
2524 * Return the mellanox core device which manages the eswitch.
2525 */
2526struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw)
2527{
2528	return mlx5_esw_allowed(esw) ? esw->dev : NULL;
2529}
2530EXPORT_SYMBOL(mlx5_eswitch_get_core_dev);
2531
2532bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev)
2533{
2534	struct mlx5_eswitch *esw = dev->priv.eswitch;
2535
2536	if (!mlx5_esw_allowed(esw))
2537		return true;
2538
2539	mutex_lock(&esw->state_lock);
2540	if (esw->enabled_ipsec_vf_count) {
2541		mutex_unlock(&esw->state_lock);
2542		return false;
2543	}
2544
2545	dev->num_ipsec_offloads++;
2546	mutex_unlock(&esw->state_lock);
2547	return true;
2548}
2549
2550void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev)
2551{
2552	struct mlx5_eswitch *esw = dev->priv.eswitch;
2553
2554	if (!mlx5_esw_allowed(esw))
2555		/* Failure means no eswitch => core dev is not a PF */
2556		return;
2557
2558	mutex_lock(&esw->state_lock);
2559	dev->num_ipsec_offloads--;
2560	mutex_unlock(&esw->state_lock);
2561}
2562
2563bool mlx5_esw_host_functions_enabled(const struct mlx5_core_dev *dev)
2564{
2565	if (!dev->priv.eswitch)
2566		return true;
2567
2568	return !dev->priv.eswitch->esw_funcs.host_funcs_disabled;
2569}
~/ Read-only file preview.