File Index
Files and directories
Sign in
FILE

en_rep.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c C
   1/*
   2 * Copyright (c) 2016, 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/dim.h>
  34#include <linux/debugfs.h>
  35#include <linux/mlx5/fs.h>
  36#include <net/netdev_lock.h>
  37#include <net/switchdev.h>
  38#include <net/pkt_cls.h>
  39#include <net/act_api.h>
  40#include <net/devlink.h>
  41#include <net/ipv6_stubs.h>
  42
  43#include "eswitch.h"
  44#include "en.h"
  45#include "en/dim.h"
  46#include "en_rep.h"
  47#include "en/params.h"
  48#include "en/txrx.h"
  49#include "en_tc.h"
  50#include "en/rep/tc.h"
  51#include "en/rep/neigh.h"
  52#include "en/rep/bridge.h"
  53#include "en/devlink.h"
  54#include "fs_core.h"
  55#include "lib/mlx5.h"
  56#include "lib/devcom.h"
  57#include "lib/vxlan.h"
  58#define CREATE_TRACE_POINTS
  59#include "diag/en_rep_tracepoint.h"
  60#include "diag/reporter_vnic.h"
  61#include "en_accel/ipsec.h"
  62#include "en/tc/int_port.h"
  63#include "en/ptp.h"
  64#include "en/fs_ethtool.h"
  65
  66#define MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE \
  67	max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)
  68#define MLX5E_REP_PARAMS_DEF_NUM_CHANNELS 1
  69#define MLX5E_REP_PARAMS_DEF_LOG_RQ_SIZE 0x8
  70
  71static const char mlx5e_rep_driver_name[] = "mlx5e_rep";
  72
  73static void mlx5e_rep_get_drvinfo(struct net_device *dev,
  74				  struct ethtool_drvinfo *drvinfo)
  75{
  76	struct mlx5e_priv *priv = netdev_priv(dev);
  77	struct mlx5_core_dev *mdev = priv->mdev;
  78	int count;
  79
  80	strscpy(drvinfo->driver, mlx5e_rep_driver_name,
  81		sizeof(drvinfo->driver));
  82	count = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
  83			 "%d.%d.%04d (%.16s)", fw_rev_maj(mdev),
  84			 fw_rev_min(mdev), fw_rev_sub(mdev), mdev->board_id);
  85	if (count >= sizeof(drvinfo->fw_version))
  86		snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
  87			 "%d.%d.%04d", fw_rev_maj(mdev),
  88			 fw_rev_min(mdev), fw_rev_sub(mdev));
  89}
  90
  91static const struct counter_desc sw_rep_stats_desc[] = {
  92	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_packets) },
  93	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_bytes) },
  94	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_packets) },
  95	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_bytes) },
  96};
  97
  98static const struct counter_desc vport_rep_stats_desc[] = {
  99	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats, vport_rx_packets) },
 100	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats, vport_rx_bytes) },
 101	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats, vport_tx_packets) },
 102	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats, vport_tx_bytes) },
 103	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats,
 104			     rx_vport_rdma_unicast_packets) },
 105	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats, rx_vport_rdma_unicast_bytes) },
 106	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats,
 107			     tx_vport_rdma_unicast_packets) },
 108	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats, tx_vport_rdma_unicast_bytes) },
 109	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats,
 110			     rx_vport_rdma_multicast_packets) },
 111	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats,
 112			     rx_vport_rdma_multicast_bytes) },
 113	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats,
 114			     tx_vport_rdma_multicast_packets) },
 115	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats,
 116			     tx_vport_rdma_multicast_bytes) },
 117};
 118
 119static const struct counter_desc vport_rep_loopback_stats_desc[] = {
 120	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats,
 121			     vport_loopback_packets) },
 122	{ MLX5E_DECLARE_STAT(struct mlx5e_rep_stats,
 123			     vport_loopback_bytes) },
 124};
 125
 126#define NUM_VPORT_REP_SW_COUNTERS ARRAY_SIZE(sw_rep_stats_desc)
 127#define NUM_VPORT_REP_HW_COUNTERS ARRAY_SIZE(vport_rep_stats_desc)
 128#define NUM_VPORT_REP_LOOPBACK_COUNTERS(dev) \
 129	(MLX5_CAP_GEN(dev, vport_counter_local_loopback) ? \
 130	 ARRAY_SIZE(vport_rep_loopback_stats_desc) : 0)
 131
 132static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(sw_rep)
 133{
 134	return NUM_VPORT_REP_SW_COUNTERS;
 135}
 136
 137static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(sw_rep)
 138{
 139	int i;
 140
 141	for (i = 0; i < NUM_VPORT_REP_SW_COUNTERS; i++)
 142		ethtool_puts(data, sw_rep_stats_desc[i].format);
 143}
 144
 145static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(sw_rep)
 146{
 147	int i;
 148
 149	for (i = 0; i < NUM_VPORT_REP_SW_COUNTERS; i++)
 150		mlx5e_ethtool_put_stat(
 151			data, MLX5E_READ_CTR64_CPU(&priv->stats.sw,
 152						   sw_rep_stats_desc, i));
 153}
 154
 155static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(sw_rep)
 156{
 157	struct mlx5e_sw_stats *s = &priv->stats.sw;
 158	struct rtnl_link_stats64 stats64 = {};
 159
 160	memset(s, 0, sizeof(*s));
 161	mlx5e_fold_sw_stats64(priv, &stats64);
 162
 163	s->rx_packets = stats64.rx_packets;
 164	s->rx_bytes   = stats64.rx_bytes;
 165	s->tx_packets = stats64.tx_packets;
 166	s->tx_bytes   = stats64.tx_bytes;
 167	s->tx_queue_dropped = stats64.tx_dropped;
 168}
 169
 170static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(vport_rep)
 171{
 172	return NUM_VPORT_REP_HW_COUNTERS +
 173	       NUM_VPORT_REP_LOOPBACK_COUNTERS(priv->mdev);
 174}
 175
 176static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(vport_rep)
 177{
 178	int i;
 179
 180	for (i = 0; i < NUM_VPORT_REP_HW_COUNTERS; i++)
 181		ethtool_puts(data, vport_rep_stats_desc[i].format);
 182	for (i = 0; i < NUM_VPORT_REP_LOOPBACK_COUNTERS(priv->mdev); i++)
 183		ethtool_puts(data, vport_rep_loopback_stats_desc[i].format);
 184}
 185
 186static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(vport_rep)
 187{
 188	int i;
 189
 190	for (i = 0; i < NUM_VPORT_REP_HW_COUNTERS; i++)
 191		mlx5e_ethtool_put_stat(
 192			data, MLX5E_READ_CTR64_CPU(&priv->stats.rep_stats,
 193						   vport_rep_stats_desc, i));
 194	for (i = 0; i < NUM_VPORT_REP_LOOPBACK_COUNTERS(priv->mdev); i++)
 195		mlx5e_ethtool_put_stat(
 196			data,
 197			MLX5E_READ_CTR64_CPU(&priv->stats.rep_stats,
 198					     vport_rep_loopback_stats_desc, i));
 199}
 200
 201static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(vport_rep)
 202{
 203	struct mlx5e_rep_stats *rep_stats = &priv->stats.rep_stats;
 204	int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out);
 205	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
 206	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 207	struct mlx5_eswitch_rep *rep = rpriv->rep;
 208	u32 *out;
 209	int err;
 210
 211	out = kvzalloc(outlen, GFP_KERNEL);
 212	if (!out)
 213		return;
 214
 215	err = mlx5_core_query_vport_counter(esw->dev, 1, rep->vport - 1, 0, out);
 216	if (err) {
 217		netdev_warn(priv->netdev, "vport %d error %d reading stats\n",
 218			    rep->vport, err);
 219		goto out;
 220	}
 221
 222	#define MLX5_GET_CTR(p, x) \
 223		MLX5_GET64(query_vport_counter_out, p, x)
 224	/* flip tx/rx as we are reporting the counters for the switch vport */
 225	rep_stats->vport_rx_packets =
 226		MLX5_GET_CTR(out, transmitted_ib_unicast.packets) +
 227		MLX5_GET_CTR(out, transmitted_eth_unicast.packets) +
 228		MLX5_GET_CTR(out, transmitted_ib_multicast.packets) +
 229		MLX5_GET_CTR(out, transmitted_eth_multicast.packets) +
 230		MLX5_GET_CTR(out, transmitted_eth_broadcast.packets);
 231
 232	rep_stats->vport_tx_packets =
 233		MLX5_GET_CTR(out, received_ib_unicast.packets) +
 234		MLX5_GET_CTR(out, received_eth_unicast.packets) +
 235		MLX5_GET_CTR(out, received_ib_multicast.packets) +
 236		MLX5_GET_CTR(out, received_eth_multicast.packets) +
 237		MLX5_GET_CTR(out, received_eth_broadcast.packets);
 238
 239	rep_stats->vport_rx_bytes =
 240		MLX5_GET_CTR(out, transmitted_ib_unicast.octets) +
 241		MLX5_GET_CTR(out, transmitted_eth_unicast.octets) +
 242		MLX5_GET_CTR(out, transmitted_ib_multicast.octets) +
 243		MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
 244
 245	rep_stats->vport_tx_bytes =
 246		MLX5_GET_CTR(out, received_ib_unicast.octets) +
 247		MLX5_GET_CTR(out, received_eth_unicast.octets) +
 248		MLX5_GET_CTR(out, received_ib_multicast.octets) +
 249		MLX5_GET_CTR(out, received_eth_multicast.octets) +
 250		MLX5_GET_CTR(out, received_eth_broadcast.octets);
 251
 252	rep_stats->rx_vport_rdma_unicast_packets =
 253		MLX5_GET_CTR(out, transmitted_ib_unicast.packets);
 254	rep_stats->tx_vport_rdma_unicast_packets =
 255		MLX5_GET_CTR(out, received_ib_unicast.packets);
 256	rep_stats->rx_vport_rdma_unicast_bytes =
 257		MLX5_GET_CTR(out, transmitted_ib_unicast.octets);
 258	rep_stats->tx_vport_rdma_unicast_bytes =
 259		MLX5_GET_CTR(out, received_ib_unicast.octets);
 260	rep_stats->rx_vport_rdma_multicast_packets =
 261		MLX5_GET_CTR(out, transmitted_ib_multicast.packets);
 262	rep_stats->tx_vport_rdma_multicast_packets =
 263		MLX5_GET_CTR(out, received_ib_multicast.packets);
 264	rep_stats->rx_vport_rdma_multicast_bytes =
 265		MLX5_GET_CTR(out, transmitted_ib_multicast.octets);
 266	rep_stats->tx_vport_rdma_multicast_bytes =
 267		MLX5_GET_CTR(out, received_ib_multicast.octets);
 268
 269	if (MLX5_CAP_GEN(priv->mdev, vport_counter_local_loopback)) {
 270		rep_stats->vport_loopback_packets =
 271			MLX5_GET_CTR(out, local_loopback.packets);
 272		rep_stats->vport_loopback_bytes =
 273			MLX5_GET_CTR(out, local_loopback.octets);
 274	}
 275
 276out:
 277	kvfree(out);
 278}
 279
 280static int mlx5e_rep_query_aggr_q_counter(struct mlx5_core_dev *dev, int vport, void *out)
 281{
 282	u32 in[MLX5_ST_SZ_DW(query_q_counter_in)] = {};
 283
 284	MLX5_SET(query_q_counter_in, in, opcode, MLX5_CMD_OP_QUERY_Q_COUNTER);
 285	MLX5_SET(query_q_counter_in, in, other_vport, 1);
 286	MLX5_SET(query_q_counter_in, in, vport_number, vport);
 287	MLX5_SET(query_q_counter_in, in, aggregate, 1);
 288
 289	return mlx5_cmd_exec_inout(dev, query_q_counter, in, out);
 290}
 291
 292static void mlx5e_rep_update_vport_q_counter(struct mlx5e_priv *priv)
 293{
 294	struct mlx5e_rep_stats *rep_stats = &priv->stats.rep_stats;
 295	u32 out[MLX5_ST_SZ_DW(query_q_counter_out)] = {};
 296	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 297	struct mlx5_eswitch_rep *rep = rpriv->rep;
 298	int err;
 299
 300	if (!MLX5_CAP_GEN(priv->mdev, q_counter_other_vport) ||
 301	    !MLX5_CAP_GEN(priv->mdev, q_counter_aggregation))
 302		return;
 303
 304	err = mlx5e_rep_query_aggr_q_counter(priv->mdev, rep->vport, out);
 305	if (err) {
 306		netdev_warn(priv->netdev, "failed reading stats on vport %d, error %d\n",
 307			    rep->vport, err);
 308		return;
 309	}
 310
 311	rep_stats->rx_vport_out_of_buffer = MLX5_GET(query_q_counter_out, out, out_of_buffer);
 312}
 313
 314static void mlx5e_rep_get_strings(struct net_device *dev,
 315				  u32 stringset, u8 *data)
 316{
 317	struct mlx5e_priv *priv = netdev_priv(dev);
 318
 319	switch (stringset) {
 320	case ETH_SS_STATS:
 321		mlx5e_stats_fill_strings(priv, data);
 322		break;
 323	}
 324}
 325
 326static void mlx5e_rep_get_ethtool_stats(struct net_device *dev,
 327					struct ethtool_stats *stats, u64 *data)
 328{
 329	struct mlx5e_priv *priv = netdev_priv(dev);
 330
 331	mlx5e_ethtool_get_ethtool_stats(priv, stats, data);
 332}
 333
 334static int mlx5e_rep_get_sset_count(struct net_device *dev, int sset)
 335{
 336	struct mlx5e_priv *priv = netdev_priv(dev);
 337
 338	switch (sset) {
 339	case ETH_SS_STATS:
 340		return mlx5e_stats_total_num(priv);
 341	default:
 342		return -EOPNOTSUPP;
 343	}
 344}
 345
 346static void
 347mlx5e_rep_get_ringparam(struct net_device *dev,
 348			struct ethtool_ringparam *param,
 349			struct kernel_ethtool_ringparam *kernel_param,
 350			struct netlink_ext_ack *extack)
 351{
 352	struct mlx5e_priv *priv = netdev_priv(dev);
 353
 354	mlx5e_ethtool_get_ringparam(priv, param, kernel_param);
 355}
 356
 357static int
 358mlx5e_rep_set_ringparam(struct net_device *dev,
 359			struct ethtool_ringparam *param,
 360			struct kernel_ethtool_ringparam *kernel_param,
 361			struct netlink_ext_ack *extack)
 362{
 363	struct mlx5e_priv *priv = netdev_priv(dev);
 364
 365	return mlx5e_ethtool_set_ringparam(priv, param, extack);
 366}
 367
 368static void mlx5e_rep_get_channels(struct net_device *dev,
 369				   struct ethtool_channels *ch)
 370{
 371	struct mlx5e_priv *priv = netdev_priv(dev);
 372
 373	mlx5e_ethtool_get_channels(priv, ch);
 374}
 375
 376static int mlx5e_rep_set_channels(struct net_device *dev,
 377				  struct ethtool_channels *ch)
 378{
 379	struct mlx5e_priv *priv = netdev_priv(dev);
 380
 381	return mlx5e_ethtool_set_channels(priv, ch);
 382}
 383
 384static int mlx5e_rep_get_coalesce(struct net_device *netdev,
 385				  struct ethtool_coalesce *coal,
 386				  struct kernel_ethtool_coalesce *kernel_coal,
 387				  struct netlink_ext_ack *extack)
 388{
 389	struct mlx5e_priv *priv = netdev_priv(netdev);
 390
 391	return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal, extack);
 392}
 393
 394static int mlx5e_rep_set_coalesce(struct net_device *netdev,
 395				  struct ethtool_coalesce *coal,
 396				  struct kernel_ethtool_coalesce *kernel_coal,
 397				  struct netlink_ext_ack *extack)
 398{
 399	struct mlx5e_priv *priv = netdev_priv(netdev);
 400
 401	return mlx5e_ethtool_set_coalesce(priv, coal, kernel_coal, extack);
 402}
 403
 404static u32 mlx5e_rep_get_rxfh_key_size(struct net_device *netdev)
 405{
 406	struct mlx5e_priv *priv = netdev_priv(netdev);
 407
 408	return mlx5e_ethtool_get_rxfh_key_size(priv);
 409}
 410
 411static u32 mlx5e_rep_get_rxfh_indir_size(struct net_device *netdev)
 412{
 413	struct mlx5e_priv *priv = netdev_priv(netdev);
 414
 415	return mlx5e_ethtool_get_rxfh_indir_size(priv);
 416}
 417
 418static const struct ethtool_ops mlx5e_rep_ethtool_ops = {
 419	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
 420				     ETHTOOL_COALESCE_MAX_FRAMES |
 421				     ETHTOOL_COALESCE_USE_ADAPTIVE,
 422	.get_drvinfo	   = mlx5e_rep_get_drvinfo,
 423	.get_link	   = ethtool_op_get_link,
 424	.get_strings       = mlx5e_rep_get_strings,
 425	.get_sset_count    = mlx5e_rep_get_sset_count,
 426	.get_ethtool_stats = mlx5e_rep_get_ethtool_stats,
 427	.get_ringparam     = mlx5e_rep_get_ringparam,
 428	.set_ringparam     = mlx5e_rep_set_ringparam,
 429	.get_channels      = mlx5e_rep_get_channels,
 430	.set_channels      = mlx5e_rep_set_channels,
 431	.get_coalesce      = mlx5e_rep_get_coalesce,
 432	.set_coalesce      = mlx5e_rep_set_coalesce,
 433	.get_per_queue_coalesce = mlx5e_get_per_queue_coalesce,
 434	.set_per_queue_coalesce = mlx5e_set_per_queue_coalesce,
 435	.get_rxfh_key_size   = mlx5e_rep_get_rxfh_key_size,
 436	.get_rxfh_indir_size = mlx5e_rep_get_rxfh_indir_size,
 437};
 438
 439static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw,
 440				 struct mlx5_eswitch_rep *rep)
 441{
 442	struct mlx5e_rep_sq *rep_sq, *tmp;
 443	struct mlx5e_rep_sq_peer *sq_peer;
 444	struct mlx5e_rep_priv *rpriv;
 445	unsigned long i;
 446
 447	if (esw->mode != MLX5_ESWITCH_OFFLOADS)
 448		return;
 449
 450	rpriv = mlx5e_rep_to_rep_priv(rep);
 451	list_for_each_entry_safe(rep_sq, tmp, &rpriv->vport_sqs_list, list) {
 452		mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule);
 453		xa_for_each(&rep_sq->sq_peer, i, sq_peer) {
 454			if (sq_peer->rule)
 455				mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule);
 456
 457			xa_erase(&rep_sq->sq_peer, i);
 458			kfree(sq_peer);
 459		}
 460
 461		xa_destroy(&rep_sq->sq_peer);
 462		list_del(&rep_sq->list);
 463		kfree(rep_sq);
 464	}
 465}
 466
 467static int mlx5e_sqs2vport_add_peers_rules(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep,
 468					   struct mlx5e_rep_sq *rep_sq, int i)
 469{
 470	struct mlx5_flow_handle *flow_rule;
 471	struct mlx5_devcom_comp_dev *tmp;
 472	struct mlx5_eswitch *peer_esw;
 473
 474	mlx5_devcom_for_each_peer_entry(esw->devcom, peer_esw, tmp) {
 475		u16 peer_rule_idx = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
 476		struct mlx5e_rep_sq_peer *sq_peer;
 477		int err;
 478
 479		sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL);
 480		if (!sq_peer)
 481			return -ENOMEM;
 482
 483		flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw,
 484								rep, rep_sq->sqn);
 485		if (IS_ERR(flow_rule)) {
 486			kfree(sq_peer);
 487			return PTR_ERR(flow_rule);
 488		}
 489
 490		sq_peer->rule = flow_rule;
 491		sq_peer->peer = peer_esw;
 492		err = xa_insert(&rep_sq->sq_peer, peer_rule_idx, sq_peer, GFP_KERNEL);
 493		if (err) {
 494			kfree(sq_peer);
 495			mlx5_eswitch_del_send_to_vport_rule(flow_rule);
 496			return err;
 497		}
 498	}
 499
 500	return 0;
 501}
 502
 503static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw,
 504				 struct mlx5_eswitch_rep *rep,
 505				 u32 *sqns_array, int sqns_num)
 506{
 507	struct mlx5_flow_handle *flow_rule;
 508	struct mlx5e_rep_priv *rpriv;
 509	struct mlx5e_rep_sq *rep_sq;
 510	bool devcom_locked = false;
 511	int err;
 512	int i;
 513
 514	if (esw->mode != MLX5_ESWITCH_OFFLOADS)
 515		return 0;
 516
 517	rpriv = mlx5e_rep_to_rep_priv(rep);
 518
 519	if (mlx5_devcom_comp_is_ready(esw->devcom) &&
 520	    mlx5_devcom_for_each_peer_begin(esw->devcom))
 521		devcom_locked = true;
 522
 523	for (i = 0; i < sqns_num; i++) {
 524		rep_sq = kzalloc(sizeof(*rep_sq), GFP_KERNEL);
 525		if (!rep_sq) {
 526			err = -ENOMEM;
 527			goto out_err;
 528		}
 529
 530		/* Add re-inject rule to the PF/representor sqs */
 531		flow_rule = mlx5_eswitch_add_send_to_vport_rule(esw, esw, rep,
 532								sqns_array[i]);
 533		if (IS_ERR(flow_rule)) {
 534			err = PTR_ERR(flow_rule);
 535			kfree(rep_sq);
 536			goto out_err;
 537		}
 538		rep_sq->send_to_vport_rule = flow_rule;
 539		rep_sq->sqn = sqns_array[i];
 540
 541		xa_init(&rep_sq->sq_peer);
 542		if (devcom_locked) {
 543			err = mlx5e_sqs2vport_add_peers_rules(esw, rep, rep_sq, i);
 544			if (err) {
 545				mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule);
 546				xa_destroy(&rep_sq->sq_peer);
 547				kfree(rep_sq);
 548				goto out_err;
 549			}
 550		}
 551
 552		list_add(&rep_sq->list, &rpriv->vport_sqs_list);
 553	}
 554
 555	if (devcom_locked)
 556		mlx5_devcom_for_each_peer_end(esw->devcom);
 557
 558	return 0;
 559
 560out_err:
 561	mlx5e_sqs2vport_stop(esw, rep);
 562
 563	if (devcom_locked)
 564		mlx5_devcom_for_each_peer_end(esw->devcom);
 565
 566	return err;
 567}
 568
 569static int
 570mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
 571{
 572	int sqs_per_channel = mlx5e_get_dcb_num_tc(&priv->channels.params);
 573	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
 574	bool is_uplink_rep = mlx5e_is_uplink_rep(priv);
 575	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 576	struct mlx5_eswitch_rep *rep = rpriv->rep;
 577	int n, tc, nch, num_sqs = 0;
 578	struct mlx5e_channel *c;
 579	int err = -ENOMEM;
 580	bool ptp_sq;
 581	u32 *sqs;
 582
 583	ptp_sq = !!(priv->channels.ptp &&
 584		    MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_TX_PORT_TS));
 585	nch = priv->channels.num + ptp_sq;
 586	/* +2 for xdpsqs, they don't exist on the ptp channel but will not be
 587	 * counted for by num_sqs.
 588	 */
 589	if (is_uplink_rep)
 590		sqs_per_channel += 2;
 591
 592	sqs = kvcalloc(nch * sqs_per_channel, sizeof(*sqs), GFP_KERNEL);
 593	if (!sqs)
 594		goto out;
 595
 596	for (n = 0; n < priv->channels.num; n++) {
 597		c = priv->channels.c[n];
 598		for (tc = 0; tc < c->num_tc; tc++)
 599			sqs[num_sqs++] = c->sq[tc].sqn;
 600
 601		if (is_uplink_rep) {
 602			if (c->xdp)
 603				sqs[num_sqs++] = c->rq_xdpsq.sqn;
 604
 605			if (c->xdpsq)
 606				sqs[num_sqs++] = c->xdpsq->sqn;
 607		}
 608	}
 609	if (ptp_sq) {
 610		struct mlx5e_ptp *ptp_ch = priv->channels.ptp;
 611
 612		for (tc = 0; tc < ptp_ch->num_tc; tc++)
 613			sqs[num_sqs++] = ptp_ch->ptpsq[tc].txqsq.sqn;
 614	}
 615
 616	err = mlx5e_sqs2vport_start(esw, rep, sqs, num_sqs);
 617	kvfree(sqs);
 618
 619out:
 620	if (err)
 621		netdev_warn(priv->netdev, "Failed to add SQs FWD rules %d\n", err);
 622	return err;
 623}
 624
 625static void
 626mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
 627{
 628	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
 629	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 630	struct mlx5_eswitch_rep *rep = rpriv->rep;
 631
 632	mlx5e_sqs2vport_stop(esw, rep);
 633}
 634
 635static int
 636mlx5e_rep_add_meta_tunnel_rule(struct mlx5e_priv *priv)
 637{
 638	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
 639	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 640	struct mlx5_eswitch_rep *rep = rpriv->rep;
 641	struct mlx5_flow_handle *flow_rule;
 642	struct mlx5_flow_group *g;
 643
 644	g = esw->fdb_table.offloads.send_to_vport_meta_grp;
 645	if (!g)
 646		return 0;
 647
 648	flow_rule = mlx5_eswitch_add_send_to_vport_meta_rule(esw, rep->vport);
 649	if (IS_ERR(flow_rule))
 650		return PTR_ERR(flow_rule);
 651
 652	rpriv->send_to_vport_meta_rule = flow_rule;
 653
 654	return 0;
 655}
 656
 657static void
 658mlx5e_rep_del_meta_tunnel_rule(struct mlx5e_priv *priv)
 659{
 660	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 661
 662	if (rpriv->send_to_vport_meta_rule)
 663		mlx5_eswitch_del_send_to_vport_meta_rule(rpriv->send_to_vport_meta_rule);
 664}
 665
 666void mlx5e_rep_activate_channels(struct mlx5e_priv *priv)
 667{
 668	mlx5e_add_sqs_fwd_rules(priv);
 669	mlx5e_rep_add_meta_tunnel_rule(priv);
 670}
 671
 672void mlx5e_rep_deactivate_channels(struct mlx5e_priv *priv)
 673{
 674	mlx5e_rep_del_meta_tunnel_rule(priv);
 675	mlx5e_remove_sqs_fwd_rules(priv);
 676}
 677
 678static int mlx5e_rep_open(struct net_device *dev)
 679{
 680	struct mlx5e_priv *priv = netdev_priv(dev);
 681	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 682	struct mlx5_eswitch_rep *rep = rpriv->rep;
 683	int err;
 684
 685	mutex_lock(&priv->state_lock);
 686	err = mlx5e_open_locked(dev);
 687	if (err)
 688		goto unlock;
 689
 690	if (!mlx5_modify_vport_admin_state(priv->mdev,
 691					   MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
 692					   rep->vport, 1,
 693					   MLX5_VPORT_ADMIN_STATE_UP))
 694		netif_carrier_on(dev);
 695
 696unlock:
 697	mutex_unlock(&priv->state_lock);
 698	return err;
 699}
 700
 701static int mlx5e_rep_close(struct net_device *dev)
 702{
 703	struct mlx5e_priv *priv = netdev_priv(dev);
 704	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 705	struct mlx5_eswitch_rep *rep = rpriv->rep;
 706	int ret;
 707
 708	mutex_lock(&priv->state_lock);
 709	mlx5_modify_vport_admin_state(priv->mdev,
 710				      MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
 711				      rep->vport, 1,
 712				      MLX5_VPORT_ADMIN_STATE_DOWN);
 713	ret = mlx5e_close_locked(dev);
 714	mutex_unlock(&priv->state_lock);
 715	return ret;
 716}
 717
 718bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
 719{
 720	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 721	struct mlx5_eswitch_rep *rep;
 722
 723	if (!MLX5_ESWITCH_MANAGER(priv->mdev))
 724		return false;
 725
 726	if (!rpriv) /* non vport rep mlx5e instances don't use this field */
 727		return false;
 728
 729	rep = rpriv->rep;
 730	return (rep->vport == MLX5_VPORT_UPLINK);
 731}
 732
 733bool mlx5e_rep_has_offload_stats(const struct net_device *dev, int attr_id)
 734{
 735	switch (attr_id) {
 736	case IFLA_OFFLOAD_XSTATS_CPU_HIT:
 737			return true;
 738	}
 739
 740	return false;
 741}
 742
 743static int
 744mlx5e_get_sw_stats64(const struct net_device *dev,
 745		     struct rtnl_link_stats64 *stats)
 746{
 747	struct mlx5e_priv *priv = netdev_priv(dev);
 748
 749	mlx5e_fold_sw_stats64(priv, stats);
 750	return 0;
 751}
 752
 753int mlx5e_rep_get_offload_stats(int attr_id, const struct net_device *dev,
 754				void *sp)
 755{
 756	switch (attr_id) {
 757	case IFLA_OFFLOAD_XSTATS_CPU_HIT:
 758		return mlx5e_get_sw_stats64(dev, sp);
 759	}
 760
 761	return -EINVAL;
 762}
 763
 764static void
 765mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
 766{
 767	struct mlx5e_priv *priv = netdev_priv(dev);
 768
 769	/* update HW stats in background for next time */
 770	mlx5e_queue_update_stats(priv);
 771	mlx5e_stats_copy_rep_stats(stats, &priv->stats.rep_stats);
 772}
 773
 774static int mlx5e_rep_change_mtu(struct net_device *netdev, int new_mtu)
 775{
 776	return mlx5e_change_mtu(netdev, new_mtu, NULL);
 777}
 778
 779static int mlx5e_rep_change_carrier(struct net_device *dev, bool new_carrier)
 780{
 781	struct mlx5e_priv *priv = netdev_priv(dev);
 782	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 783	struct mlx5_eswitch_rep *rep = rpriv->rep;
 784	int err;
 785
 786	if (new_carrier) {
 787		err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
 788						    rep->vport, 1, MLX5_VPORT_ADMIN_STATE_UP);
 789		if (err)
 790			return err;
 791		netif_carrier_on(dev);
 792	} else {
 793		err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
 794						    rep->vport, 1, MLX5_VPORT_ADMIN_STATE_DOWN);
 795		if (err)
 796			return err;
 797		netif_carrier_off(dev);
 798	}
 799	return 0;
 800}
 801
 802static const struct net_device_ops mlx5e_netdev_ops_rep = {
 803	.ndo_open                = mlx5e_rep_open,
 804	.ndo_stop                = mlx5e_rep_close,
 805	.ndo_start_xmit          = mlx5e_xmit,
 806	.ndo_setup_tc            = mlx5e_rep_setup_tc,
 807	.ndo_set_mac_address	 = eth_mac_addr,
 808	.ndo_get_stats64         = mlx5e_rep_get_stats,
 809	.ndo_has_offload_stats	 = mlx5e_rep_has_offload_stats,
 810	.ndo_get_offload_stats	 = mlx5e_rep_get_offload_stats,
 811	.ndo_change_mtu          = mlx5e_rep_change_mtu,
 812	.ndo_change_carrier      = mlx5e_rep_change_carrier,
 813};
 814
 815bool mlx5e_eswitch_uplink_rep(const struct net_device *netdev)
 816{
 817	return netdev->netdev_ops == &mlx5e_netdev_ops &&
 818	       mlx5e_is_uplink_rep(netdev_priv(netdev));
 819}
 820
 821bool mlx5e_eswitch_vf_rep(const struct net_device *netdev)
 822{
 823	return netdev->netdev_ops == &mlx5e_netdev_ops_rep;
 824}
 825
 826/* One indirect TIR set for outer. Inner not supported in reps. */
 827#define REP_NUM_INDIR_TIRS MLX5E_NUM_INDIR_TIRS
 828
 829static int mlx5e_rep_max_nch_limit(struct mlx5_core_dev *mdev)
 830{
 831	int max_tir_num = 1 << MLX5_CAP_GEN(mdev, log_max_tir);
 832	int num_vports = mlx5_eswitch_get_total_vports(mdev);
 833
 834	return (max_tir_num - mlx5e_get_pf_num_tirs(mdev)
 835		- (num_vports * REP_NUM_INDIR_TIRS)) / num_vports;
 836}
 837
 838static void mlx5e_build_rep_params(struct net_device *netdev)
 839{
 840	const bool take_rtnl = netdev->reg_state == NETREG_REGISTERED;
 841	struct mlx5e_priv *priv = netdev_priv(netdev);
 842	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 843	struct mlx5_eswitch_rep *rep = rpriv->rep;
 844	struct mlx5_core_dev *mdev = priv->mdev;
 845	struct mlx5e_params *params;
 846
 847	params = &priv->channels.params;
 848
 849	params->num_channels = MLX5E_REP_PARAMS_DEF_NUM_CHANNELS;
 850	params->hard_mtu    = MLX5E_ETH_HARD_MTU;
 851	params->sw_mtu      = netdev->mtu;
 852
 853	/* SQ */
 854	if (rep->vport == MLX5_VPORT_UPLINK)
 855		params->log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
 856	else
 857		params->log_sq_size = MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE;
 858
 859	/* RQ */
 860	mlx5e_build_rq_params(mdev, params);
 861	if (!mlx5e_is_uplink_rep(priv) && mlx5_core_is_ecpf(mdev))
 862		params->log_rq_mtu_frames = MLX5E_REP_PARAMS_DEF_LOG_RQ_SIZE;
 863
 864	/* If netdev is already registered (e.g. move from nic profile to uplink,
 865	 * RTNL lock must be held before triggering netdev notifiers.
 866	 */
 867	if (take_rtnl)
 868		rtnl_lock();
 869	/* update XDP supported features */
 870	mlx5e_set_xdp_feature(priv);
 871	if (take_rtnl)
 872		rtnl_unlock();
 873
 874	/* CQ moderation params */
 875	params->rx_dim_enabled = MLX5_CAP_GEN(mdev, cq_moderation);
 876	params->rx_moder_use_cqe_mode = !!MLX5_CAP_GEN(mdev, cq_period_start_from_cqe);
 877
 878	params->mqprio.num_tc       = 1;
 879	if (rep->vport != MLX5_VPORT_UPLINK)
 880		params->vlan_strip_disable = true;
 881
 882	mlx5_query_min_inline(mdev, &params->tx_min_inline_mode);
 883}
 884
 885static void mlx5e_build_rep_netdev(struct net_device *netdev,
 886				   struct mlx5_core_dev *mdev)
 887{
 888	SET_NETDEV_DEV(netdev, mdev->device);
 889	netdev->netdev_ops = &mlx5e_netdev_ops_rep;
 890	netdev->request_ops_lock = true;
 891	netdev_lockdep_set_classes(netdev);
 892	eth_hw_addr_random(netdev);
 893	netdev->ethtool_ops = &mlx5e_rep_ethtool_ops;
 894
 895	netdev->watchdog_timeo    = 15 * HZ;
 896	if (mlx5_core_is_ecpf(mdev))
 897		netdev->tx_queue_len = 1 << MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE;
 898
 899#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
 900	netdev->hw_features    |= NETIF_F_HW_TC;
 901#endif
 902	netdev->hw_features    |= NETIF_F_SG;
 903	netdev->hw_features    |= NETIF_F_IP_CSUM;
 904	netdev->hw_features    |= NETIF_F_IPV6_CSUM;
 905	netdev->hw_features    |= NETIF_F_GRO;
 906	netdev->hw_features    |= NETIF_F_TSO;
 907	netdev->hw_features    |= NETIF_F_TSO6;
 908	netdev->hw_features    |= NETIF_F_RXCSUM;
 909
 910	netdev->features |= netdev->hw_features;
 911
 912	netdev->netns_immutable = true;
 913}
 914
 915static int mlx5e_init_rep(struct mlx5_core_dev *mdev,
 916			  struct net_device *netdev)
 917{
 918	struct mlx5e_priv *priv = netdev_priv(netdev);
 919
 920	priv->fs =
 921		mlx5e_fs_init(priv->profile, mdev,
 922			      !test_bit(MLX5E_STATE_DESTROYING, &priv->state),
 923			      priv->dfs_root);
 924	if (!priv->fs) {
 925		netdev_err(priv->netdev, "FS allocation failed\n");
 926		return -ENOMEM;
 927	}
 928
 929	mlx5e_build_rep_params(netdev);
 930	mlx5e_timestamp_init(priv);
 931
 932	return 0;
 933}
 934
 935static int mlx5e_init_ul_rep(struct mlx5_core_dev *mdev,
 936			     struct net_device *netdev)
 937{
 938	struct mlx5e_priv *priv = netdev_priv(netdev);
 939
 940	priv->dfs_root = debugfs_create_dir("nic",
 941					    mlx5_debugfs_get_dev_root(mdev));
 942
 943	priv->fs = mlx5e_fs_init(priv->profile, mdev,
 944				 !test_bit(MLX5E_STATE_DESTROYING, &priv->state),
 945				 priv->dfs_root);
 946	if (!priv->fs) {
 947		netdev_err(priv->netdev, "FS allocation failed\n");
 948		debugfs_remove_recursive(priv->dfs_root);
 949		return -ENOMEM;
 950	}
 951
 952	mlx5e_vxlan_set_netdev_info(priv);
 953	mlx5e_build_rep_params(netdev);
 954	mlx5e_timestamp_init(priv);
 955	return 0;
 956}
 957
 958static void mlx5e_cleanup_rep(struct mlx5e_priv *priv)
 959{
 960	mlx5e_fs_cleanup(priv->fs);
 961	debugfs_remove_recursive(priv->dfs_root);
 962	priv->fs = NULL;
 963}
 964
 965static int mlx5e_create_rep_ttc_table(struct mlx5e_priv *priv)
 966{
 967	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 968	struct mlx5_eswitch_rep *rep = rpriv->rep;
 969	struct ttc_params ttc_params = {};
 970	int err;
 971
 972	mlx5e_fs_set_ns(priv->fs,
 973			mlx5_get_flow_namespace(priv->mdev,
 974						MLX5_FLOW_NAMESPACE_KERNEL), false);
 975
 976	/* The inner_ttc in the ttc params is intentionally not set */
 977	mlx5e_set_ttc_params(priv->fs, priv->rx_res, &ttc_params, false, false);
 978
 979	if (rep->vport != MLX5_VPORT_UPLINK)
 980		/* To give uplik rep TTC a lower level for chaining from root ft */
 981		ttc_params.ft_attr.level = MLX5E_TTC_FT_LEVEL + 1;
 982
 983	mlx5e_fs_set_ttc(priv->fs, mlx5_create_ttc_table(priv->mdev, &ttc_params), false);
 984	if (IS_ERR(mlx5e_fs_get_ttc(priv->fs, false))) {
 985		err = PTR_ERR(mlx5e_fs_get_ttc(priv->fs, false));
 986		netdev_err(priv->netdev, "Failed to create rep ttc table, err=%d\n",
 987			   err);
 988		return err;
 989	}
 990	return 0;
 991}
 992
 993static int mlx5e_create_rep_root_ft(struct mlx5e_priv *priv)
 994{
 995	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 996	struct mlx5_eswitch_rep *rep = rpriv->rep;
 997	struct mlx5_flow_table_attr ft_attr = {};
 998	struct mlx5_flow_namespace *ns;
 999	int err = 0;
1000
1001	if (rep->vport != MLX5_VPORT_UPLINK) {
1002		/* non uplik reps will skip any bypass tables and go directly to
1003		 * their own ttc
1004		 */
1005		rpriv->root_ft = mlx5_get_ttc_flow_table(mlx5e_fs_get_ttc(priv->fs, false));
1006		return 0;
1007	}
1008
1009	/* uplink root ft will be used to auto chain, to ethtool or ttc tables */
1010	ns = mlx5_get_flow_namespace(priv->mdev, MLX5_FLOW_NAMESPACE_OFFLOADS);
1011	if (!ns) {
1012		netdev_err(priv->netdev, "Failed to get reps offloads namespace\n");
1013		return -EOPNOTSUPP;
1014	}
1015
1016	ft_attr.max_fte = 0; /* Empty table, miss rule will always point to next table */
1017	ft_attr.prio = 1;
1018	ft_attr.level = 1;
1019
1020	rpriv->root_ft = mlx5_create_flow_table(ns, &ft_attr);
1021	if (IS_ERR(rpriv->root_ft)) {
1022		err = PTR_ERR(rpriv->root_ft);
1023		rpriv->root_ft = NULL;
1024	}
1025
1026	return err;
1027}
1028
1029static void mlx5e_destroy_rep_root_ft(struct mlx5e_priv *priv)
1030{
1031	struct mlx5e_rep_priv *rpriv = priv->ppriv;
1032	struct mlx5_eswitch_rep *rep = rpriv->rep;
1033
1034	if (rep->vport != MLX5_VPORT_UPLINK)
1035		return;
1036	mlx5_destroy_flow_table(rpriv->root_ft);
1037}
1038
1039static int mlx5e_create_rep_vport_rx_rule(struct mlx5e_priv *priv)
1040{
1041	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
1042	struct mlx5e_rep_priv *rpriv = priv->ppriv;
1043	struct mlx5_eswitch_rep *rep = rpriv->rep;
1044	struct mlx5_flow_handle *flow_rule;
1045	struct mlx5_flow_destination dest;
1046
1047	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1048	dest.ft = rpriv->root_ft;
1049
1050	flow_rule = mlx5_eswitch_create_vport_rx_rule(esw, rep->vport, &dest);
1051	if (IS_ERR(flow_rule))
1052		return PTR_ERR(flow_rule);
1053	rpriv->vport_rx_rule = flow_rule;
1054	return 0;
1055}
1056
1057static void rep_vport_rx_rule_destroy(struct mlx5e_priv *priv)
1058{
1059	struct mlx5e_rep_priv *rpriv = priv->ppriv;
1060
1061	if (!rpriv->vport_rx_rule)
1062		return;
1063
1064	mlx5_del_flow_rules(rpriv->vport_rx_rule);
1065	rpriv->vport_rx_rule = NULL;
1066}
1067
1068int mlx5e_rep_bond_update(struct mlx5e_priv *priv, bool cleanup)
1069{
1070	rep_vport_rx_rule_destroy(priv);
1071
1072	return cleanup ? 0 : mlx5e_create_rep_vport_rx_rule(priv);
1073}
1074
1075static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
1076{
1077	struct mlx5_core_dev *mdev = priv->mdev;
1078	int err;
1079
1080	mlx5e_fs_init_l2_addr(priv->fs, priv->netdev);
1081
1082	err = mlx5e_open_drop_rq(priv, &priv->drop_rq);
1083	if (err) {
1084		mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
1085		goto err_free_fs;
1086	}
1087
1088	priv->rx_res = mlx5e_rx_res_create(priv->mdev, 0, priv->max_nch, priv->drop_rq.rqn,
1089					   &priv->channels.params.packet_merge,
1090					   priv->channels.params.num_channels);
1091	if (IS_ERR(priv->rx_res)) {
1092		err = PTR_ERR(priv->rx_res);
1093		mlx5_core_err(mdev, "Create rx resources failed, err=%d\n", err);
1094		goto err_close_drop_rq;
1095	}
1096
1097	err = mlx5e_create_rep_ttc_table(priv);
1098	if (err)
1099		goto err_destroy_rx_res;
1100
1101	err = mlx5e_create_rep_root_ft(priv);
1102	if (err)
1103		goto err_destroy_ttc_table;
1104
1105	err = mlx5e_create_rep_vport_rx_rule(priv);
1106	if (err)
1107		goto err_destroy_root_ft;
1108
1109	mlx5e_ethtool_init_steering(priv->fs);
1110
1111	return 0;
1112
1113err_destroy_root_ft:
1114	mlx5e_destroy_rep_root_ft(priv);
1115err_destroy_ttc_table:
1116	mlx5_destroy_ttc_table(mlx5e_fs_get_ttc(priv->fs, false));
1117err_destroy_rx_res:
1118	mlx5e_rx_res_destroy(priv->rx_res);
1119	priv->rx_res = ERR_PTR(-EINVAL);
1120err_close_drop_rq:
1121	mlx5e_close_drop_rq(&priv->drop_rq);
1122err_free_fs:
1123	mlx5e_fs_cleanup(priv->fs);
1124	priv->fs = NULL;
1125	return err;
1126}
1127
1128static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
1129{
1130	mlx5e_ethtool_cleanup_steering(priv->fs);
1131	rep_vport_rx_rule_destroy(priv);
1132	mlx5e_destroy_rep_root_ft(priv);
1133	mlx5_destroy_ttc_table(mlx5e_fs_get_ttc(priv->fs, false));
1134	mlx5e_rx_res_destroy(priv->rx_res);
1135	priv->rx_res = ERR_PTR(-EINVAL);
1136	mlx5e_close_drop_rq(&priv->drop_rq);
1137}
1138
1139static void mlx5e_rep_mpesw_work(struct work_struct *work)
1140{
1141	struct mlx5_rep_uplink_priv *uplink_priv =
1142		container_of(work, struct mlx5_rep_uplink_priv,
1143			     mpesw_work);
1144	struct mlx5e_rep_priv *rpriv =
1145		container_of(uplink_priv, struct mlx5e_rep_priv,
1146			     uplink_priv);
1147	struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
1148
1149	rep_vport_rx_rule_destroy(priv);
1150	mlx5e_create_rep_vport_rx_rule(priv);
1151}
1152
1153static int mlx5e_init_ul_rep_rx(struct mlx5e_priv *priv)
1154{
1155	struct mlx5e_rep_priv *rpriv = priv->ppriv;
1156	int err;
1157
1158	mlx5e_create_q_counters(priv);
1159	err = mlx5e_init_rep_rx(priv);
1160	if (err)
1161		goto out;
1162
1163	mlx5e_tc_int_port_init_rep_rx(priv);
1164
1165	INIT_WORK(&rpriv->uplink_priv.mpesw_work, mlx5e_rep_mpesw_work);
1166
1167out:
1168	return err;
1169}
1170
1171static void mlx5e_cleanup_ul_rep_rx(struct mlx5e_priv *priv)
1172{
1173	struct mlx5e_rep_priv *rpriv = priv->ppriv;
1174
1175	cancel_work_sync(&rpriv->uplink_priv.mpesw_work);
1176	mlx5e_tc_int_port_cleanup_rep_rx(priv);
1177	mlx5e_cleanup_rep_rx(priv);
1178	mlx5e_destroy_q_counters(priv);
1179}
1180
1181static int mlx5e_init_uplink_rep_tx(struct mlx5e_rep_priv *rpriv)
1182{
1183	struct mlx5_rep_uplink_priv *uplink_priv;
1184	struct net_device *netdev;
1185	struct mlx5e_priv *priv;
1186	int err;
1187
1188	netdev = rpriv->netdev;
1189	priv = netdev_priv(netdev);
1190	uplink_priv = &rpriv->uplink_priv;
1191
1192	err = mlx5e_rep_tc_init(rpriv);
1193	if (err)
1194		return err;
1195
1196	mlx5_init_port_tun_entropy(&uplink_priv->tun_entropy, priv->mdev);
1197
1198	mlx5e_rep_bond_init(rpriv);
1199	err = mlx5e_rep_tc_netdevice_event_register(rpriv);
1200	if (err) {
1201		mlx5_core_err(priv->mdev, "Failed to register netdev notifier, err: %d\n",
1202			      err);
1203		goto err_event_reg;
1204	}
1205
1206	return 0;
1207
1208err_event_reg:
1209	mlx5e_rep_bond_cleanup(rpriv);
1210	mlx5e_rep_tc_cleanup(rpriv);
1211	return err;
1212}
1213
1214static void mlx5e_cleanup_uplink_rep_tx(struct mlx5e_rep_priv *rpriv)
1215{
1216	mlx5e_rep_tc_netdevice_event_unregister(rpriv);
1217	mlx5e_rep_bond_cleanup(rpriv);
1218	mlx5e_rep_tc_cleanup(rpriv);
1219}
1220
1221static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
1222{
1223	struct mlx5e_rep_priv *rpriv = priv->ppriv;
1224	int err;
1225
1226	err = mlx5e_rep_neigh_init(rpriv);
1227	if (err)
1228		goto err_neigh_init;
1229
1230	if (rpriv->rep->vport == MLX5_VPORT_UPLINK) {
1231		err = mlx5e_init_uplink_rep_tx(rpriv);
1232		if (err)
1233			goto err_init_tx;
1234	}
1235
1236	err = mlx5e_tc_ht_init(&rpriv->tc_ht);
1237	if (err)
1238		goto err_ht_init;
1239
1240	return 0;
1241
1242err_ht_init:
1243	if (rpriv->rep->vport == MLX5_VPORT_UPLINK)
1244		mlx5e_cleanup_uplink_rep_tx(rpriv);
1245err_init_tx:
1246	mlx5e_rep_neigh_cleanup(rpriv);
1247err_neigh_init:
1248	return err;
1249}
1250
1251static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv)
1252{
1253	struct mlx5e_rep_priv *rpriv = priv->ppriv;
1254
1255	mlx5e_tc_ht_cleanup(&rpriv->tc_ht);
1256
1257	if (rpriv->rep->vport == MLX5_VPORT_UPLINK)
1258		mlx5e_cleanup_uplink_rep_tx(rpriv);
1259
1260	mlx5e_rep_neigh_cleanup(rpriv);
1261}
1262
1263static void mlx5e_rep_enable(struct mlx5e_priv *priv)
1264{
1265	mlx5e_set_netdev_mtu_boundaries(priv);
1266}
1267
1268static void mlx5e_rep_disable(struct mlx5e_priv *priv)
1269{
1270}
1271
1272static int mlx5e_update_rep_rx(struct mlx5e_priv *priv)
1273{
1274	return 0;
1275}
1276
1277static void mlx5e_rep_stats_update_ndo_stats(struct mlx5e_priv *priv)
1278{
1279	mlx5e_stats_update_ndo_stats(priv);
1280	mlx5e_rep_update_vport_q_counter(priv);
1281}
1282
1283static int mlx5e_rep_event_mpesw(struct mlx5e_priv *priv)
1284{
1285	struct mlx5e_rep_priv *rpriv = priv->ppriv;
1286	struct mlx5_eswitch_rep *rep = rpriv->rep;
1287
1288	if (rep->vport != MLX5_VPORT_UPLINK)
1289		return NOTIFY_DONE;
1290
1291	queue_work(priv->wq, &rpriv->uplink_priv.mpesw_work);
1292
1293	return NOTIFY_OK;
1294}
1295
1296static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event, void *data)
1297{
1298	struct mlx5e_priv *priv = container_of(nb, struct mlx5e_priv, events_nb);
1299
1300	if (event == MLX5_EVENT_TYPE_PORT_CHANGE) {
1301		struct mlx5_eqe *eqe = data;
1302
1303		switch (eqe->sub_type) {
1304		case MLX5_PORT_CHANGE_SUBTYPE_DOWN:
1305		case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE:
1306			queue_work(priv->wq, &priv->update_carrier_work);
1307			break;
1308		default:
1309			return NOTIFY_DONE;
1310		}
1311
1312		return NOTIFY_OK;
1313	}
1314
1315	if (event == MLX5_DEV_EVENT_PORT_AFFINITY)
1316		return mlx5e_rep_tc_event_port_affinity(priv);
1317	else if (event == MLX5_DEV_EVENT_MULTIPORT_ESW)
1318		return mlx5e_rep_event_mpesw(priv);
1319
1320	return NOTIFY_DONE;
1321}
1322
1323static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
1324{
1325	struct net_device *netdev = priv->netdev;
1326	struct mlx5_core_dev *mdev = priv->mdev;
1327	u16 max_mtu;
1328
1329	mlx5e_ipsec_init(priv);
1330
1331	netdev->min_mtu = ETH_MIN_MTU;
1332	mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1);
1333	netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu);
1334	mlx5e_set_dev_port_mtu(priv);
1335
1336	mlx5e_rep_tc_enable(priv);
1337
1338	if (MLX5_CAP_GEN(mdev, uplink_follow))
1339		mlx5_modify_vport_admin_state(mdev, MLX5_VPORT_STATE_OP_MOD_UPLINK,
1340					      0, 0, MLX5_VPORT_ADMIN_STATE_AUTO);
1341	mlx5_lag_add_netdev(mdev, netdev);
1342	priv->events_nb.notifier_call = uplink_rep_async_event;
1343	mlx5_notifier_register(mdev, &priv->events_nb);
1344	mlx5e_dcbnl_initialize(priv);
1345	mlx5e_dcbnl_init_app(priv);
1346	mlx5e_rep_bridge_init(priv);
1347
1348	netdev->wanted_features |= NETIF_F_HW_TC;
1349
1350	rtnl_lock();
1351	netdev_lock(netdev);
1352	if (netif_running(netdev))
1353		mlx5e_open(netdev);
1354	udp_tunnel_nic_reset_ntf(priv->netdev);
1355	netdev_unlock(netdev);
1356	netif_device_attach(netdev);
1357	rtnl_unlock();
1358}
1359
1360static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
1361{
1362	struct mlx5_core_dev *mdev = priv->mdev;
1363
1364	rtnl_lock();
1365	netdev_lock(priv->netdev);
1366	if (netif_running(priv->netdev))
1367		mlx5e_close(priv->netdev);
1368	netif_device_detach(priv->netdev);
1369	netdev_unlock(priv->netdev);
1370	rtnl_unlock();
1371
1372	mlx5e_rep_bridge_cleanup(priv);
1373	mlx5e_dcbnl_delete_app(priv);
1374	mlx5_notifier_unregister(mdev, &priv->events_nb);
1375	mlx5e_rep_tc_disable(priv);
1376	mlx5_lag_remove_netdev(mdev, priv->netdev);
1377	mlx5_vxlan_reset_to_default(mdev->vxlan);
1378
1379	mlx5e_ipsec_cleanup(priv);
1380}
1381
1382static MLX5E_DEFINE_STATS_GRP(sw_rep, 0);
1383static MLX5E_DEFINE_STATS_GRP(vport_rep, MLX5E_NDO_UPDATE_STATS);
1384
1385/* The stats groups order is opposite to the update_stats() order calls */
1386static mlx5e_stats_grp_t mlx5e_rep_stats_grps[] = {
1387	&MLX5E_STATS_GRP(sw_rep),
1388	&MLX5E_STATS_GRP(vport_rep),
1389};
1390
1391static unsigned int mlx5e_rep_stats_grps_num(struct mlx5e_priv *priv)
1392{
1393	return ARRAY_SIZE(mlx5e_rep_stats_grps);
1394}
1395
1396/* The stats groups order is opposite to the update_stats() order calls */
1397static mlx5e_stats_grp_t mlx5e_ul_rep_stats_grps[] = {
1398	&MLX5E_STATS_GRP(sw),
1399	&MLX5E_STATS_GRP(qcnt),
1400	&MLX5E_STATS_GRP(vnic_env),
1401	&MLX5E_STATS_GRP(vport),
1402	&MLX5E_STATS_GRP(802_3),
1403	&MLX5E_STATS_GRP(2863),
1404	&MLX5E_STATS_GRP(2819),
1405	&MLX5E_STATS_GRP(phy),
1406	&MLX5E_STATS_GRP(eth_ext),
1407	&MLX5E_STATS_GRP(pcie),
1408	&MLX5E_STATS_GRP(per_prio),
1409	&MLX5E_STATS_GRP(pme),
1410	&MLX5E_STATS_GRP(channels),
1411	&MLX5E_STATS_GRP(per_port_buff_congest),
1412#ifdef CONFIG_MLX5_EN_IPSEC
1413	&MLX5E_STATS_GRP(ipsec_hw),
1414	&MLX5E_STATS_GRP(ipsec_sw),
1415#endif
1416	&MLX5E_STATS_GRP(ptp),
1417};
1418
1419static unsigned int mlx5e_ul_rep_stats_grps_num(struct mlx5e_priv *priv)
1420{
1421	return ARRAY_SIZE(mlx5e_ul_rep_stats_grps);
1422}
1423
1424static int
1425mlx5e_rep_vnic_reporter_diagnose(struct devlink_health_reporter *reporter,
1426				 struct devlink_fmsg *fmsg,
1427				 struct netlink_ext_ack *extack)
1428{
1429	struct mlx5e_rep_priv *rpriv = devlink_health_reporter_priv(reporter);
1430	struct mlx5_eswitch_rep *rep = rpriv->rep;
1431
1432	mlx5_reporter_vnic_diagnose_counters(rep->esw->dev, fmsg, rep->vport,
1433					     true);
1434	return 0;
1435}
1436
1437static const struct devlink_health_reporter_ops mlx5_rep_vnic_reporter_ops = {
1438	.name = "vnic",
1439	.diagnose = mlx5e_rep_vnic_reporter_diagnose,
1440};
1441
1442static void mlx5e_rep_vnic_reporter_create(struct mlx5e_priv *priv,
1443					   struct devlink_port *dl_port)
1444{
1445	struct mlx5e_rep_priv *rpriv = priv->ppriv;
1446	struct devlink_health_reporter *reporter;
1447
1448	reporter = devl_port_health_reporter_create(dl_port,
1449						    &mlx5_rep_vnic_reporter_ops,
1450						    rpriv);
1451	if (IS_ERR(reporter)) {
1452		mlx5_core_err(priv->mdev,
1453			      "Failed to create representor vnic reporter, err = %pe\n",
1454			      reporter);
1455		return;
1456	}
1457
1458	rpriv->rep_vnic_reporter = reporter;
1459}
1460
1461static void mlx5e_rep_vnic_reporter_destroy(struct mlx5e_priv *priv)
1462{
1463	struct mlx5e_rep_priv *rpriv = priv->ppriv;
1464
1465	if (!IS_ERR_OR_NULL(rpriv->rep_vnic_reporter))
1466		devl_health_reporter_destroy(rpriv->rep_vnic_reporter);
1467}
1468
1469static const struct mlx5e_profile mlx5e_rep_profile = {
1470	.init			= mlx5e_init_rep,
1471	.cleanup		= mlx5e_cleanup_rep,
1472	.init_rx		= mlx5e_init_rep_rx,
1473	.cleanup_rx		= mlx5e_cleanup_rep_rx,
1474	.init_tx		= mlx5e_init_rep_tx,
1475	.cleanup_tx		= mlx5e_cleanup_rep_tx,
1476	.enable		        = mlx5e_rep_enable,
1477	.disable	        = mlx5e_rep_disable,
1478	.update_rx		= mlx5e_update_rep_rx,
1479	.update_stats           = mlx5e_rep_stats_update_ndo_stats,
1480	.rx_handlers            = &mlx5e_rx_handlers_rep,
1481	.max_tc			= 1,
1482	.stats_grps		= mlx5e_rep_stats_grps,
1483	.stats_grps_num		= mlx5e_rep_stats_grps_num,
1484	.max_nch_limit		= mlx5e_rep_max_nch_limit,
1485};
1486
1487static const struct mlx5e_profile mlx5e_uplink_rep_profile = {
1488	.init			= mlx5e_init_ul_rep,
1489	.cleanup		= mlx5e_cleanup_rep,
1490	.init_rx		= mlx5e_init_ul_rep_rx,
1491	.cleanup_rx		= mlx5e_cleanup_ul_rep_rx,
1492	.init_tx		= mlx5e_init_rep_tx,
1493	.cleanup_tx		= mlx5e_cleanup_rep_tx,
1494	.enable		        = mlx5e_uplink_rep_enable,
1495	.disable	        = mlx5e_uplink_rep_disable,
1496	.update_rx		= mlx5e_update_rep_rx,
1497	.update_stats           = mlx5e_stats_update_ndo_stats,
1498	.update_carrier	        = mlx5e_update_carrier,
1499	.rx_handlers            = &mlx5e_rx_handlers_rep,
1500	.max_tc			= MLX5_MAX_NUM_TC,
1501	.stats_grps		= mlx5e_ul_rep_stats_grps,
1502	.stats_grps_num		= mlx5e_ul_rep_stats_grps_num,
1503};
1504
1505/* e-Switch vport representors */
1506static int
1507mlx5e_vport_uplink_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
1508{
1509	struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
1510	struct net_device *netdev;
1511	int err;
1512
1513	netdev = mlx5_uplink_netdev_get(dev);
1514	if (!netdev)
1515		return 0;
1516
1517	/* must not use netdev_priv(netdev), it might not be initialized yet */
1518	rpriv->netdev = netdev;
1519	err = mlx5e_netdev_change_profile(netdev, dev,
1520					  &mlx5e_uplink_rep_profile, rpriv);
1521	mlx5_uplink_netdev_put(dev, netdev);
1522	return err;
1523}
1524
1525static void
1526mlx5e_vport_uplink_rep_unload(struct mlx5e_rep_priv *rpriv)
1527{
1528	struct net_device *netdev = rpriv->netdev;
1529	struct mlx5e_priv *priv;
1530
1531	priv = netdev_priv(netdev);
1532
1533	/* This bit is set when using devlink to change eswitch mode from
1534	 * switchdev to legacy. As need to keep uplink netdev ifindex, we
1535	 * detach uplink representor profile and attach NIC profile only.
1536	 * The netdev will be unregistered later when unload NIC auxiliary
1537	 * driver for this case.
1538	 * We explicitly block devlink eswitch mode change if any IPSec rules
1539	 * offloaded, but can't block other cases, such as driver unload
1540	 * and devlink reload. We have to unregister netdev before profile
1541	 * change for those cases. This is to avoid resource leak because
1542	 * the offloaded rules don't have the chance to be unoffloaded before
1543	 * cleanup which is triggered by detach uplink representor profile.
1544	 */
1545	if (!(priv->mdev->priv.flags & MLX5_PRIV_FLAGS_SWITCH_LEGACY))
1546		unregister_netdev(netdev);
1547
1548	mlx5e_netdev_attach_nic_profile(netdev, priv->mdev);
1549}
1550
1551static int
1552mlx5e_vport_vf_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
1553{
1554	struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
1555	const struct mlx5e_profile *profile;
1556	struct devlink_port *dl_port;
1557	struct net_device *netdev;
1558	struct mlx5e_priv *priv;
1559	int err;
1560
1561	profile = &mlx5e_rep_profile;
1562	netdev = mlx5e_create_netdev(dev, profile);
1563	if (!netdev) {
1564		mlx5_core_warn(dev,
1565			       "Failed to create representor netdev for vport %d\n",
1566			       rep->vport);
1567		return -EINVAL;
1568	}
1569
1570	mlx5e_build_rep_netdev(netdev, dev);
1571	rpriv->netdev = netdev;
1572
1573	priv = netdev_priv(netdev);
1574	priv->profile = profile;
1575	priv->ppriv = rpriv;
1576	err = profile->init(dev, netdev);
1577	if (err) {
1578		netdev_warn(netdev, "rep profile init failed, %d\n", err);
1579		goto err_destroy_netdev;
1580	}
1581
1582	err = mlx5e_attach_netdev(netdev_priv(netdev));
1583	if (err) {
1584		netdev_warn(netdev,
1585			    "Failed to attach representor netdev for vport %d\n",
1586			    rep->vport);
1587		goto err_cleanup_profile;
1588	}
1589
1590	dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch,
1591						 rpriv->rep->vport);
1592	if (!IS_ERR(dl_port)) {
1593		SET_NETDEV_DEVLINK_PORT(netdev, dl_port);
1594		mlx5e_rep_vnic_reporter_create(priv, dl_port);
1595	}
1596
1597	err = register_netdev(netdev);
1598	if (err) {
1599		netdev_warn(netdev,
1600			    "Failed to register representor netdev for vport %d\n",
1601			    rep->vport);
1602		goto err_detach_netdev;
1603	}
1604
1605	return 0;
1606
1607err_detach_netdev:
1608	mlx5e_rep_vnic_reporter_destroy(priv);
1609	mlx5e_detach_netdev(netdev_priv(netdev));
1610err_cleanup_profile:
1611	priv->profile->cleanup(priv);
1612
1613err_destroy_netdev:
1614	mlx5e_destroy_netdev(netdev);
1615	return err;
1616}
1617
1618static int
1619mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
1620{
1621	struct mlx5e_rep_priv *rpriv;
1622	int err;
1623
1624	rpriv = kvzalloc(sizeof(*rpriv), GFP_KERNEL);
1625	if (!rpriv)
1626		return -ENOMEM;
1627
1628	/* rpriv->rep to be looked up when profile->init() is called */
1629	rpriv->rep = rep;
1630	rep->rep_data[REP_ETH].priv = rpriv;
1631	INIT_LIST_HEAD(&rpriv->vport_sqs_list);
1632
1633	if (rep->vport == MLX5_VPORT_UPLINK)
1634		err = mlx5e_vport_uplink_rep_load(dev, rep);
1635	else
1636		err = mlx5e_vport_vf_rep_load(dev, rep);
1637
1638	if (err)
1639		kvfree(rpriv);
1640
1641	return err;
1642}
1643
1644static void
1645mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
1646{
1647	struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
1648	struct net_device *netdev = rpriv->netdev;
1649	struct mlx5e_priv *priv;
1650	void *ppriv;
1651
1652	if (!netdev) {
1653		ppriv = rpriv;
1654		goto free_ppriv;
1655	}
1656
1657	priv = netdev_priv(netdev);
1658	ppriv = priv->ppriv;
1659
1660	if (rep->vport == MLX5_VPORT_UPLINK) {
1661		mlx5e_vport_uplink_rep_unload(rpriv);
1662		goto free_ppriv;
1663	}
1664
1665	unregister_netdev(netdev);
1666	mlx5e_rep_vnic_reporter_destroy(priv);
1667	mlx5e_detach_netdev(priv);
1668	priv->profile->cleanup(priv);
1669	mlx5e_destroy_netdev(netdev);
1670free_ppriv:
1671	kvfree(ppriv); /* mlx5e_rep_priv */
1672}
1673
1674static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep)
1675{
1676	struct mlx5e_rep_priv *rpriv;
1677
1678	rpriv = mlx5e_rep_to_rep_priv(rep);
1679
1680	return rpriv->netdev;
1681}
1682
1683static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep,
1684					 struct mlx5_eswitch *peer_esw)
1685{
1686	u16 i = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
1687	struct mlx5e_rep_priv *rpriv;
1688	struct mlx5e_rep_sq *rep_sq;
1689
1690	WARN_ON_ONCE(!peer_esw);
1691	rpriv = mlx5e_rep_to_rep_priv(rep);
1692	list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) {
1693		struct mlx5e_rep_sq_peer *sq_peer = xa_load(&rep_sq->sq_peer, i);
1694
1695		if (!sq_peer || sq_peer->peer != peer_esw)
1696			continue;
1697
1698		mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule);
1699		xa_erase(&rep_sq->sq_peer, i);
1700		kfree(sq_peer);
1701	}
1702}
1703
1704static int mlx5e_vport_rep_event_pair(struct mlx5_eswitch *esw,
1705				      struct mlx5_eswitch_rep *rep,
1706				      struct mlx5_eswitch *peer_esw)
1707{
1708	u16 i = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
1709	struct mlx5_flow_handle *flow_rule;
1710	struct mlx5e_rep_sq_peer *sq_peer;
1711	struct mlx5e_rep_priv *rpriv;
1712	struct mlx5e_rep_sq *rep_sq;
1713	int err;
1714
1715	rpriv = mlx5e_rep_to_rep_priv(rep);
1716	list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) {
1717		sq_peer = xa_load(&rep_sq->sq_peer, i);
1718
1719		if (sq_peer && sq_peer->peer)
1720			continue;
1721
1722		flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep,
1723								rep_sq->sqn);
1724		if (IS_ERR(flow_rule)) {
1725			err = PTR_ERR(flow_rule);
1726			goto err_out;
1727		}
1728
1729		if (sq_peer) {
1730			sq_peer->rule = flow_rule;
1731			sq_peer->peer = peer_esw;
1732			continue;
1733		}
1734		sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL);
1735		if (!sq_peer) {
1736			err = -ENOMEM;
1737			goto err_sq_alloc;
1738		}
1739		err = xa_insert(&rep_sq->sq_peer, i, sq_peer, GFP_KERNEL);
1740		if (err)
1741			goto err_xa;
1742		sq_peer->rule = flow_rule;
1743		sq_peer->peer = peer_esw;
1744	}
1745
1746	return 0;
1747err_xa:
1748	kfree(sq_peer);
1749err_sq_alloc:
1750	mlx5_eswitch_del_send_to_vport_rule(flow_rule);
1751err_out:
1752	mlx5e_vport_rep_event_unpair(rep, peer_esw);
1753	return err;
1754}
1755
1756static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw,
1757				 struct mlx5_eswitch_rep *rep,
1758				 enum mlx5_switchdev_event event,
1759				 void *data)
1760{
1761	int err = 0;
1762
1763	if (event == MLX5_SWITCHDEV_EVENT_PAIR)
1764		err = mlx5e_vport_rep_event_pair(esw, rep, data);
1765	else if (event == MLX5_SWITCHDEV_EVENT_UNPAIR)
1766		mlx5e_vport_rep_event_unpair(rep, data);
1767
1768	return err;
1769}
1770
1771static const struct mlx5_eswitch_rep_ops rep_ops = {
1772	.load = mlx5e_vport_rep_load,
1773	.unload = mlx5e_vport_rep_unload,
1774	.get_proto_dev = mlx5e_vport_rep_get_proto_dev,
1775	.event = mlx5e_vport_rep_event,
1776};
1777
1778static int mlx5e_rep_probe(struct auxiliary_device *adev,
1779			   const struct auxiliary_device_id *id)
1780{
1781	struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
1782	struct mlx5_core_dev *mdev = edev->mdev;
1783	struct mlx5_eswitch *esw;
1784
1785	esw = mdev->priv.eswitch;
1786	mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_ETH);
1787	return 0;
1788}
1789
1790static void mlx5e_rep_remove(struct auxiliary_device *adev)
1791{
1792	struct mlx5_adev *vdev = container_of(adev, struct mlx5_adev, adev);
1793	struct mlx5_core_dev *mdev = vdev->mdev;
1794	struct mlx5_eswitch *esw;
1795
1796	esw = mdev->priv.eswitch;
1797	mlx5_eswitch_unregister_vport_reps(esw, REP_ETH);
1798}
1799
1800static const struct auxiliary_device_id mlx5e_rep_id_table[] = {
1801	{ .name = MLX5_ADEV_NAME ".eth-rep", },
1802	{},
1803};
1804
1805MODULE_DEVICE_TABLE(auxiliary, mlx5e_rep_id_table);
1806
1807static struct auxiliary_driver mlx5e_rep_driver = {
1808	.name = "eth-rep",
1809	.probe = mlx5e_rep_probe,
1810	.remove = mlx5e_rep_remove,
1811	.id_table = mlx5e_rep_id_table,
1812};
1813
1814int mlx5e_rep_init(void)
1815{
1816	return auxiliary_driver_register(&mlx5e_rep_driver);
1817}
1818
1819void mlx5e_rep_cleanup(void)
1820{
1821	auxiliary_driver_unregister(&mlx5e_rep_driver);
1822}
~/ Read-only file preview.