cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

eswitch.c (54100B)


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