Commit a6696735 authored by Maxim Mikityanskiy's avatar Maxim Mikityanskiy Committed by Saeed Mahameed
Browse files

net/mlx5e: Convert TIR to a dedicated object



Code related to TIR is now encapsulated into a dedicated object and put
into new files en/tir.{c,h}. All usages are converted.

The Builder pattern is used to initialize a TIR. It allows to create a
multitude of different configurations, turning on and off some specific
features in different combinations, without having long parameter lists,
initializers per usage and repeating code in initializers.

Signed-off-by: default avatarMaxim Mikityanskiy <maximmi@nvidia.com>
Reviewed-by: default avatarMaor Dickman <maord@nvidia.com>
Reviewed-by: default avatarTariq Toukan <tariqt@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent 6fe5ff2c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \
		en_selftest.o en/port.o en/monitor_stats.o en/health.o \
		en/reporter_tx.o en/reporter_rx.o en/params.o en/xsk/pool.o \
		en/xsk/setup.o en/xsk/rx.o en/xsk/tx.o en/devlink.o en/ptp.o \
		en/qos.o en/trap.o en/fs_tt_redirect.o en/rqt.o
		en/qos.o en/trap.o en/fs_tt_redirect.o en/rqt.o en/tir.o

#
# Netdev extra
+1 −9
Original line number Diff line number Diff line
@@ -127,7 +127,6 @@ struct page_pool;

#define MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE_MPW            0x2

#define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ                 (64 * 1024)
#define MLX5E_DEFAULT_LRO_TIMEOUT                       32
#define MLX5E_LRO_TIMEOUT_ARR_SIZE                      4

@@ -922,10 +921,7 @@ int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
			   u16 vid);
void mlx5e_timestamp_init(struct mlx5e_priv *priv);

void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_rss_params *rss_params,
				    const struct mlx5e_tirc_config *ttconfig,
				    void *tirc, bool inner);
void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in);
int mlx5e_modify_tirs_hash(struct mlx5e_priv *priv);
struct mlx5e_tirc_config mlx5e_tirc_get_default_config(enum mlx5e_traffic_types tt);

struct mlx5e_xsk_param;
@@ -1026,10 +1022,6 @@ static inline bool mlx5_tx_swp_supported(struct mlx5_core_dev *mdev)

extern const struct ethtool_ops mlx5e_ethtool_ops;

int mlx5e_create_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir,
		     u32 *in);
void mlx5e_destroy_tir(struct mlx5_core_dev *mdev,
		       struct mlx5e_tir *tir);
int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev);
void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev);
int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb,
+1 −10
Original line number Diff line number Diff line
@@ -6,26 +6,17 @@

#include <linux/kernel.h>
#include "rqt.h"
#include "tir.h"
#include "fs.h"

#define MLX5E_MAX_NUM_CHANNELS (MLX5E_INDIR_RQT_SIZE / 2)

struct mlx5e_rss_params_hash {
	u8 hfunc;
	u8 toeplitz_hash_key[40];
};

struct mlx5e_rss_params {
	struct mlx5e_rss_params_hash hash;
	struct mlx5e_rss_params_indir indir;
	u32 rx_hash_fields[MLX5E_NUM_INDIR_TIRS];
};

struct mlx5e_tir {
	u32 tirn;
	struct list_head list;
};

struct mlx5e_rx_res {
	struct mlx5e_rss_params rss_params;

+188 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */

#include "tir.h"
#include "params.h"
#include <linux/mlx5/transobj.h>

#define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ (64 * 1024)

/* max() doesn't work inside square brackets. */
#define MLX5E_TIR_CMD_IN_SZ_DW ( \
	MLX5_ST_SZ_DW(create_tir_in) > MLX5_ST_SZ_DW(modify_tir_in) ? \
	MLX5_ST_SZ_DW(create_tir_in) : MLX5_ST_SZ_DW(modify_tir_in) \
)

struct mlx5e_tir_builder {
	u32 in[MLX5E_TIR_CMD_IN_SZ_DW];
	bool modify;
};

struct mlx5e_tir_builder *mlx5e_tir_builder_alloc(bool modify)
{
	struct mlx5e_tir_builder *builder;

	builder = kvzalloc(sizeof(*builder), GFP_KERNEL);
	builder->modify = modify;

