Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2015, Mellanox Technologies. All rights reserved.
0003  *
0004  * This software is available to you under a choice of one of two
0005  * licenses.  You may choose to be licensed under the terms of the GNU
0006  * General Public License (GPL) Version 2, available from the file
0007  * COPYING in the main directory of this source tree, or the
0008  * OpenIB.org BSD license below:
0009  *
0010  *     Redistribution and use in source and binary forms, with or
0011  *     without modification, are permitted provided that the following
0012  *     conditions are met:
0013  *
0014  *      - Redistributions of source code must retain the above
0015  *        copyright notice, this list of conditions and the following
0016  *        disclaimer.
0017  *
0018  *      - Redistributions in binary form must reproduce the above
0019  *        copyright notice, this list of conditions and the following
0020  *        disclaimer in the documentation and/or other materials
0021  *        provided with the distribution.
0022  *
0023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0024  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0025  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0026  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0027  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0028  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0029  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0030  * SOFTWARE.
0031  */
0032 
0033 #include <linux/etherdevice.h>
0034 #include <linux/mlx5/driver.h>
0035 #include <linux/mlx5/mlx5_ifc.h>
0036 #include <linux/mlx5/vport.h>
0037 #include <linux/mlx5/fs.h>
0038 #include <linux/mlx5/mpfs.h>
0039 #include <linux/debugfs.h>
0040 #include "esw/acl/lgcy.h"
0041 #include "esw/legacy.h"
0042 #include "esw/qos.h"
0043 #include "mlx5_core.h"
0044 #include "lib/eq.h"
0045 #include "eswitch.h"
0046 #include "fs_core.h"
0047 #include "devlink.h"
0048 #include "ecpf.h"
0049 #include "en/mod_hdr.h"
0050 
0051 enum {
0052     MLX5_ACTION_NONE = 0,
0053     MLX5_ACTION_ADD  = 1,
0054     MLX5_ACTION_DEL  = 2,
0055 };
0056 
0057 /* Vport UC/MC hash node */
0058 struct vport_addr {
0059     struct l2addr_node     node;
0060     u8                     action;
0061     u16                    vport;
0062     struct mlx5_flow_handle *flow_rule;
0063     bool mpfs; /* UC MAC was added to MPFs */
0064     /* A flag indicating that mac was added due to mc promiscuous vport */
0065     bool mc_promisc;
0066 };
0067 
0068 static int mlx5_eswitch_check(const struct mlx5_core_dev *dev)
0069 {
0070     if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
0071         return -EOPNOTSUPP;
0072 
0073     if (!MLX5_ESWITCH_MANAGER(dev))
0074         return -EOPNOTSUPP;
0075 
0076     return 0;
0077 }
0078 
0079 struct mlx5_eswitch *mlx5_devlink_eswitch_get(struct devlink *devlink)
0080 {
0081     struct mlx5_core_dev *dev = devlink_priv(devlink);
0082     int err;
0083 
0084     err = mlx5_eswitch_check(dev);
0085     if (err)
0086         return ERR_PTR(err);
0087 
0088     return dev->priv.eswitch;
0089 }
0090 
0091 struct mlx5_vport *__must_check
0092 mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num)
0093 {
0094     struct mlx5_vport *vport;
0095 
0096     if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager))
0097         return ERR_PTR(-EPERM);
0098 
0099     vport = xa_load(&esw->vports, vport_num);
0100     if (!vport) {
0101         esw_debug(esw->dev, "vport out of range: num(0x%x)\n", vport_num);
0102         return ERR_PTR(-EINVAL);
0103     }
0104     return vport;
0105 }
0106 
0107 static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport,
0108                     u32 events_mask)
0109 {
0110     u32 in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)] = {};
0111     void *nic_vport_ctx;
0112 
0113     MLX5_SET(modify_nic_vport_context_in, in,
0114          opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
0115     MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1);
0116     MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
0117     MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
0118     nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
0119                      in, nic_vport_context);
0120 
0121     MLX5_SET(nic_vport_context, nic_vport_ctx, arm_change_event, 1);
0122 
0123     if (events_mask & MLX5_VPORT_UC_ADDR_CHANGE)
0124         MLX5_SET(nic_vport_context, nic_vport_ctx,
0125              event_on_uc_address_change, 1);
0126     if (events_mask & MLX5_VPORT_MC_ADDR_CHANGE)
0127         MLX5_SET(nic_vport_context, nic_vport_ctx,
0128              event_on_mc_address_change, 1);
0129     if (events_mask & MLX5_VPORT_PROMISC_CHANGE)
0130         MLX5_SET(nic_vport_context, nic_vport_ctx,
0131              event_on_promisc_change, 1);
0132 
0133     return mlx5_cmd_exec_in(dev, modify_nic_vport_context, in);
0134 }
0135 
0136 /* E-Switch vport context HW commands */
0137 int mlx5_eswitch_modify_esw_vport_context(struct mlx5_core_dev *dev, u16 vport,
0138                       bool other_vport, void *in)
0139 {
0140     MLX5_SET(modify_esw_vport_context_in, in, opcode,
0141          MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT);
0142     MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport);
0143     MLX5_SET(modify_esw_vport_context_in, in, other_vport, other_vport);
0144     return mlx5_cmd_exec_in(dev, modify_esw_vport_context, in);
0145 }
0146 
0147 static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u16 vport,
0148                   u16 vlan, u8 qos, u8 set_flags)
0149 {
0150     u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {};
0151 
0152     if (!MLX5_CAP_ESW(dev, vport_cvlan_strip) ||
0153         !MLX5_CAP_ESW(dev, vport_cvlan_insert_if_not_exist))
0154         return -EOPNOTSUPP;
0155 
0156     esw_debug(dev, "Set Vport[%d] VLAN %d qos %d set=%x\n",
0157           vport, vlan, qos, set_flags);
0158 
0159     if (set_flags & SET_VLAN_STRIP)
0160         MLX5_SET(modify_esw_vport_context_in, in,
0161              esw_vport_context.vport_cvlan_strip, 1);
0162 
0163     if (set_flags & SET_VLAN_INSERT) {
0164         /* insert only if no vlan in packet */
0165         MLX5_SET(modify_esw_vport_context_in, in,
0166              esw_vport_context.vport_cvlan_insert, 1);
0167 
0168         MLX5_SET(modify_esw_vport_context_in, in,
0169              esw_vport_context.cvlan_pcp, qos);
0170         MLX5_SET(modify_esw_vport_context_in, in,
0171              esw_vport_context.cvlan_id, vlan);
0172     }
0173 
0174     MLX5_SET(modify_esw_vport_context_in, in,
0175          field_select.vport_cvlan_strip, 1);
0176     MLX5_SET(modify_esw_vport_context_in, in,
0177          field_select.vport_cvlan_insert, 1);
0178 
0179     return mlx5_eswitch_modify_esw_vport_context(dev, vport, true, in);
0180 }
0181 
0182 /* E-Switch FDB */
0183 static struct mlx5_flow_handle *
0184 __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u16 vport, bool rx_rule,
0185              u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN])
0186 {
0187     int match_header = (is_zero_ether_addr(mac_c) ? 0 :
0188                 MLX5_MATCH_OUTER_HEADERS);
0189     struct mlx5_flow_handle *flow_rule = NULL;
0190     struct mlx5_flow_act flow_act = {0};
0191     struct mlx5_flow_destination dest = {};
0192     struct mlx5_flow_spec *spec;
0193     void *mv_misc = NULL;
0194     void *mc_misc = NULL;
0195     u8 *dmac_v = NULL;
0196     u8 *dmac_c = NULL;
0197 
0198     if (rx_rule)
0199         match_header |= MLX5_MATCH_MISC_PARAMETERS;
0200 
0201     spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
0202     if (!spec)
0203         return NULL;
0204 
0205     dmac_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
0206                   outer_headers.dmac_47_16);
0207     dmac_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
0208                   outer_headers.dmac_47_16);
0209 
0210     if (match_header & MLX5_MATCH_OUTER_HEADERS) {
0211         ether_addr_copy(dmac_v, mac_v);
0212         ether_addr_copy(dmac_c, mac_c);
0213     }
0214 
0215     if (match_header & MLX5_MATCH_MISC_PARAMETERS) {
0216         mv_misc  = MLX5_ADDR_OF(fte_match_param, spec->match_value,
0217                     misc_parameters);
0218         mc_misc  = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
0219                     misc_parameters);
0220         MLX5_SET(fte_match_set_misc, mv_misc, source_port, MLX5_VPORT_UPLINK);
0221         MLX5_SET_TO_ONES(fte_match_set_misc, mc_misc, source_port);
0222     }
0223 
0224     dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
0225     dest.vport.num = vport;
0226 
0227     esw_debug(esw->dev,
0228           "\tFDB add rule dmac_v(%pM) dmac_c(%pM) -> vport(%d)\n",
0229           dmac_v, dmac_c, vport);
0230     spec->match_criteria_enable = match_header;
0231     flow_act.action =  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
0232     flow_rule =
0233         mlx5_add_flow_rules(esw->fdb_table.legacy.fdb, spec,
0234                     &flow_act, &dest, 1);
0235     if (IS_ERR(flow_rule)) {
0236         esw_warn(esw->dev,
0237              "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n",
0238              dmac_v, dmac_c, vport, PTR_ERR(flow_rule));
0239         flow_rule = NULL;
0240     }
0241 
0242     kvfree(spec);
0243     return flow_rule;
0244 }
0245 
0246 static struct mlx5_flow_handle *
0247 esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u16 vport)
0248 {
0249     u8 mac_c[ETH_ALEN];
0250 
0251     eth_broadcast_addr(mac_c);
0252     return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac);
0253 }
0254 
0255 static struct mlx5_flow_handle *
0256 esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u16 vport)
0257 {
0258     u8 mac_c[ETH_ALEN];
0259     u8 mac_v[ETH_ALEN];
0260 
0261     eth_zero_addr(mac_c);
0262     eth_zero_addr(mac_v);
0263     mac_c[0] = 0x01;
0264     mac_v[0] = 0x01;
0265     return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac_v);
0266 }
0267 
0268 static struct mlx5_flow_handle *
0269 esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport)
0270 {
0271     u8 mac_c[ETH_ALEN];
0272     u8 mac_v[ETH_ALEN];
0273 
0274     eth_zero_addr(mac_c);
0275     eth_zero_addr(mac_v);
0276     return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v);
0277 }
0278 
0279 /* E-Switch vport UC/MC lists management */
0280 typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
0281                  struct vport_addr *vaddr);
0282 
0283 static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
0284 {
0285     u8 *mac = vaddr->node.addr;
0286     u16 vport = vaddr->vport;
0287     int err;
0288 
0289     /* Skip mlx5_mpfs_add_mac for eswitch_managers,
0290      * it is already done by its netdev in mlx5e_execute_l2_action
0291      */
0292     if (mlx5_esw_is_manager_vport(esw, vport))
0293         goto fdb_add;
0294 
0295     err = mlx5_mpfs_add_mac(esw->dev, mac);
0296     if (err) {
0297         esw_warn(esw->dev,
0298              "Failed to add L2 table mac(%pM) for vport(0x%x), err(%d)\n",
0299              mac, vport, err);
0300         return err;
0301     }
0302     vaddr->mpfs = true;
0303 
0304 fdb_add:
0305     /* SRIOV is enabled: Forward UC MAC to vport */
0306     if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY)
0307         vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
0308 
0309     esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n",
0310           vport, mac, vaddr->flow_rule);
0311 
0312     return 0;
0313 }
0314 
0315 static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
0316 {
0317     u8 *mac = vaddr->node.addr;
0318     u16 vport = vaddr->vport;
0319     int err = 0;
0320 
0321     /* Skip mlx5_mpfs_del_mac for eswitch managers,
0322      * it is already done by its netdev in mlx5e_execute_l2_action
0323      */
0324     if (!vaddr->mpfs || mlx5_esw_is_manager_vport(esw, vport))
0325         goto fdb_del;
0326 
0327     err = mlx5_mpfs_del_mac(esw->dev, mac);
0328     if (err)
0329         esw_warn(esw->dev,
0330              "Failed to del L2 table mac(%pM) for vport(%d), err(%d)\n",
0331              mac, vport, err);
0332     vaddr->mpfs = false;
0333 
0334 fdb_del:
0335     if (vaddr->flow_rule)
0336         mlx5_del_flow_rules(vaddr->flow_rule);
0337     vaddr->flow_rule = NULL;
0338 
0339     return 0;
0340 }
0341 
0342 static void update_allmulti_vports(struct mlx5_eswitch *esw,
0343                    struct vport_addr *vaddr,
0344                    struct esw_mc_addr *esw_mc)
0345 {
0346     u8 *mac = vaddr->node.addr;
0347     struct mlx5_vport *vport;
0348     unsigned long i;
0349     u16 vport_num;
0350 
0351     mlx5_esw_for_each_vport(esw, i, vport) {
0352         struct hlist_head *vport_hash = vport->mc_list;
0353         struct vport_addr *iter_vaddr =
0354                     l2addr_hash_find(vport_hash,
0355                              mac,
0356                              struct vport_addr);
0357         vport_num = vport->vport;
0358         if (IS_ERR_OR_NULL(vport->allmulti_rule) ||
0359             vaddr->vport == vport_num)
0360             continue;
0361         switch (vaddr->action) {
0362         case MLX5_ACTION_ADD:
0363             if (iter_vaddr)
0364                 continue;
0365             iter_vaddr = l2addr_hash_add(vport_hash, mac,
0366                              struct vport_addr,
0367                              GFP_KERNEL);
0368             if (!iter_vaddr) {
0369                 esw_warn(esw->dev,
0370                      "ALL-MULTI: Failed to add MAC(%pM) to vport[%d] DB\n",
0371                      mac, vport_num);
0372                 continue;
0373             }
0374             iter_vaddr->vport = vport_num;
0375             iter_vaddr->flow_rule =
0376                     esw_fdb_set_vport_rule(esw,
0377                                    mac,
0378                                    vport_num);
0379             iter_vaddr->mc_promisc = true;
0380             break;
0381         case MLX5_ACTION_DEL:
0382             if (!iter_vaddr)
0383                 continue;
0384             mlx5_del_flow_rules(iter_vaddr->flow_rule);
0385             l2addr_hash_del(iter_vaddr);
0386             break;
0387         }
0388     }
0389 }
0390 
0391 static int esw_add_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
0392 {
0393     struct hlist_head *hash = esw->mc_table;
0394     struct esw_mc_addr *esw_mc;
0395     u8 *mac = vaddr->node.addr;
0396     u16 vport = vaddr->vport;
0397 
0398     if (!esw->fdb_table.legacy.fdb)
0399         return 0;
0400 
0401     esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr);
0402     if (esw_mc)
0403         goto add;
0404 
0405     esw_mc = l2addr_hash_add(hash, mac, struct esw_mc_addr, GFP_KERNEL);
0406     if (!esw_mc)
0407         return -ENOMEM;
0408 
0409     esw_mc->uplink_rule = /* Forward MC MAC to Uplink */
0410         esw_fdb_set_vport_rule(esw, mac, MLX5_VPORT_UPLINK);
0411 
0412     /* Add this multicast mac to all the mc promiscuous vports */
0413     update_allmulti_vports(esw, vaddr, esw_mc);
0414 
0415 add:
0416     /* If the multicast mac is added as a result of mc promiscuous vport,
0417      * don't increment the multicast ref count
0418      */
0419     if (!vaddr->mc_promisc)
0420         esw_mc->refcnt++;
0421 
0422     /* Forward MC MAC to vport */
0423     vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
0424     esw_debug(esw->dev,
0425           "\tADDED MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n",
0426           vport, mac, vaddr->flow_rule,
0427           esw_mc->refcnt, esw_mc->uplink_rule);
0428     return 0;
0429 }
0430 
0431 static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
0432 {
0433     struct hlist_head *hash = esw->mc_table;
0434     struct esw_mc_addr *esw_mc;
0435     u8 *mac = vaddr->node.addr;
0436     u16 vport = vaddr->vport;
0437 
0438     if (!esw->fdb_table.legacy.fdb)
0439         return 0;
0440 
0441     esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr);
0442     if (!esw_mc) {
0443         esw_warn(esw->dev,
0444              "Failed to find eswitch MC addr for MAC(%pM) vport(%d)",
0445              mac, vport);
0446         return -EINVAL;
0447     }
0448     esw_debug(esw->dev,
0449           "\tDELETE MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n",
0450           vport, mac, vaddr->flow_rule, esw_mc->refcnt,
0451           esw_mc->uplink_rule);
0452 
0453     if (vaddr->flow_rule)
0454         mlx5_del_flow_rules(vaddr->flow_rule);
0455     vaddr->flow_rule = NULL;
0456 
0457     /* If the multicast mac is added as a result of mc promiscuous vport,
0458      * don't decrement the multicast ref count.
0459      */
0460     if (vaddr->mc_promisc || (--esw_mc->refcnt > 0))
0461         return 0;
0462 
0463     /* Remove this multicast mac from all the mc promiscuous vports */
0464     update_allmulti_vports(esw, vaddr, esw_mc);
0465 
0466     if (esw_mc->uplink_rule)
0467         mlx5_del_flow_rules(esw_mc->uplink_rule);
0468 
0469     l2addr_hash_del(esw_mc);
0470     return 0;
0471 }
0472 
0473 /* Apply vport UC/MC list to HW l2 table and FDB table */
0474 static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw,
0475                       struct mlx5_vport *vport, int list_type)
0476 {
0477     bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
0478     vport_addr_action vport_addr_add;
0479     vport_addr_action vport_addr_del;
0480     struct vport_addr *addr;
0481     struct l2addr_node *node;
0482     struct hlist_head *hash;
0483     struct hlist_node *tmp;
0484     int hi;
0485 
0486     vport_addr_add = is_uc ? esw_add_uc_addr :
0487                  esw_add_mc_addr;
0488     vport_addr_del = is_uc ? esw_del_uc_addr :
0489                  esw_del_mc_addr;
0490 
0491     hash = is_uc ? vport->uc_list : vport->mc_list;
0492     for_each_l2hash_node(node, tmp, hash, hi) {
0493         addr = container_of(node, struct vport_addr, node);
0494         switch (addr->action) {
0495         case MLX5_ACTION_ADD:
0496             vport_addr_add(esw, addr);
0497             addr->action = MLX5_ACTION_NONE;
0498             break;
0499         case MLX5_ACTION_DEL:
0500             vport_addr_del(esw, addr);
0501             l2addr_hash_del(addr);
0502             break;
0503         }
0504     }
0505 }
0506 
0507 /* Sync vport UC/MC list from vport context */
0508 static void esw_update_vport_addr_list(struct mlx5_eswitch *esw,
0509                        struct mlx5_vport *vport, int list_type)
0510 {
0511     bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
0512     u8 (*mac_list)[ETH_ALEN];
0513     struct l2addr_node *node;
0514     struct vport_addr *addr;
0515     struct hlist_head *hash;
0516     struct hlist_node *tmp;
0517     int size;
0518     int err;
0519     int hi;
0520     int i;
0521 
0522     size = is_uc ? MLX5_MAX_UC_PER_VPORT(esw->dev) :
0523                MLX5_MAX_MC_PER_VPORT(esw->dev);
0524 
0525     mac_list = kcalloc(size, ETH_ALEN, GFP_KERNEL);
0526     if (!mac_list)
0527         return;
0528 
0529     hash = is_uc ? vport->uc_list : vport->mc_list;
0530 
0531     for_each_l2hash_node(node, tmp, hash, hi) {
0532         addr = container_of(node, struct vport_addr, node);
0533         addr->action = MLX5_ACTION_DEL;
0534     }
0535 
0536     if (!vport->enabled)
0537         goto out;
0538 
0539     err = mlx5_query_nic_vport_mac_list(esw->dev, vport->vport, list_type,
0540                         mac_list, &size);
0541     if (err)
0542         goto out;
0543     esw_debug(esw->dev, "vport[%d] context update %s list size (%d)\n",
0544           vport->vport, is_uc ? "UC" : "MC", size);
0545 
0546     for (i = 0; i < size; i++) {
0547         if (is_uc && !is_valid_ether_addr(mac_list[i]))
0548             continue;
0549 
0550         if (!is_uc && !is_multicast_ether_addr(mac_list[i]))
0551             continue;
0552 
0553         addr = l2addr_hash_find(hash, mac_list[i], struct vport_addr);
0554         if (addr) {
0555             addr->action = MLX5_ACTION_NONE;
0556             /* If this mac was previously added because of allmulti
0557              * promiscuous rx mode, its now converted to be original
0558              * vport mac.
0559              */
0560             if (addr->mc_promisc) {
0561                 struct esw_mc_addr *esw_mc =
0562                     l2addr_hash_find(esw->mc_table,
0563                              mac_list[i],
0564                              struct esw_mc_addr);
0565                 if (!esw_mc) {
0566                     esw_warn(esw->dev,
0567                          "Failed to MAC(%pM) in mcast DB\n",
0568                          mac_list[i]);
0569                     continue;
0570                 }
0571                 esw_mc->refcnt++;
0572                 addr->mc_promisc = false;
0573             }
0574             continue;
0575         }
0576 
0577         addr = l2addr_hash_add(hash, mac_list[i], struct vport_addr,
0578                        GFP_KERNEL);
0579         if (!addr) {
0580             esw_warn(esw->dev,
0581                  "Failed to add MAC(%pM) to vport[%d] DB\n",
0582                  mac_list[i], vport->vport);
0583             continue;
0584         }
0585         addr->vport = vport->vport;
0586         addr->action = MLX5_ACTION_ADD;
0587     }
0588 out:
0589     kfree(mac_list);
0590 }
0591 
0592 /* Sync vport UC/MC list from vport context
0593  * Must be called after esw_update_vport_addr_list
0594  */
0595 static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw,
0596                     struct mlx5_vport *vport)
0597 {
0598     struct l2addr_node *node;
0599     struct vport_addr *addr;
0600     struct hlist_head *hash;
0601     struct hlist_node *tmp;
0602     int hi;
0603 
0604     hash = vport->mc_list;
0605 
0606     for_each_l2hash_node(node, tmp, esw->mc_table, hi) {
0607         u8 *mac = node->addr;
0608 
0609         addr = l2addr_hash_find(hash, mac, struct vport_addr);
0610         if (addr) {
0611             if (addr->action == MLX5_ACTION_DEL)
0612                 addr->action = MLX5_ACTION_NONE;
0613             continue;
0614         }
0615         addr = l2addr_hash_add(hash, mac, struct vport_addr,
0616                        GFP_KERNEL);
0617         if (!addr) {
0618             esw_warn(esw->dev,
0619                  "Failed to add allmulti MAC(%pM) to vport[%d] DB\n",
0620                  mac, vport->vport);
0621             continue;
0622         }
0623         addr->vport = vport->vport;
0624         addr->action = MLX5_ACTION_ADD;
0625         addr->mc_promisc = true;
0626     }
0627 }
0628 
0629 /* Apply vport rx mode to HW FDB table */
0630 static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw,
0631                     struct mlx5_vport *vport,
0632                     bool promisc, bool mc_promisc)
0633 {
0634     struct esw_mc_addr *allmulti_addr = &esw->mc_promisc;
0635 
0636     if (IS_ERR_OR_NULL(vport->allmulti_rule) != mc_promisc)
0637         goto promisc;
0638 
0639     if (mc_promisc) {
0640         vport->allmulti_rule =
0641             esw_fdb_set_vport_allmulti_rule(esw, vport->vport);
0642         if (!allmulti_addr->uplink_rule)
0643             allmulti_addr->uplink_rule =
0644                 esw_fdb_set_vport_allmulti_rule(esw,
0645                                 MLX5_VPORT_UPLINK);
0646         allmulti_addr->refcnt++;
0647     } else if (vport->allmulti_rule) {
0648         mlx5_del_flow_rules(vport->allmulti_rule);
0649         vport->allmulti_rule = NULL;
0650 
0651         if (--allmulti_addr->refcnt > 0)
0652             goto promisc;
0653 
0654         if (allmulti_addr->uplink_rule)
0655             mlx5_del_flow_rules(allmulti_addr->uplink_rule);
0656         allmulti_addr->uplink_rule = NULL;
0657     }
0658 
0659 promisc:
0660     if (IS_ERR_OR_NULL(vport->promisc_rule) != promisc)
0661         return;
0662 
0663     if (promisc) {
0664         vport->promisc_rule =
0665             esw_fdb_set_vport_promisc_rule(esw, vport->vport);
0666     } else if (vport->promisc_rule) {
0667         mlx5_del_flow_rules(vport->promisc_rule);
0668         vport->promisc_rule = NULL;
0669     }
0670 }
0671 
0672 /* Sync vport rx mode from vport context */
0673 static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw,
0674                      struct mlx5_vport *vport)
0675 {
0676     int promisc_all = 0;
0677     int promisc_uc = 0;
0678     int promisc_mc = 0;
0679     int err;
0680 
0681     err = mlx5_query_nic_vport_promisc(esw->dev,
0682                        vport->vport,
0683                        &promisc_uc,
0684                        &promisc_mc,
0685                        &promisc_all);
0686     if (err)
0687         return;
0688     esw_debug(esw->dev, "vport[%d] context update rx mode promisc_all=%d, all_multi=%d\n",
0689           vport->vport, promisc_all, promisc_mc);
0690 
0691     if (!vport->info.trusted || !vport->enabled) {
0692         promisc_uc = 0;
0693         promisc_mc = 0;
0694         promisc_all = 0;
0695     }
0696 
0697     esw_apply_vport_rx_mode(esw, vport, promisc_all,
0698                 (promisc_all || promisc_mc));
0699 }
0700 
0701 void esw_vport_change_handle_locked(struct mlx5_vport *vport)
0702 {
0703     struct mlx5_core_dev *dev = vport->dev;
0704     struct mlx5_eswitch *esw = dev->priv.eswitch;
0705     u8 mac[ETH_ALEN];
0706 
0707     mlx5_query_nic_vport_mac_address(dev, vport->vport, true, mac);
0708     esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n",
0709           vport->vport, mac);
0710 
0711     if (vport->enabled_events & MLX5_VPORT_UC_ADDR_CHANGE) {
0712         esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC);
0713         esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC);
0714     }
0715 
0716     if (vport->enabled_events & MLX5_VPORT_MC_ADDR_CHANGE)
0717         esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC);
0718 
0719     if (vport->enabled_events & MLX5_VPORT_PROMISC_CHANGE) {
0720         esw_update_vport_rx_mode(esw, vport);
0721         if (!IS_ERR_OR_NULL(vport->allmulti_rule))
0722             esw_update_vport_mc_promisc(esw, vport);
0723     }
0724 
0725     if (vport->enabled_events & (MLX5_VPORT_PROMISC_CHANGE | MLX5_VPORT_MC_ADDR_CHANGE))
0726         esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC);
0727 
0728     esw_debug(esw->dev, "vport[%d] Context Changed: Done\n", vport->vport);
0729     if (vport->enabled)
0730         arm_vport_context_events_cmd(dev, vport->vport,
0731                          vport->enabled_events);
0732 }
0733 
0734 static void esw_vport_change_handler(struct work_struct *work)
0735 {
0736     struct mlx5_vport *vport =
0737         container_of(work, struct mlx5_vport, vport_change_handler);
0738     struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
0739 
0740     mutex_lock(&esw->state_lock);
0741     esw_vport_change_handle_locked(vport);
0742     mutex_unlock(&esw->state_lock);
0743 }
0744 
0745 static void node_guid_gen_from_mac(u64 *node_guid, const u8 *mac)
0746 {
0747     ((u8 *)node_guid)[7] = mac[0];
0748     ((u8 *)node_guid)[6] = mac[1];
0749     ((u8 *)node_guid)[5] = mac[2];
0750     ((u8 *)node_guid)[4] = 0xff;
0751     ((u8 *)node_guid)[3] = 0xfe;
0752     ((u8 *)node_guid)[2] = mac[3];
0753     ((u8 *)node_guid)[1] = mac[4];
0754     ((u8 *)node_guid)[0] = mac[5];
0755 }
0756 
0757 static int esw_vport_setup_acl(struct mlx5_eswitch *esw,
0758                    struct mlx5_vport *vport)
0759 {
0760     if (esw->mode == MLX5_ESWITCH_LEGACY)
0761         return esw_legacy_vport_acl_setup(esw, vport);
0762     else
0763         return esw_vport_create_offloads_acl_tables(esw, vport);
0764 }
0765 
0766 static void esw_vport_cleanup_acl(struct mlx5_eswitch *esw,
0767                   struct mlx5_vport *vport)
0768 {
0769     if (esw->mode == MLX5_ESWITCH_LEGACY)
0770         esw_legacy_vport_acl_cleanup(esw, vport);
0771     else
0772         esw_vport_destroy_offloads_acl_tables(esw, vport);
0773 }
0774 
0775 static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
0776 {
0777     u16 vport_num = vport->vport;
0778     int flags;
0779     int err;
0780 
0781     err = esw_vport_setup_acl(esw, vport);
0782     if (err)
0783         return err;
0784 
0785     if (mlx5_esw_is_manager_vport(esw, vport_num))
0786         return 0;
0787 
0788     mlx5_modify_vport_admin_state(esw->dev,
0789                       MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
0790                       vport_num, 1,
0791                       vport->info.link_state);
0792 
0793     /* Host PF has its own mac/guid. */
0794     if (vport_num) {
0795         mlx5_modify_nic_vport_mac_address(esw->dev, vport_num,
0796                           vport->info.mac);
0797         mlx5_modify_nic_vport_node_guid(esw->dev, vport_num,
0798                         vport->info.node_guid);
0799     }
0800 
0801     flags = (vport->info.vlan || vport->info.qos) ?
0802         SET_VLAN_STRIP | SET_VLAN_INSERT : 0;
0803     modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan,
0804                    vport->info.qos, flags);
0805 
0806     return 0;
0807 }
0808 
0809 /* Don't cleanup vport->info, it's needed to restore vport configuration */
0810 static void esw_vport_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
0811 {
0812     u16 vport_num = vport->vport;
0813 
0814     if (!mlx5_esw_is_manager_vport(esw, vport_num))
0815         mlx5_modify_vport_admin_state(esw->dev,
0816                           MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
0817                           vport_num, 1,
0818                           MLX5_VPORT_ADMIN_STATE_DOWN);
0819 
0820     mlx5_esw_qos_vport_disable(esw, vport);
0821     esw_vport_cleanup_acl(esw, vport);
0822 }
0823 
0824 int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, u16 vport_num,
0825               enum mlx5_eswitch_vport_event enabled_events)
0826 {
0827     struct mlx5_vport *vport;
0828     int ret;
0829 
0830     vport = mlx5_eswitch_get_vport(esw, vport_num);
0831     if (IS_ERR(vport))
0832         return PTR_ERR(vport);
0833 
0834     mutex_lock(&esw->state_lock);
0835     WARN_ON(vport->enabled);
0836 
0837     esw_debug(esw->dev, "Enabling VPORT(%d)\n", vport_num);
0838 
0839     ret = esw_vport_setup(esw, vport);
0840     if (ret)
0841         goto done;
0842 
0843     /* Sync with current vport context */
0844     vport->enabled_events = enabled_events;
0845     vport->enabled = true;
0846 
0847     /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well
0848      * in smartNIC as it's a vport group manager.
0849      */
0850     if (mlx5_esw_is_manager_vport(esw, vport_num) ||
0851         (!vport_num && mlx5_core_is_ecpf(esw->dev)))
0852         vport->info.trusted = true;
0853 
0854     if (!mlx5_esw_is_manager_vport(esw, vport->vport) &&
0855         MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) {
0856         ret = mlx5_esw_vport_vhca_id_set(esw, vport_num);
0857         if (ret)
0858             goto err_vhca_mapping;
0859     }
0860 
0861     /* External controller host PF has factory programmed MAC.
0862      * Read it from the device.
0863      */
0864     if (mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF)
0865         mlx5_query_nic_vport_mac_address(esw->dev, vport_num, true, vport->info.mac);
0866 
0867     esw_vport_change_handle_locked(vport);
0868 
0869     esw->enabled_vports++;
0870     esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num);
0871 done:
0872     mutex_unlock(&esw->state_lock);
0873     return ret;
0874 
0875 err_vhca_mapping:
0876     esw_vport_cleanup(esw, vport);
0877     mutex_unlock(&esw->state_lock);
0878     return ret;
0879 }
0880 
0881 void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num)
0882 {
0883     struct mlx5_vport *vport;
0884 
0885     vport = mlx5_eswitch_get_vport(esw, vport_num);
0886     if (IS_ERR(vport))
0887         return;
0888 
0889     mutex_lock(&esw->state_lock);
0890     if (!vport->enabled)
0891         goto done;
0892 
0893     esw_debug(esw->dev, "Disabling vport(%d)\n", vport_num);
0894     /* Mark this vport as disabled to discard new events */
0895     vport->enabled = false;
0896 
0897     /* Disable events from this vport */
0898     arm_vport_context_events_cmd(esw->dev, vport->vport, 0);
0899 
0900     if (!mlx5_esw_is_manager_vport(esw, vport->vport) &&
0901         MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
0902         mlx5_esw_vport_vhca_id_clear(esw, vport_num);
0903 
0904     /* We don't assume VFs will cleanup after themselves.
0905      * Calling vport change handler while vport is disabled will cleanup
0906      * the vport resources.
0907      */
0908     esw_vport_change_handle_locked(vport);
0909     vport->enabled_events = 0;
0910     esw_vport_cleanup(esw, vport);
0911     esw->enabled_vports--;
0912 
0913 done:
0914     mutex_unlock(&esw->state_lock);
0915 }
0916 
0917 static int eswitch_vport_event(struct notifier_block *nb,
0918                    unsigned long type, void *data)
0919 {
0920     struct mlx5_eswitch *esw = mlx5_nb_cof(nb, struct mlx5_eswitch, nb);
0921     struct mlx5_eqe *eqe = data;
0922     struct mlx5_vport *vport;
0923     u16 vport_num;
0924 
0925     vport_num = be16_to_cpu(eqe->data.vport_change.vport_num);
0926     vport = mlx5_eswitch_get_vport(esw, vport_num);
0927     if (!IS_ERR(vport))
0928         queue_work(esw->work_queue, &vport->vport_change_handler);
0929     return NOTIFY_OK;
0930 }
0931 
0932 /**
0933  * mlx5_esw_query_functions - Returns raw output about functions state
0934  * @dev:    Pointer to device to query
0935  *
0936  * mlx5_esw_query_functions() allocates and returns functions changed
0937  * raw output memory pointer from device on success. Otherwise returns ERR_PTR.
0938  * Caller must free the memory using kvfree() when valid pointer is returned.
0939  */
0940 const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
0941 {
0942     int outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out);
0943     u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {};
0944     u32 *out;
0945     int err;
0946 
0947     out = kvzalloc(outlen, GFP_KERNEL);
0948     if (!out)
0949         return ERR_PTR(-ENOMEM);
0950 
0951     MLX5_SET(query_esw_functions_in, in, opcode,
0952          MLX5_CMD_OP_QUERY_ESW_FUNCTIONS);
0953 
0954     err = mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
0955     if (!err)
0956         return out;
0957 
0958     kvfree(out);
0959     return ERR_PTR(err);
0960 }
0961 
0962 static void mlx5_eswitch_event_handlers_register(struct mlx5_eswitch *esw)
0963 {
0964     MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE);
0965     mlx5_eq_notifier_register(esw->dev, &esw->nb);
0966 
0967     if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) {
0968         MLX5_NB_INIT(&esw->esw_funcs.nb, mlx5_esw_funcs_changed_handler,
0969                  ESW_FUNCTIONS_CHANGED);
0970         mlx5_eq_notifier_register(esw->dev, &esw->esw_funcs.nb);
0971     }
0972 }
0973 
0974 static void mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch *esw)
0975 {
0976     if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev))
0977         mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb);
0978 
0979     mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
0980 
0981     flush_workqueue(esw->work_queue);
0982 }
0983 
0984 static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
0985 {
0986     struct mlx5_vport *vport;
0987     unsigned long i;
0988 
0989     mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
0990         memset(&vport->qos, 0, sizeof(vport->qos));
0991         memset(&vport->info, 0, sizeof(vport->info));
0992         vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
0993     }
0994 }
0995 
0996 /* Public E-Switch API */
0997 int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num,
0998                 enum mlx5_eswitch_vport_event enabled_events)
0999 {
1000     int err;
1001 
1002     err = mlx5_esw_vport_enable(esw, vport_num, enabled_events);
1003     if (err)
1004         return err;
1005 
1006     mlx5_esw_vport_debugfs_create(esw, vport_num, false, 0);
1007     err = esw_offloads_load_rep(esw, vport_num);
1008     if (err)
1009         goto err_rep;
1010 
1011     return err;
1012 
1013 err_rep:
1014     mlx5_esw_vport_debugfs_destroy(esw, vport_num);
1015     mlx5_esw_vport_disable(esw, vport_num);
1016     return err;
1017 }
1018 
1019 void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num)
1020 {
1021     esw_offloads_unload_rep(esw, vport_num);
1022     mlx5_esw_vport_debugfs_destroy(esw, vport_num);
1023     mlx5_esw_vport_disable(esw, vport_num);
1024 }
1025 
1026 void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs)
1027 {
1028     struct mlx5_vport *vport;
1029     unsigned long i;
1030 
1031     mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) {
1032         if (!vport->enabled)
1033             continue;
1034         mlx5_eswitch_unload_vport(esw, vport->vport);
1035     }
1036 }
1037 
1038 int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs,
1039                 enum mlx5_eswitch_vport_event enabled_events)
1040 {
1041     struct mlx5_vport *vport;
1042     unsigned long i;
1043     int err;
1044 
1045     mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) {
1046         err = mlx5_eswitch_load_vport(esw, vport->vport, enabled_events);
1047         if (err)
1048             goto vf_err;
1049     }
1050 
1051     return 0;
1052 
1053 vf_err:
1054     mlx5_eswitch_unload_vf_vports(esw, num_vfs);
1055     return err;
1056 }
1057 
1058 static int host_pf_enable_hca(struct mlx5_core_dev *dev)
1059 {
1060     if (!mlx5_core_is_ecpf(dev))
1061         return 0;
1062 
1063     /* Once vport and representor are ready, take out the external host PF
1064      * out of initializing state. Enabling HCA clears the iser->initializing
1065      * bit and host PF driver loading can progress.
1066      */
1067     return mlx5_cmd_host_pf_enable_hca(dev);
1068 }
1069 
1070 static void host_pf_disable_hca(struct mlx5_core_dev *dev)
1071 {
1072     if (!mlx5_core_is_ecpf(dev))
1073         return;
1074 
1075     mlx5_cmd_host_pf_disable_hca(dev);
1076 }
1077 
1078 /* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs
1079  * whichever are present on the eswitch.
1080  */
1081 int
1082 mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
1083                  enum mlx5_eswitch_vport_event enabled_events)
1084 {
1085     int ret;
1086 
1087     /* Enable PF vport */
1088     ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_PF, enabled_events);
1089     if (ret)
1090         return ret;
1091 
1092     /* Enable external host PF HCA */
1093     ret = host_pf_enable_hca(esw->dev);
1094     if (ret)
1095         goto pf_hca_err;
1096 
1097     /* Enable ECPF vport */
1098     if (mlx5_ecpf_vport_exists(esw->dev)) {
1099         ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_ECPF, enabled_events);
1100         if (ret)
1101             goto ecpf_err;
1102     }
1103 
1104     /* Enable VF vports */
1105     ret = mlx5_eswitch_load_vf_vports(esw, esw->esw_funcs.num_vfs,
1106                       enabled_events);
1107     if (ret)
1108         goto vf_err;
1109     return 0;
1110 
1111 vf_err:
1112     if (mlx5_ecpf_vport_exists(esw->dev))
1113         mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
1114 ecpf_err:
1115     host_pf_disable_hca(esw->dev);
1116 pf_hca_err:
1117     mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF);
1118     return ret;
1119 }
1120 
1121 /* mlx5_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs
1122  * whichever are previously enabled on the eswitch.
1123  */
1124 void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw)
1125 {
1126     mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
1127 
1128     if (mlx5_ecpf_vport_exists(esw->dev))
1129         mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
1130 
1131     host_pf_disable_hca(esw->dev);
1132     mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF);
1133 }
1134 
1135 static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw)
1136 {
1137     struct devlink *devlink = priv_to_devlink(esw->dev);
1138     union devlink_param_value val;
1139     int err;
1140 
1141     err = devlink_param_driverinit_value_get(devlink,
1142                          MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
1143                          &val);
1144     if (!err) {
1145         esw->params.large_group_num = val.vu32;
1146     } else {
1147         esw_warn(esw->dev,
1148              "Devlink can't get param fdb_large_groups, uses default (%d).\n",
1149              ESW_OFFLOADS_DEFAULT_NUM_GROUPS);
1150         esw->params.large_group_num = ESW_OFFLOADS_DEFAULT_NUM_GROUPS;
1151     }
1152 }
1153 
1154 static void
1155 mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs)
1156 {
1157     const u32 *out;
1158 
1159     if (num_vfs < 0)
1160         return;
1161 
1162     if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1163         esw->esw_funcs.num_vfs = num_vfs;
1164         return;
1165     }
1166 
1167     out = mlx5_esw_query_functions(esw->dev);
1168     if (IS_ERR(out))
1169         return;
1170 
1171     esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out,
1172                       host_params_context.host_num_of_vfs);
1173     kvfree(out);
1174 }
1175 
1176 static void mlx5_esw_mode_change_notify(struct mlx5_eswitch *esw, u16 mode)
1177 {
1178     struct mlx5_esw_event_info info = {};
1179 
1180     info.new_mode = mode;
1181 
1182     blocking_notifier_call_chain(&esw->n_head, 0, &info);
1183 }
1184 
1185 static int mlx5_esw_acls_ns_init(struct mlx5_eswitch *esw)
1186 {
1187     struct mlx5_core_dev *dev = esw->dev;
1188     int total_vports;
1189     int err;
1190 
1191     if (esw->flags & MLX5_ESWITCH_VPORT_ACL_NS_CREATED)
1192         return 0;
1193 
1194     total_vports = mlx5_eswitch_get_total_vports(dev);
1195 
1196     if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
1197         err = mlx5_fs_egress_acls_init(dev, total_vports);
1198         if (err)
1199             return err;
1200     } else {
1201         esw_warn(dev, "engress ACL is not supported by FW\n");
1202     }
1203 
1204     if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
1205         err = mlx5_fs_ingress_acls_init(dev, total_vports);
1206         if (err)
1207             goto err;
1208     } else {
1209         esw_warn(dev, "ingress ACL is not supported by FW\n");
1210     }
1211     esw->flags |= MLX5_ESWITCH_VPORT_ACL_NS_CREATED;
1212     return 0;
1213 
1214 err:
1215     if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
1216         mlx5_fs_egress_acls_cleanup(dev);
1217     return err;
1218 }
1219 
1220 static void mlx5_esw_acls_ns_cleanup(struct mlx5_eswitch *esw)
1221 {
1222     struct mlx5_core_dev *dev = esw->dev;
1223 
1224     esw->flags &= ~MLX5_ESWITCH_VPORT_ACL_NS_CREATED;
1225     if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support))
1226         mlx5_fs_ingress_acls_cleanup(dev);
1227     if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
1228         mlx5_fs_egress_acls_cleanup(dev);
1229 }
1230 
1231 /**
1232  * mlx5_eswitch_enable_locked - Enable eswitch
1233  * @esw:    Pointer to eswitch
1234  * @num_vfs:    Enable eswitch for given number of VFs. This is optional.
1235  *      Valid value are 0, > 0 and MLX5_ESWITCH_IGNORE_NUM_VFS.
1236  *      Caller should pass num_vfs > 0 when enabling eswitch for
1237  *      vf vports. Caller should pass num_vfs = 0, when eswitch
1238  *      is enabled without sriov VFs or when caller
1239  *      is unaware of the sriov state of the host PF on ECPF based
1240  *      eswitch. Caller should pass < 0 when num_vfs should be
1241  *      completely ignored. This is typically the case when eswitch
1242  *      is enabled without sriov regardless of PF/ECPF system.
1243  * mlx5_eswitch_enable_locked() Enables eswitch in either legacy or offloads
1244  * mode. If num_vfs >=0 is provided, it setup VF related eswitch vports.
1245  * It returns 0 on success or error code on failure.
1246  */
1247 int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs)
1248 {
1249     int err;
1250 
1251     lockdep_assert_held(&esw->mode_lock);
1252 
1253     if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
1254         esw_warn(esw->dev, "FDB is not supported, aborting ...\n");
1255         return -EOPNOTSUPP;
1256     }
1257 
1258     mlx5_eswitch_get_devlink_param(esw);
1259 
1260     err = mlx5_esw_acls_ns_init(esw);
1261     if (err)
1262         return err;
1263 
1264     mlx5_eswitch_update_num_of_vfs(esw, num_vfs);
1265 
1266     if (esw->mode == MLX5_ESWITCH_LEGACY) {
1267         err = esw_legacy_enable(esw);
1268     } else {
1269         mlx5_rescan_drivers(esw->dev);
1270         err = esw_offloads_enable(esw);
1271     }
1272 
1273     if (err)
1274         goto abort;
1275 
1276     esw->fdb_table.flags |= MLX5_ESW_FDB_CREATED;
1277 
1278     mlx5_eswitch_event_handlers_register(esw);
1279 
1280     esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n",
1281          esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
1282          esw->esw_funcs.num_vfs, esw->enabled_vports);
1283 
1284     mlx5_esw_mode_change_notify(esw, esw->mode);
1285 
1286     return 0;
1287 
1288 abort:
1289     mlx5_esw_acls_ns_cleanup(esw);
1290     return err;
1291 }
1292 
1293 /**
1294  * mlx5_eswitch_enable - Enable eswitch
1295  * @esw:    Pointer to eswitch
1296  * @num_vfs:    Enable eswitch switch for given number of VFs.
1297  *      Caller must pass num_vfs > 0 when enabling eswitch for
1298  *      vf vports.
1299  * mlx5_eswitch_enable() returns 0 on success or error code on failure.
1300  */
1301 int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
1302 {
1303     bool toggle_lag;
1304     int ret;
1305 
1306     if (!mlx5_esw_allowed(esw))
1307         return 0;
1308 
1309     devl_assert_locked(priv_to_devlink(esw->dev));
1310 
1311     toggle_lag = !mlx5_esw_is_fdb_created(esw);
1312 
1313     if (toggle_lag)
1314         mlx5_lag_disable_change(esw->dev);
1315 
1316     down_write(&esw->mode_lock);
1317     if (!mlx5_esw_is_fdb_created(esw)) {
1318         ret = mlx5_eswitch_enable_locked(esw, num_vfs);
1319     } else {
1320         enum mlx5_eswitch_vport_event vport_events;
1321 
1322         vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ?
1323                     MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE;
1324         ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events);
1325         if (!ret)
1326             esw->esw_funcs.num_vfs = num_vfs;
1327     }
1328     up_write(&esw->mode_lock);
1329 
1330     if (toggle_lag)
1331         mlx5_lag_enable_change(esw->dev);
1332 
1333     return ret;
1334 }
1335 
1336 /* When disabling sriov, free driver level resources. */
1337 void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
1338 {
1339     if (!mlx5_esw_allowed(esw))
1340         return;
1341 
1342     devl_assert_locked(priv_to_devlink(esw->dev));
1343     down_write(&esw->mode_lock);
1344     /* If driver is unloaded, this function is called twice by remove_one()
1345      * and mlx5_unload(). Prevent the second call.
1346      */
1347     if (!esw->esw_funcs.num_vfs && !clear_vf)
1348         goto unlock;
1349 
1350     esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), active vports(%d)\n",
1351          esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
1352          esw->esw_funcs.num_vfs, esw->enabled_vports);
1353 
1354     mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
1355     if (clear_vf)
1356         mlx5_eswitch_clear_vf_vports_info(esw);
1357     /* If disabling sriov in switchdev mode, free meta rules here
1358      * because it depends on num_vfs.
1359      */
1360     if (esw->mode == MLX5_ESWITCH_OFFLOADS) {
1361         struct devlink *devlink = priv_to_devlink(esw->dev);
1362 
1363         esw_offloads_del_send_to_vport_meta_rules(esw);
1364         devl_rate_nodes_destroy(devlink);
1365     }
1366 
1367     esw->esw_funcs.num_vfs = 0;
1368 
1369 unlock:
1370     up_write(&esw->mode_lock);
1371 }
1372 
1373 /* Free resources for corresponding eswitch mode. It is called by devlink
1374  * when changing eswitch mode or modprobe when unloading driver.
1375  */
1376 void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw)
1377 {
1378     struct devlink *devlink = priv_to_devlink(esw->dev);
1379 
1380     /* Notify eswitch users that it is exiting from current mode.
1381      * So that it can do necessary cleanup before the eswitch is disabled.
1382      */
1383     mlx5_esw_mode_change_notify(esw, MLX5_ESWITCH_LEGACY);
1384 
1385     mlx5_eswitch_event_handlers_unregister(esw);
1386 
1387     esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), active vports(%d)\n",
1388          esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
1389          esw->esw_funcs.num_vfs, esw->enabled_vports);
1390 
1391     esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED;
1392     if (esw->mode == MLX5_ESWITCH_OFFLOADS)
1393         esw_offloads_disable(esw);
1394     else if (esw->mode == MLX5_ESWITCH_LEGACY)
1395         esw_legacy_disable(esw);
1396     mlx5_esw_acls_ns_cleanup(esw);
1397 
1398     if (esw->mode == MLX5_ESWITCH_OFFLOADS)
1399         devl_rate_nodes_destroy(devlink);
1400 }
1401 
1402 void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
1403 {
1404     if (!mlx5_esw_allowed(esw))
1405         return;
1406 
1407     devl_assert_locked(priv_to_devlink(esw->dev));
1408     mlx5_lag_disable_change(esw->dev);
1409     down_write(&esw->mode_lock);
1410     mlx5_eswitch_disable_locked(esw);
1411     up_write(&esw->mode_lock);
1412     mlx5_lag_enable_change(esw->dev);
1413 }
1414 
1415 static int mlx5_query_hca_cap_host_pf(struct mlx5_core_dev *dev, void *out)
1416 {
1417     u16 opmod = (MLX5_CAP_GENERAL << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01);
1418     u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {};
1419 
1420     MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
1421     MLX5_SET(query_hca_cap_in, in, op_mod, opmod);
1422     MLX5_SET(query_hca_cap_in, in, function_id, MLX5_VPORT_PF);
1423     MLX5_SET(query_hca_cap_in, in, other_function, true);
1424     return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out);
1425 }
1426 
1427 int mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev *dev, u16 *max_sfs, u16 *sf_base_id)
1428 
1429 {
1430     int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
1431     void *query_ctx;
1432     void *hca_caps;
1433     int err;
1434 
1435     if (!mlx5_core_is_ecpf(dev)) {
1436         *max_sfs = 0;
1437         return 0;
1438     }
1439 
1440     query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
1441     if (!query_ctx)
1442         return -ENOMEM;
1443 
1444     err = mlx5_query_hca_cap_host_pf(dev, query_ctx);
1445     if (err)
1446         goto out_free;
1447 
1448     hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
1449     *max_sfs = MLX5_GET(cmd_hca_cap, hca_caps, max_num_sf);
1450     *sf_base_id = MLX5_GET(cmd_hca_cap, hca_caps, sf_base_id);
1451 
1452 out_free:
1453     kfree(query_ctx);
1454     return err;
1455 }
1456 
1457 static int mlx5_esw_vport_alloc(struct mlx5_eswitch *esw, struct mlx5_core_dev *dev,
1458                 int index, u16 vport_num)
1459 {
1460     struct mlx5_vport *vport;
1461     int err;
1462 
1463     vport = kzalloc(sizeof(*vport), GFP_KERNEL);
1464     if (!vport)
1465         return -ENOMEM;
1466 
1467     vport->dev = esw->dev;
1468     vport->vport = vport_num;
1469     vport->index = index;
1470     vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
1471     INIT_WORK(&vport->vport_change_handler, esw_vport_change_handler);
1472     err = xa_insert(&esw->vports, vport_num, vport, GFP_KERNEL);
1473     if (err)
1474         goto insert_err;
1475 
1476     esw->total_vports++;
1477     return 0;
1478 
1479 insert_err:
1480     kfree(vport);
1481     return err;
1482 }
1483 
1484 static void mlx5_esw_vport_free(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
1485 {
1486     xa_erase(&esw->vports, vport->vport);
1487     kfree(vport);
1488 }
1489 
1490 static void mlx5_esw_vports_cleanup(struct mlx5_eswitch *esw)
1491 {
1492     struct mlx5_vport *vport;
1493     unsigned long i;
1494 
1495     mlx5_esw_for_each_vport(esw, i, vport)
1496         mlx5_esw_vport_free(esw, vport);
1497     xa_destroy(&esw->vports);
1498 }
1499 
1500 static int mlx5_esw_vports_init(struct mlx5_eswitch *esw)
1501 {
1502     struct mlx5_core_dev *dev = esw->dev;
1503     u16 max_host_pf_sfs;
1504     u16 base_sf_num;
1505     int idx = 0;
1506     int err;
1507     int i;
1508 
1509     xa_init(&esw->vports);
1510 
1511     err = mlx5_esw_vport_alloc(esw, dev, idx, MLX5_VPORT_PF);
1512     if (err)
1513         goto err;
1514     if (esw->first_host_vport == MLX5_VPORT_PF)
1515         xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN);
1516     idx++;
1517 
1518     for (i = 0; i < mlx5_core_max_vfs(dev); i++) {
1519         err = mlx5_esw_vport_alloc(esw, dev, idx, idx);
1520         if (err)
1521             goto err;
1522         xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_VF);
1523         xa_set_mark(&esw->vports, idx, MLX5_ESW_VPT_HOST_FN);
1524         idx++;
1525     }
1526     base_sf_num = mlx5_sf_start_function_id(dev);
1527     for (i = 0; i < mlx5_sf_max_functions(dev); i++) {
1528         err = mlx5_esw_vport_alloc(esw, dev, idx, base_sf_num + i);
1529         if (err)
1530             goto err;
1531         xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF);
1532         idx++;
1533     }
1534 
1535     err = mlx5_esw_sf_max_hpf_functions(dev, &max_host_pf_sfs, &base_sf_num);
1536     if (err)
1537         goto err;
1538     for (i = 0; i < max_host_pf_sfs; i++) {
1539         err = mlx5_esw_vport_alloc(esw, dev, idx, base_sf_num + i);
1540         if (err)
1541             goto err;
1542         xa_set_mark(&esw->vports, base_sf_num + i, MLX5_ESW_VPT_SF);
1543         idx++;
1544     }
1545 
1546     if (mlx5_ecpf_vport_exists(dev)) {
1547         err = mlx5_esw_vport_alloc(esw, dev, idx, MLX5_VPORT_ECPF);
1548         if (err)
1549             goto err;
1550         idx++;
1551     }
1552     err = mlx5_esw_vport_alloc(esw, dev, idx, MLX5_VPORT_UPLINK);
1553     if (err)
1554         goto err;
1555     return 0;
1556 
1557 err:
1558     mlx5_esw_vports_cleanup(esw);
1559     return err;
1560 }
1561 
1562 int mlx5_eswitch_init(struct mlx5_core_dev *dev)
1563 {
1564     struct mlx5_eswitch *esw;
1565     int err;
1566 
1567     if (!MLX5_VPORT_MANAGER(dev))
1568         return 0;
1569 
1570     esw = kzalloc(sizeof(*esw), GFP_KERNEL);
1571     if (!esw)
1572         return -ENOMEM;
1573 
1574     esw->dev = dev;
1575     esw->manager_vport = mlx5_eswitch_manager_vport(dev);
1576     esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev);
1577 
1578     esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq");
1579     if (!esw->work_queue) {
1580         err = -ENOMEM;
1581         goto abort;
1582     }
1583 
1584     err = mlx5_esw_vports_init(esw);
1585     if (err)
1586         goto abort;
1587 
1588     err = esw_offloads_init_reps(esw);
1589     if (err)
1590         goto reps_err;
1591 
1592     mutex_init(&esw->offloads.encap_tbl_lock);
1593     hash_init(esw->offloads.encap_tbl);
1594     mutex_init(&esw->offloads.decap_tbl_lock);
1595     hash_init(esw->offloads.decap_tbl);
1596     mlx5e_mod_hdr_tbl_init(&esw->offloads.mod_hdr);
1597     atomic64_set(&esw->offloads.num_flows, 0);
1598     ida_init(&esw->offloads.vport_metadata_ida);
1599     xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC);
1600     mutex_init(&esw->state_lock);
1601     init_rwsem(&esw->mode_lock);
1602     refcount_set(&esw->qos.refcnt, 0);
1603 
1604     esw->enabled_vports = 0;
1605     esw->mode = MLX5_ESWITCH_LEGACY;
1606     esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
1607     if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) &&
1608         MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
1609         esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
1610     else
1611         esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
1612     if (MLX5_ESWITCH_MANAGER(dev) &&
1613         mlx5_esw_vport_match_metadata_supported(esw))
1614         esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
1615 
1616     dev->priv.eswitch = esw;
1617     BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head);
1618 
1619     esw->dbgfs = debugfs_create_dir("esw", mlx5_debugfs_get_dev_root(esw->dev));
1620     esw_info(dev,
1621          "Total vports %d, per vport: max uc(%d) max mc(%d)\n",
1622          esw->total_vports,
1623          MLX5_MAX_UC_PER_VPORT(dev),
1624          MLX5_MAX_MC_PER_VPORT(dev));
1625     return 0;
1626 
1627 reps_err:
1628     mlx5_esw_vports_cleanup(esw);
1629 abort:
1630     if (esw->work_queue)
1631         destroy_workqueue(esw->work_queue);
1632     kfree(esw);
1633     return err;
1634 }
1635 
1636 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
1637 {
1638     if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
1639         return;
1640 
1641     esw_info(esw->dev, "cleanup\n");
1642 
1643     debugfs_remove_recursive(esw->dbgfs);
1644     esw->dev->priv.eswitch = NULL;
1645     destroy_workqueue(esw->work_queue);
1646     WARN_ON(refcount_read(&esw->qos.refcnt));
1647     mutex_destroy(&esw->state_lock);
1648     WARN_ON(!xa_empty(&esw->offloads.vhca_map));
1649     xa_destroy(&esw->offloads.vhca_map);
1650     ida_destroy(&esw->offloads.vport_metadata_ida);
1651     mlx5e_mod_hdr_tbl_destroy(&esw->offloads.mod_hdr);
1652     mutex_destroy(&esw->offloads.encap_tbl_lock);
1653     mutex_destroy(&esw->offloads.decap_tbl_lock);
1654     esw_offloads_cleanup_reps(esw);
1655     mlx5_esw_vports_cleanup(esw);
1656     kfree(esw);
1657 }
1658 
1659 /* Vport Administration */
1660 static int
1661 mlx5_esw_set_vport_mac_locked(struct mlx5_eswitch *esw,
1662                   struct mlx5_vport *evport, const u8 *mac)
1663 {
1664     u16 vport_num = evport->vport;
1665     u64 node_guid;
1666     int err = 0;
1667 
1668     if (is_multicast_ether_addr(mac))
1669         return -EINVAL;
1670 
1671     if (evport->info.spoofchk && !is_valid_ether_addr(mac))
1672         mlx5_core_warn(esw->dev,
1673                    "Set invalid MAC while spoofchk is on, vport(%d)\n",
1674                    vport_num);
1675 
1676     err = mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, mac);
1677     if (err) {
1678         mlx5_core_warn(esw->dev,
1679                    "Failed to mlx5_modify_nic_vport_mac vport(%d) err=(%d)\n",
1680                    vport_num, err);
1681         return err;
1682     }
1683 
1684     node_guid_gen_from_mac(&node_guid, mac);
1685     err = mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, node_guid);
1686     if (err)
1687         mlx5_core_warn(esw->dev,
1688                    "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n",
1689                    vport_num, err);
1690 
1691     ether_addr_copy(evport->info.mac, mac);
1692     evport->info.node_guid = node_guid;
1693     if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
1694         err = esw_acl_ingress_lgcy_setup(esw, evport);
1695 
1696     return err;
1697 }
1698 
1699 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
1700                    u16 vport, const u8 *mac)
1701 {
1702     struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1703     int err = 0;
1704 
1705     if (IS_ERR(evport))
1706         return PTR_ERR(evport);
1707 
1708     mutex_lock(&esw->state_lock);
1709     err = mlx5_esw_set_vport_mac_locked(esw, evport, mac);
1710     mutex_unlock(&esw->state_lock);
1711     return err;
1712 }
1713 
1714 static bool mlx5_esw_check_port_type(struct mlx5_eswitch *esw, u16 vport_num, xa_mark_t mark)
1715 {
1716     struct mlx5_vport *vport;
1717 
1718     vport = mlx5_eswitch_get_vport(esw, vport_num);
1719     if (IS_ERR(vport))
1720         return false;
1721 
1722     return xa_get_mark(&esw->vports, vport_num, mark);
1723 }
1724 
1725 bool mlx5_eswitch_is_vf_vport(struct mlx5_eswitch *esw, u16 vport_num)
1726 {
1727     return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_VF);
1728 }
1729 
1730 bool mlx5_esw_is_sf_vport(struct mlx5_eswitch *esw, u16 vport_num)
1731 {
1732     return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_SF);
1733 }
1734 
1735 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
1736                  u16 vport, int link_state)
1737 {
1738     struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1739     int opmod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT;
1740     int other_vport = 1;
1741     int err = 0;
1742 
1743     if (!mlx5_esw_allowed(esw))
1744         return -EPERM;
1745     if (IS_ERR(evport))
1746         return PTR_ERR(evport);
1747 
1748     if (vport == MLX5_VPORT_UPLINK) {
1749         opmod = MLX5_VPORT_STATE_OP_MOD_UPLINK;
1750         other_vport = 0;
1751         vport = 0;
1752     }
1753     mutex_lock(&esw->state_lock);
1754     if (esw->mode != MLX5_ESWITCH_LEGACY) {
1755         err = -EOPNOTSUPP;
1756         goto unlock;
1757     }
1758 
1759     err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, other_vport, link_state);
1760     if (err) {
1761         mlx5_core_warn(esw->dev, "Failed to set vport %d link state, opmod = %d, err = %d",
1762                    vport, opmod, err);
1763         goto unlock;
1764     }
1765 
1766     evport->info.link_state = link_state;
1767 
1768 unlock:
1769     mutex_unlock(&esw->state_lock);
1770     return err;
1771 }
1772 
1773 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
1774                   u16 vport, struct ifla_vf_info *ivi)
1775 {
1776     struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1777 
1778     if (IS_ERR(evport))
1779         return PTR_ERR(evport);
1780 
1781     memset(ivi, 0, sizeof(*ivi));
1782     ivi->vf = vport - 1;
1783 
1784     mutex_lock(&esw->state_lock);
1785     ether_addr_copy(ivi->mac, evport->info.mac);
1786     ivi->linkstate = evport->info.link_state;
1787     ivi->vlan = evport->info.vlan;
1788     ivi->qos = evport->info.qos;
1789     ivi->spoofchk = evport->info.spoofchk;
1790     ivi->trusted = evport->info.trusted;
1791     if (evport->qos.enabled) {
1792         ivi->min_tx_rate = evport->qos.min_rate;
1793         ivi->max_tx_rate = evport->qos.max_rate;
1794     }
1795     mutex_unlock(&esw->state_lock);
1796 
1797     return 0;
1798 }
1799 
1800 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
1801                   u16 vport, u16 vlan, u8 qos, u8 set_flags)
1802 {
1803     struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1804     int err = 0;
1805 
1806     if (IS_ERR(evport))
1807         return PTR_ERR(evport);
1808     if (vlan > 4095 || qos > 7)
1809         return -EINVAL;
1810 
1811     err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags);
1812     if (err)
1813         return err;
1814 
1815     evport->info.vlan = vlan;
1816     evport->info.qos = qos;
1817     if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) {
1818         err = esw_acl_ingress_lgcy_setup(esw, evport);
1819         if (err)
1820             return err;
1821         err = esw_acl_egress_lgcy_setup(esw, evport);
1822     }
1823 
1824     return err;
1825 }
1826 
1827 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
1828                  u16 vport_num,
1829                  struct ifla_vf_stats *vf_stats)
1830 {
1831     struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
1832     int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out);
1833     u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {};
1834     struct mlx5_vport_drop_stats stats = {};
1835     int err = 0;
1836     u32 *out;
1837 
1838     if (IS_ERR(vport))
1839         return PTR_ERR(vport);
1840 
1841     out = kvzalloc(outlen, GFP_KERNEL);
1842     if (!out)
1843         return -ENOMEM;
1844 
1845     MLX5_SET(query_vport_counter_in, in, opcode,
1846          MLX5_CMD_OP_QUERY_VPORT_COUNTER);
1847     MLX5_SET(query_vport_counter_in, in, op_mod, 0);
1848     MLX5_SET(query_vport_counter_in, in, vport_number, vport->vport);
1849     MLX5_SET(query_vport_counter_in, in, other_vport, 1);
1850 
1851     err = mlx5_cmd_exec_inout(esw->dev, query_vport_counter, in, out);
1852     if (err)
1853         goto free_out;
1854 
1855     #define MLX5_GET_CTR(p, x) \
1856         MLX5_GET64(query_vport_counter_out, p, x)
1857 
1858     memset(vf_stats, 0, sizeof(*vf_stats));
1859     vf_stats->rx_packets =
1860         MLX5_GET_CTR(out, received_eth_unicast.packets) +
1861         MLX5_GET_CTR(out, received_ib_unicast.packets) +
1862         MLX5_GET_CTR(out, received_eth_multicast.packets) +
1863         MLX5_GET_CTR(out, received_ib_multicast.packets) +
1864         MLX5_GET_CTR(out, received_eth_broadcast.packets);
1865 
1866     vf_stats->rx_bytes =
1867         MLX5_GET_CTR(out, received_eth_unicast.octets) +
1868         MLX5_GET_CTR(out, received_ib_unicast.octets) +
1869         MLX5_GET_CTR(out, received_eth_multicast.octets) +
1870         MLX5_GET_CTR(out, received_ib_multicast.octets) +
1871         MLX5_GET_CTR(out, received_eth_broadcast.octets);
1872 
1873     vf_stats->tx_packets =
1874         MLX5_GET_CTR(out, transmitted_eth_unicast.packets) +
1875         MLX5_GET_CTR(out, transmitted_ib_unicast.packets) +
1876         MLX5_GET_CTR(out, transmitted_eth_multicast.packets) +
1877         MLX5_GET_CTR(out, transmitted_ib_multicast.packets) +
1878         MLX5_GET_CTR(out, transmitted_eth_broadcast.packets);
1879 
1880     vf_stats->tx_bytes =
1881         MLX5_GET_CTR(out, transmitted_eth_unicast.octets) +
1882         MLX5_GET_CTR(out, transmitted_ib_unicast.octets) +
1883         MLX5_GET_CTR(out, transmitted_eth_multicast.octets) +
1884         MLX5_GET_CTR(out, transmitted_ib_multicast.octets) +
1885         MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
1886 
1887     vf_stats->multicast =
1888         MLX5_GET_CTR(out, received_eth_multicast.packets) +
1889         MLX5_GET_CTR(out, received_ib_multicast.packets);
1890 
1891     vf_stats->broadcast =
1892         MLX5_GET_CTR(out, received_eth_broadcast.packets);
1893 
1894     err = mlx5_esw_query_vport_drop_stats(esw->dev, vport, &stats);
1895     if (err)
1896         goto free_out;
1897     vf_stats->rx_dropped = stats.rx_dropped;
1898     vf_stats->tx_dropped = stats.tx_dropped;
1899 
1900 free_out:
1901     kvfree(out);
1902     return err;
1903 }
1904 
1905 u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev)
1906 {
1907     struct mlx5_eswitch *esw = dev->priv.eswitch;
1908 
1909     return mlx5_esw_allowed(esw) ? esw->mode : MLX5_ESWITCH_LEGACY;
1910 }
1911 EXPORT_SYMBOL_GPL(mlx5_eswitch_mode);
1912 
1913 enum devlink_eswitch_encap_mode
1914 mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev)
1915 {
1916     struct mlx5_eswitch *esw;
1917 
1918     esw = dev->priv.eswitch;
1919     return (mlx5_eswitch_mode(dev) == MLX5_ESWITCH_OFFLOADS)  ? esw->offloads.encap :
1920         DEVLINK_ESWITCH_ENCAP_MODE_NONE;
1921 }
1922 EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);
1923 
1924 bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
1925                    struct mlx5_core_dev *dev1)
1926 {
1927     return (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS &&
1928         dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS);
1929 }
1930 
1931 int mlx5_esw_event_notifier_register(struct mlx5_eswitch *esw, struct notifier_block *nb)
1932 {
1933     return blocking_notifier_chain_register(&esw->n_head, nb);
1934 }
1935 
1936 void mlx5_esw_event_notifier_unregister(struct mlx5_eswitch *esw, struct notifier_block *nb)
1937 {
1938     blocking_notifier_chain_unregister(&esw->n_head, nb);
1939 }
1940 
1941 /**
1942  * mlx5_esw_hold() - Try to take a read lock on esw mode lock.
1943  * @mdev: mlx5 core device.
1944  *
1945  * Should be called by esw resources callers.
1946  *
1947  * Return: true on success or false.
1948  */
1949 bool mlx5_esw_hold(struct mlx5_core_dev *mdev)
1950 {
1951     struct mlx5_eswitch *esw = mdev->priv.eswitch;
1952 
1953     /* e.g. VF doesn't have eswitch so nothing to do */
1954     if (!mlx5_esw_allowed(esw))
1955         return true;
1956 
1957     if (down_read_trylock(&esw->mode_lock) != 0)
1958         return true;
1959 
1960     return false;
1961 }
1962 
1963 /**
1964  * mlx5_esw_release() - Release a read lock on esw mode lock.
1965  * @mdev: mlx5 core device.
1966  */
1967 void mlx5_esw_release(struct mlx5_core_dev *mdev)
1968 {
1969     struct mlx5_eswitch *esw = mdev->priv.eswitch;
1970 
1971     if (mlx5_esw_allowed(esw))
1972         up_read(&esw->mode_lock);
1973 }
1974 
1975 /**
1976  * mlx5_esw_get() - Increase esw user count.
1977  * @mdev: mlx5 core device.
1978  */
1979 void mlx5_esw_get(struct mlx5_core_dev *mdev)
1980 {
1981     struct mlx5_eswitch *esw = mdev->priv.eswitch;
1982 
1983     if (mlx5_esw_allowed(esw))
1984         atomic64_inc(&esw->user_count);
1985 }
1986 
1987 /**
1988  * mlx5_esw_put() - Decrease esw user count.
1989  * @mdev: mlx5 core device.
1990  */
1991 void mlx5_esw_put(struct mlx5_core_dev *mdev)
1992 {
1993     struct mlx5_eswitch *esw = mdev->priv.eswitch;
1994 
1995     if (mlx5_esw_allowed(esw))
1996         atomic64_dec_if_positive(&esw->user_count);
1997 }
1998 
1999 /**
2000  * mlx5_esw_try_lock() - Take a write lock on esw mode lock.
2001  * @esw: eswitch device.
2002  *
2003  * Should be called by esw mode change routine.
2004  *
2005  * Return:
2006  * * 0       - esw mode if successfully locked and refcount is 0.
2007  * * -EBUSY  - refcount is not 0.
2008  * * -EINVAL - In the middle of switching mode or lock is already held.
2009  */
2010 int mlx5_esw_try_lock(struct mlx5_eswitch *esw)
2011 {
2012     if (down_write_trylock(&esw->mode_lock) == 0)
2013         return -EINVAL;
2014 
2015     if (atomic64_read(&esw->user_count) > 0) {
2016         up_write(&esw->mode_lock);
2017         return -EBUSY;
2018     }
2019 
2020     return esw->mode;
2021 }
2022 
2023 /**
2024  * mlx5_esw_unlock() - Release write lock on esw mode lock
2025  * @esw: eswitch device.
2026  */
2027 void mlx5_esw_unlock(struct mlx5_eswitch *esw)
2028 {
2029     up_write(&esw->mode_lock);
2030 }
2031 
2032 /**
2033  * mlx5_eswitch_get_total_vports - Get total vports of the eswitch
2034  *
2035  * @dev: Pointer to core device
2036  *
2037  * mlx5_eswitch_get_total_vports returns total number of eswitch vports.
2038  */
2039 u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev)
2040 {
2041     struct mlx5_eswitch *esw;
2042 
2043     esw = dev->priv.eswitch;
2044     return mlx5_esw_allowed(esw) ? esw->total_vports : 0;
2045 }
2046 EXPORT_SYMBOL_GPL(mlx5_eswitch_get_total_vports);
2047 
2048 /**
2049  * mlx5_eswitch_get_core_dev - Get the mdev device
2050  * @esw : eswitch device.
2051  *
2052  * Return the mellanox core device which manages the eswitch.
2053  */
2054 struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw)
2055 {
2056     return mlx5_esw_allowed(esw) ? esw->dev : NULL;
2057 }
2058 EXPORT_SYMBOL(mlx5_eswitch_get_core_dev);