	return builder;
}

void mlx5e_tir_builder_free(struct mlx5e_tir_builder *builder)
{
	kvfree(builder);
}

void mlx5e_tir_builder_clear(struct mlx5e_tir_builder *builder)
{
	memset(builder->in, 0, sizeof(builder->in));
}

static void *mlx5e_tir_builder_get_tirc(struct mlx5e_tir_builder *builder)
{
	if (builder->modify)
		return MLX5_ADDR_OF(modify_tir_in, builder->in, ctx);
	return MLX5_ADDR_OF(create_tir_in, builder->in, ctx);
}

void mlx5e_tir_builder_build_inline(struct mlx5e_tir_builder *builder, u32 tdn, u32 rqn)
{
	void *tirc = mlx5e_tir_builder_get_tirc(builder);

	WARN_ON(builder->modify);

	MLX5_SET(tirc, tirc, transport_domain, tdn);
	MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_DIRECT);
	MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_NONE);
	MLX5_SET(tirc, tirc, inline_rqn, rqn);
}

void mlx5e_tir_builder_build_rqt(struct mlx5e_tir_builder *builder, u32 tdn,
				 u32 rqtn, bool inner_ft_support)
{
	void *tirc = mlx5e_tir_builder_get_tirc(builder);

	WARN_ON(builder->modify);

	MLX5_SET(tirc, tirc, transport_domain, tdn);
	MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
	MLX5_SET(tirc, tirc, indirect_table, rqtn);
	MLX5_SET(tirc, tirc, tunneled_offload_en, inner_ft_support);
}

void mlx5e_tir_builder_build_lro(struct mlx5e_tir_builder *builder,
				 const struct mlx5e_lro_param *lro_param)
{
	void *tirc = mlx5e_tir_builder_get_tirc(builder);
	const unsigned int rough_max_l2_l3_hdr_sz = 256;

	if (builder->modify)
		MLX5_SET(modify_tir_in, builder->in, bitmask.lro, 1);

	if (!lro_param->enabled)
		return;

	MLX5_SET(tirc, tirc, lro_enable_mask,
		 MLX5_TIRC_LRO_ENABLE_MASK_IPV4_LRO |
		 MLX5_TIRC_LRO_ENABLE_MASK_IPV6_LRO);
	MLX5_SET(tirc, tirc, lro_max_ip_payload_size,
		 (MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ - rough_max_l2_l3_hdr_sz) >> 8);
	MLX5_SET(tirc, tirc, lro_timeout_period_usecs, lro_param->timeout);
}

static int mlx5e_hfunc_to_hw(u8 hfunc)
{
	switch (hfunc) {
	case ETH_RSS_HASH_TOP:
		return MLX5_RX_HASH_FN_TOEPLITZ;
	case ETH_RSS_HASH_XOR:
		return MLX5_RX_HASH_FN_INVERTED_XOR8;
	default:
		return MLX5_RX_HASH_FN_NONE;
	}
}

void mlx5e_tir_builder_build_rss(struct mlx5e_tir_builder *builder,
				 const struct mlx5e_rss_params_hash *rss_hash,
				 const struct mlx5e_rss_params_traffic_type *rss_tt,
				 bool inner)
{
	void *tirc = mlx5e_tir_builder_get_tirc(builder);
	void *hfso;

	if (builder->modify)
		MLX5_SET(modify_tir_in, builder->in, bitmask.hash, 1);

	MLX5_SET(tirc, tirc, rx_hash_fn, mlx5e_hfunc_to_hw(rss_hash->hfunc));
	if (rss_hash->hfunc == ETH_RSS_HASH_TOP) {
		const size_t len = MLX5_FLD_SZ_BYTES(tirc, rx_hash_toeplitz_key);
		void *rss_key = MLX5_ADDR_OF(tirc, tirc, rx_hash_toeplitz_key);

		MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
		memcpy(rss_key, rss_hash->toeplitz_hash_key, len);
	}

	if (inner)
		hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_inner);
	else
		hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
	MLX5_SET(rx_hash_field_select, hfso, l3_prot_type, rss_tt->l3_prot_type);
	MLX5_SET(rx_hash_field_select, hfso, l4_prot_type, rss_tt->l4_prot_type);
	MLX5_SET(rx_hash_field_select, hfso, selected_fields, rss_tt->rx_hash_fields);
}

void mlx5e_tir_builder_build_direct(struct mlx5e_tir_builder *builder)
{
	void *tirc = mlx5e_tir_builder_get_tirc(builder);

	WARN_ON(builder->modify);

	MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_INVERTED_XOR8);
}

int mlx5e_tir_init(struct mlx5e_tir *tir, struct mlx5e_tir_builder *builder,
		   struct mlx5_core_dev *mdev, bool reg)
{
	int err;

	tir->mdev = mdev;

	err = mlx5_core_create_tir(tir->mdev, builder->in, &tir->tirn);
	if (err)
		return err;

	if (reg) {
		struct mlx5e_hw_objs *res = &tir->mdev->mlx5e_res.hw_objs;

		mutex_lock(&res->td.list_lock);
		list_add(&tir->list, &res->td.tirs_list);
		mutex_unlock(&res->td.list_lock);
	} else {
		INIT_LIST_HEAD(&tir->list);
	}

	return 0;
}

void mlx5e_tir_destroy(struct mlx5e_tir *tir)
{
	struct mlx5e_hw_objs *res = &tir->mdev->mlx5e_res.hw_objs;

	/* Skip mutex if list_del is no-op (the TIR wasn't registered in the
	 * list). list_empty will never return true for an item of tirs_list,
	 * and READ_ONCE/WRITE_ONCE in list_empty/list_del guarantee consistency
	 * of the list->next value.
	 */
	if (!list_empty(&tir->list)) {
		mutex_lock(&res->td.list_lock);
		list_del(&tir->list);
		mutex_unlock(&res->td.list_lock);
	}

	mlx5_core_destroy_tir(tir->mdev, tir->tirn);
}

int mlx5e_tir_modify(struct mlx5e_tir *tir, struct mlx5e_tir_builder *builder)
{
	return mlx5_core_modify_tir(tir->mdev, tir->tirn, builder->in);
}
+57 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */

#ifndef __MLX5_EN_TIR_H__
#define __MLX5_EN_TIR_H__

#include <linux/kernel.h>

struct mlx5e_rss_params_hash {
	u8 hfunc;
	u8 toeplitz_hash_key[40];
};

struct mlx5e_rss_params_traffic_type {
	u8 l3_prot_type;
	u8 l4_prot_type;
	u32 rx_hash_fields;
};

struct mlx5e_tir_builder;
struct mlx5e_lro_param;

struct mlx5e_tir_builder *mlx5e_tir_builder_alloc(bool modify);
void mlx5e_tir_builder_free(struct mlx5e_tir_builder *builder);
void mlx5e_tir_builder_clear(struct mlx5e_tir_builder *builder);

void mlx5e_tir_builder_build_inline(struct mlx5e_tir_builder *builder, u32 tdn, u32 rqn);
void mlx5e_tir_builder_build_rqt(struct mlx5e_tir_builder *builder, u32 tdn,
				 u32 rqtn, bool inner_ft_support);
void mlx5e_tir_builder_build_lro(struct mlx5e_tir_builder *builder,
				 const struct mlx5e_lro_param *lro_param);
void mlx5e_tir_builder_build_rss(struct mlx5e_tir_builder *builder,
				 const struct mlx5e_rss_params_hash *rss_hash,
				 const struct mlx5e_rss_params_traffic_type *rss_tt,
				 bool inner);
void mlx5e_tir_builder_build_direct(struct mlx5e_tir_builder *builder);

struct mlx5_core_dev;

struct mlx5e_tir {
	struct mlx5_core_dev *mdev;
	u32 tirn;
	struct list_head list;
};

int mlx5e_tir_init(struct mlx5e_tir *tir, struct mlx5e_tir_builder *builder,
		   struct mlx5_core_dev *mdev, bool reg);
void mlx5e_tir_destroy(struct mlx5e_tir *tir);

static inline u32 mlx5e_tir_get_tirn(struct mlx5e_tir *tir)
{
	return tir->tirn;
}

int mlx5e_tir_modify(struct mlx5e_tir *tir, struct mlx5e_tir_builder *builder);

#endif /* __MLX5_EN_TIR_H__ */
Loading