Commit 3c89a986 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'mlx5-hardware-steering-part-2'

Tariq Toukan says:

====================
mlx5 Hardware Steering part 2

This series contain HWS code cleanups, enhancements, bug fixes, and
additions. Note that some of these patches are fixing bugs in existing
code, but we submit them without 'Fixes' tag to avoid the unnecessary
burden for stable releases, as HWS still couldn't be enabled.

Patches 1-5:
HWS, various code cleanups and enhancements

Patches 6-14:
HWS, various bug fixes and additions

Patch 15:
HWS, setting timeout on polling
====================

Link: https://patch.msgid.link/20250102181415.1477316-1-tariqt@nvidia.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 7c7ea705 d74ee6e1
Loading
Loading
Loading
Loading
+102 −57
Original line number Diff line number Diff line
@@ -11,8 +11,7 @@
/* This is the longest supported action sequence for FDB table:
 * DECAP, POP_VLAN, MODIFY, CTR, ASO, PUSH_VLAN, MODIFY, ENCAP, Term.
 */
static const u32 action_order_arr[MLX5HWS_TABLE_TYPE_MAX][MLX5HWS_ACTION_TYP_MAX] = {
	[MLX5HWS_TABLE_TYPE_FDB] = {
static const u32 action_order_arr[MLX5HWS_ACTION_TYP_MAX] = {
	BIT(MLX5HWS_ACTION_TYP_REMOVE_HEADER) |
	BIT(MLX5HWS_ACTION_TYP_REFORMAT_TNL_L2_TO_L2) |
	BIT(MLX5HWS_ACTION_TYP_REFORMAT_TNL_L3_TO_L2),
@@ -35,7 +34,6 @@ static const u32 action_order_arr[MLX5HWS_TABLE_TYPE_MAX][MLX5HWS_ACTION_TYP_MAX
	BIT(MLX5HWS_ACTION_TYP_RANGE) |
	BIT(MLX5HWS_ACTION_TYP_DEST_ARRAY),
	BIT(MLX5HWS_ACTION_TYP_LAST),
	},
};

static const char * const mlx5hws_action_type_str[] = {
@@ -83,8 +81,8 @@ static int hws_action_get_shared_stc_nic(struct mlx5hws_context *ctx,
	int ret;

	mutex_lock(&ctx->ctrl_lock);
	if (ctx->common_res[tbl_type].shared_stc[stc_type]) {
		ctx->common_res[tbl_type].shared_stc[stc_type]->refcount++;
	if (ctx->common_res.shared_stc[stc_type]) {
		ctx->common_res.shared_stc[stc_type]->refcount++;
		mutex_unlock(&ctx->ctrl_lock);
		return 0;
	}
@@ -124,8 +122,8 @@ static int hws_action_get_shared_stc_nic(struct mlx5hws_context *ctx,
		goto free_shared_stc;
	}

	ctx->common_res[tbl_type].shared_stc[stc_type] = shared_stc;
	ctx->common_res[tbl_type].shared_stc[stc_type]->refcount = 1;
	ctx->common_res.shared_stc[stc_type] = shared_stc;
	ctx->common_res.shared_stc[stc_type]->refcount = 1;

	mutex_unlock(&ctx->ctrl_lock);

@@ -178,16 +176,16 @@ static void hws_action_put_shared_stc(struct mlx5hws_action *action,
	}

	mutex_lock(&ctx->ctrl_lock);
	if (--ctx->common_res[tbl_type].shared_stc[stc_type]->refcount) {
	if (--ctx->common_res.shared_stc[stc_type]->refcount) {
		mutex_unlock(&ctx->ctrl_lock);
		return;
	}

	shared_stc = ctx->common_res[tbl_type].shared_stc[stc_type];
	shared_stc = ctx->common_res.shared_stc[stc_type];

	mlx5hws_action_free_single_stc(ctx, tbl_type, &shared_stc->stc_chunk);
	kfree(shared_stc);
	ctx->common_res[tbl_type].shared_stc[stc_type] = NULL;
	ctx->common_res.shared_stc[stc_type] = NULL;
	mutex_unlock(&ctx->ctrl_lock);
}

@@ -206,10 +204,10 @@ bool mlx5hws_action_check_combo(struct mlx5hws_context *ctx,
				enum mlx5hws_action_type *user_actions,
				enum mlx5hws_table_type table_type)
{
	const u32 *order_arr = action_order_arr[table_type];
	const u32 *order_arr = action_order_arr;
	bool valid_combo;
	u8 order_idx = 0;
	u8 user_idx = 0;
	bool valid_combo;

	if (table_type >= MLX5HWS_TABLE_TYPE_MAX) {
		mlx5hws_err(ctx, "Invalid table_type %d", table_type);
@@ -321,8 +319,8 @@ int mlx5hws_action_alloc_single_stc(struct mlx5hws_context *ctx,
__must_hold(&ctx->ctrl_lock)
{
	struct mlx5hws_cmd_stc_modify_attr cleanup_stc_attr = {0};
	struct mlx5hws_pool *stc_pool = ctx->stc_pool[table_type];
	struct mlx5hws_cmd_stc_modify_attr fixup_stc_attr = {0};
	struct mlx5hws_pool *stc_pool = ctx->stc_pool;
	bool use_fixup;
	u32 obj_0_id;
	int ret;
@@ -387,8 +385,8 @@ void mlx5hws_action_free_single_stc(struct mlx5hws_context *ctx,
				    struct mlx5hws_pool_chunk *stc)
__must_hold(&ctx->ctrl_lock)
{
	struct mlx5hws_pool *stc_pool = ctx->stc_pool[table_type];
	struct mlx5hws_cmd_stc_modify_attr stc_attr = {0};
	struct mlx5hws_pool *stc_pool = ctx->stc_pool;
	u32 obj_id;

	/* Modify the STC not to point to an object */
@@ -473,6 +471,7 @@ static void hws_action_fill_stc_attr(struct mlx5hws_action *action,
		break;
	case MLX5HWS_ACTION_TYP_TBL:
	case MLX5HWS_ACTION_TYP_DEST_ARRAY:
	case MLX5HWS_ACTION_TYP_SAMPLER:
		attr->action_type = MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_FT;
		attr->action_offset = MLX5HWS_ACTION_OFFSET_HIT;
		attr->dest_table_id = obj_id;
@@ -561,7 +560,7 @@ hws_action_create_stcs(struct mlx5hws_action *action, u32 obj_id)
	if (action->flags & MLX5HWS_ACTION_FLAG_HWS_FDB) {
		ret = mlx5hws_action_alloc_single_stc(ctx, &stc_attr,
						      MLX5HWS_TABLE_TYPE_FDB,
						      &action->stc[MLX5HWS_TABLE_TYPE_FDB]);
						      &action->stc);
		if (ret)
			goto out_err;
	}
@@ -585,7 +584,7 @@ hws_action_destroy_stcs(struct mlx5hws_action *action)

	if (action->flags & MLX5HWS_ACTION_FLAG_HWS_FDB)
		mlx5hws_action_free_single_stc(ctx, MLX5HWS_TABLE_TYPE_FDB,
					       &action->stc[MLX5HWS_TABLE_TYPE_FDB]);
					       &action->stc);

	mutex_unlock(&ctx->ctrl_lock);
}
@@ -1639,8 +1638,8 @@ hws_action_create_dest_match_range_table(struct mlx5hws_context *ctx,
	rtc_attr.table_type = mlx5hws_table_get_res_fw_ft_type(MLX5HWS_TABLE_TYPE_FDB, false);

	/* STC is a single resource (obj_id), use any STC for the ID */
	stc_pool = ctx->stc_pool[MLX5HWS_TABLE_TYPE_FDB];
	default_stc = ctx->common_res[MLX5HWS_TABLE_TYPE_FDB].default_stc;
	stc_pool = ctx->stc_pool;
	default_stc = ctx->common_res.default_stc;
	obj_id = mlx5hws_pool_chunk_get_base_id(stc_pool, &default_stc->default_hit);
	rtc_attr.stc_base = obj_id;

@@ -1731,7 +1730,7 @@ hws_action_create_dest_match_range_fill_table(struct mlx5hws_context *ctx,
	ste_attr.used_id_rtc_0 = &used_rtc_0_id;
	ste_attr.used_id_rtc_1 = &used_rtc_1_id;

	common_res = &ctx->common_res[MLX5HWS_TABLE_TYPE_FDB];
	common_res = &ctx->common_res;

	/* init an empty match STE which will always hit */
	ste_attr.wqe_ctrl = &wqe_ctrl;
@@ -1750,7 +1749,7 @@ hws_action_create_dest_match_range_fill_table(struct mlx5hws_context *ctx,
	wqe_ctrl.stc_ix[MLX5HWS_ACTION_STC_IDX_CTRL] |=
		htonl(MLX5HWS_ACTION_STC_IDX_LAST_COMBO2 << 29);
	wqe_ctrl.stc_ix[MLX5HWS_ACTION_STC_IDX_HIT] =
		htonl(hit_ft_action->stc[MLX5HWS_TABLE_TYPE_FDB].offset);
		htonl(hit_ft_action->stc.offset);

	wqe_data_arr = (__force __be32 *)&range_wqe_data;

@@ -1843,7 +1842,7 @@ mlx5hws_action_create_dest_match_range(struct mlx5hws_context *ctx,
	stc_attr.ste_table.match_definer_id = ctx->caps->trivial_match_definer;

	ret = mlx5hws_action_alloc_single_stc(ctx, &stc_attr, MLX5HWS_TABLE_TYPE_FDB,
					      &action->stc[MLX5HWS_TABLE_TYPE_FDB]);
					      &action->stc);
	if (ret)
		goto error_unlock;

@@ -1875,7 +1874,50 @@ struct mlx5hws_action *
mlx5hws_action_create_flow_sampler(struct mlx5hws_context *ctx,
				   u32 sampler_id, u32 flags)
{
	mlx5hws_err(ctx, "Flow sampler action - unsupported\n");
	struct mlx5hws_cmd_ft_create_attr ft_attr = {0};
	struct mlx5hws_cmd_set_fte_attr fte_attr = {0};
	struct mlx5hws_cmd_forward_tbl *fw_island;
	struct mlx5hws_cmd_set_fte_dest dest;
	struct mlx5hws_action *action;
	int ret;

	if (flags != (MLX5HWS_ACTION_FLAG_HWS_FDB | MLX5HWS_ACTION_FLAG_SHARED)) {
		mlx5hws_err(ctx, "Unsupported flags for flow sampler\n");
		return NULL;
	}

	ft_attr.type = FS_FT_FDB;
	ft_attr.level = ctx->caps->fdb_ft.max_level - 1;

	dest.destination_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER;
	dest.destination_id = sampler_id;

	fte_attr.dests_num = 1;
	fte_attr.dests = &dest;
	fte_attr.action_flags = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
	fte_attr.ignore_flow_level = 1;

	fw_island = mlx5hws_cmd_forward_tbl_create(ctx->mdev, &ft_attr, &fte_attr);
	if (!fw_island)
		return NULL;

	action = hws_action_create_generic(ctx, flags,
					   MLX5HWS_ACTION_TYP_SAMPLER);
	if (!action)
		goto destroy_fw_island;

	ret = hws_action_create_stcs(action, fw_island->ft_id);
	if (ret)
		goto free_action;

	action->flow_sampler.fw_island = fw_island;

	return action;

free_action:
	kfree(action);
destroy_fw_island:
	mlx5hws_cmd_forward_tbl_destroy(ctx->mdev, fw_island);
	return NULL;
}

@@ -1914,6 +1956,11 @@ static void hws_action_destroy_hws(struct mlx5hws_action *action)
		}
		kfree(action->dest_array.dest_list);
		break;
	case MLX5HWS_ACTION_TYP_SAMPLER:
		hws_action_destroy_stcs(action);
		mlx5hws_cmd_forward_tbl_destroy(action->ctx->mdev,
						action->flow_sampler.fw_island);
		break;
	case MLX5HWS_ACTION_TYP_REFORMAT_TNL_L3_TO_L2:
	case MLX5HWS_ACTION_TYP_MODIFY_HDR:
		shared_arg = false;
@@ -1970,8 +2017,8 @@ __must_hold(&ctx->ctrl_lock)
	struct mlx5hws_action_default_stc *default_stc;
	int ret;

	if (ctx->common_res[tbl_type].default_stc) {
		ctx->common_res[tbl_type].default_stc->refcount++;
	if (ctx->common_res.default_stc) {
		ctx->common_res.default_stc->refcount++;
		return 0;
	}

@@ -2023,8 +2070,8 @@ __must_hold(&ctx->ctrl_lock)
		goto free_nop_dw7;
	}

	ctx->common_res[tbl_type].default_stc = default_stc;
	ctx->common_res[tbl_type].default_stc->refcount++;
	ctx->common_res.default_stc = default_stc;
	ctx->common_res.default_stc->refcount++;

	return 0;

@@ -2046,9 +2093,7 @@ __must_hold(&ctx->ctrl_lock)
{
	struct mlx5hws_action_default_stc *default_stc;

	default_stc = ctx->common_res[tbl_type].default_stc;

	default_stc = ctx->common_res[tbl_type].default_stc;
	default_stc = ctx->common_res.default_stc;
	if (--default_stc->refcount)
		return;

@@ -2058,7 +2103,7 @@ __must_hold(&ctx->ctrl_lock)
	mlx5hws_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw5);
	mlx5hws_action_free_single_stc(ctx, tbl_type, &default_stc->nop_ctr);
	kfree(default_stc);
	ctx->common_res[tbl_type].default_stc = NULL;
	ctx->common_res.default_stc = NULL;
}

static void hws_action_modify_write(struct mlx5hws_send_engine *queue,
@@ -2150,8 +2195,7 @@ hws_action_apply_stc(struct mlx5hws_actions_apply_data *apply,
{
	struct mlx5hws_action *action = apply->rule_action[action_idx].action;

	apply->wqe_ctrl->stc_ix[stc_idx] =
		htonl(action->stc[apply->tbl_type].offset);
	apply->wqe_ctrl->stc_ix[stc_idx] = htonl(action->stc.offset);
}

static void
@@ -2181,7 +2225,7 @@ hws_action_setter_modify_header(struct mlx5hws_actions_apply_data *apply,
	rule_action = &apply->rule_action[setter->idx_double];
	action = rule_action->action;

	stc_idx = htonl(action->stc[apply->tbl_type].offset);
	stc_idx = htonl(action->stc.offset);
	apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW6] = stc_idx;
	apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW7] = 0;

@@ -2240,7 +2284,7 @@ hws_action_setter_insert_ptr(struct mlx5hws_actions_apply_data *apply,
	apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW6] = 0;
	apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW7] = htonl(arg_idx);

	stc_idx = htonl(action->stc[apply->tbl_type].offset);
	stc_idx = htonl(action->stc.offset);
	apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW6] = stc_idx;
	apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW7] = 0;

@@ -2272,7 +2316,7 @@ hws_action_setter_tnl_l3_to_l2(struct mlx5hws_actions_apply_data *apply,
	apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW6] = 0;
	apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW7] = htonl(arg_idx);

	stc_idx = htonl(action->stc[apply->tbl_type].offset);
	stc_idx = htonl(action->stc.offset);
	apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW6] = stc_idx;
	apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW7] = 0;

@@ -2434,6 +2478,7 @@ int mlx5hws_action_template_process(struct mlx5hws_action_template *at)
		case MLX5HWS_ACTION_TYP_DROP:
		case MLX5HWS_ACTION_TYP_TBL:
		case MLX5HWS_ACTION_TYP_DEST_ARRAY:
		case MLX5HWS_ACTION_TYP_SAMPLER:
		case MLX5HWS_ACTION_TYP_VPORT:
		case MLX5HWS_ACTION_TYP_MISS:
			/* Hit action */
+6 −3
Original line number Diff line number Diff line
@@ -70,12 +70,12 @@ struct mlx5hws_action_default_stc {
	struct mlx5hws_pool_chunk nop_dw6;
	struct mlx5hws_pool_chunk nop_dw7;
	struct mlx5hws_pool_chunk default_hit;
	u32 refcount;
	u32 refcount; /* protected by context ctrl lock */
};

struct mlx5hws_action_shared_stc {
	struct mlx5hws_pool_chunk stc_chunk;
	u32 refcount;
	u32 refcount; /* protected by context ctrl lock */
};

struct mlx5hws_actions_apply_data {
@@ -124,7 +124,7 @@ struct mlx5hws_action {
	struct mlx5hws_context *ctx;
	union {
		struct {
			struct mlx5hws_pool_chunk stc[MLX5HWS_TABLE_TYPE_MAX];
			struct mlx5hws_pool_chunk stc;
			union {
				struct {
					u32 pat_id;
@@ -165,6 +165,9 @@ struct mlx5hws_action {
					size_t num_dest;
					struct mlx5hws_cmd_set_fte_dest *dest_list;
				} dest_array;
				struct {
					struct mlx5hws_cmd_forward_tbl *fw_island;
				} flow_sampler;
				struct {
					u8 type;
					u8 start_anchor;
+36 −18
Original line number Diff line number Diff line
@@ -152,6 +152,8 @@ mlx5hws_bwc_matcher_create(struct mlx5hws_table *table,
	if (!bwc_matcher)
		return NULL;

	atomic_set(&bwc_matcher->num_of_rules, 0);

	/* Check if the required match params can be all matched
	 * in single STE, otherwise complex matcher is needed.
	 */
@@ -199,10 +201,12 @@ int mlx5hws_bwc_matcher_destroy_simple(struct mlx5hws_bwc_matcher *bwc_matcher)

int mlx5hws_bwc_matcher_destroy(struct mlx5hws_bwc_matcher *bwc_matcher)
{
	if (bwc_matcher->num_of_rules)
	u32 num_of_rules = atomic_read(&bwc_matcher->num_of_rules);

	if (num_of_rules)
		mlx5hws_err(bwc_matcher->matcher->tbl->ctx,
			    "BWC matcher destroy: matcher still has %d rules\n",
			    bwc_matcher->num_of_rules);
			    num_of_rules);

	mlx5hws_bwc_matcher_destroy_simple(bwc_matcher);

@@ -215,6 +219,8 @@ static int hws_bwc_queue_poll(struct mlx5hws_context *ctx,
			      u32 *pending_rules,
			      bool drain)
{
	unsigned long timeout = jiffies +
				msecs_to_jiffies(MLX5HWS_BWC_POLLING_TIMEOUT * MSEC_PER_SEC);
	struct mlx5hws_flow_op_result comp[MLX5HWS_BWC_MATCHER_REHASH_BURST_TH];
	u16 burst_th = hws_bwc_get_burst_th(ctx, queue_id);
	bool got_comp = *pending_rules >= burst_th;
@@ -250,6 +256,11 @@ static int hws_bwc_queue_poll(struct mlx5hws_context *ctx,
		}

		got_comp = !!ret;

		if (unlikely(!got_comp && time_after(jiffies, timeout))) {
			mlx5hws_err(ctx, "BWC poll error: polling queue %d - TIMEOUT\n", queue_id);
			return -ETIMEDOUT;
		}
	}

	return err;
@@ -309,7 +320,7 @@ static void hws_bwc_rule_list_add(struct mlx5hws_bwc_rule *bwc_rule, u16 idx)
{
	struct mlx5hws_bwc_matcher *bwc_matcher = bwc_rule->bwc_matcher;

	bwc_matcher->num_of_rules++;
	atomic_inc(&bwc_matcher->num_of_rules);
	bwc_rule->bwc_queue_idx = idx;
	list_add(&bwc_rule->list_node, &bwc_matcher->rules[idx]);
}
@@ -318,7 +329,7 @@ static void hws_bwc_rule_list_remove(struct mlx5hws_bwc_rule *bwc_rule)
{
	struct mlx5hws_bwc_matcher *bwc_matcher = bwc_rule->bwc_matcher;

	bwc_matcher->num_of_rules--;
	atomic_dec(&bwc_matcher->num_of_rules);
	list_del_init(&bwc_rule->list_node);
}

@@ -334,22 +345,21 @@ hws_bwc_rule_destroy_hws_sync(struct mlx5hws_bwc_rule *bwc_rule,
			      struct mlx5hws_rule_attr *rule_attr)
{
	struct mlx5hws_context *ctx = bwc_rule->bwc_matcher->matcher->tbl->ctx;
	struct mlx5hws_flow_op_result completion;
	u32 expected_completions = 1;
	int ret;

	ret = hws_bwc_rule_destroy_hws_async(bwc_rule, rule_attr);
	if (unlikely(ret))
		return ret;

	do {
		ret = mlx5hws_send_queue_poll(ctx, rule_attr->queue_id, &completion, 1);
	} while (ret != 1);

	if (unlikely(completion.status != MLX5HWS_FLOW_OP_SUCCESS ||
		     (bwc_rule->rule->status != MLX5HWS_RULE_STATUS_DELETED &&
		      bwc_rule->rule->status != MLX5HWS_RULE_STATUS_DELETING))) {
		mlx5hws_err(ctx, "Failed destroying BWC rule: completion %d, rule status %d\n",
			    completion.status, bwc_rule->rule->status);
	ret = hws_bwc_queue_poll(ctx, rule_attr->queue_id, &expected_completions, true);
	if (unlikely(ret))
		return ret;

	if (unlikely(bwc_rule->rule->status != MLX5HWS_RULE_STATUS_DELETED &&
		     bwc_rule->rule->status != MLX5HWS_RULE_STATUS_DELETING)) {
		mlx5hws_err(ctx, "Failed destroying BWC rule: rule status %d\n",
			    bwc_rule->rule->status);
		return -EINVAL;
	}

@@ -615,10 +625,14 @@ static int hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_match

				ret = hws_bwc_queue_poll(ctx, rule_attr.queue_id,
							 &pending_rules[i], false);
				if (unlikely(ret))
				if (unlikely(ret)) {
					mlx5hws_err(ctx,
						    "Moving BWC rule failed during rehash (%d)\n",
						    ret);
					goto free_bwc_rules;
				}
			}
		}
	} while (!all_done);

	/* drain all the bwc queues */
@@ -629,10 +643,13 @@ static int hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_match
			mlx5hws_send_engine_flush_queue(&ctx->send_queue[queue_id]);
			ret = hws_bwc_queue_poll(ctx, queue_id,
						 &pending_rules[i], true);
			if (unlikely(ret))
			if (unlikely(ret)) {
				mlx5hws_err(ctx,
					    "Moving BWC rule failed during rehash (%d)\n", ret);
				goto free_bwc_rules;
			}
		}
	}

free_bwc_rules:
	kfree(bwc_rules);
@@ -704,7 +721,8 @@ hws_bwc_matcher_rehash_size(struct mlx5hws_bwc_matcher *bwc_matcher)
	 * Need to check again if we really need rehash.
	 * If the reason for rehash was size, but not any more - skip rehash.
	 */
	if (!hws_bwc_matcher_rehash_size_needed(bwc_matcher, bwc_matcher->num_of_rules))
	if (!hws_bwc_matcher_rehash_size_needed(bwc_matcher,
						atomic_read(&bwc_matcher->num_of_rules)))
		return 0;

	/* Now we're done all the checking - do the rehash:
@@ -797,7 +815,7 @@ int mlx5hws_bwc_rule_create_simple(struct mlx5hws_bwc_rule *bwc_rule,
	}

	/* check if number of rules require rehash */
	num_of_rules = bwc_matcher->num_of_rules;
	num_of_rules = atomic_read(&bwc_matcher->num_of_rules);

	if (unlikely(hws_bwc_matcher_rehash_size_needed(bwc_matcher, num_of_rules))) {
		mutex_unlock(queue_lock);
+10 −2
Original line number Diff line number Diff line
@@ -8,10 +8,18 @@
#define MLX5HWS_BWC_MATCHER_SIZE_LOG_STEP 1
#define MLX5HWS_BWC_MATCHER_REHASH_PERCENT_TH 70
#define MLX5HWS_BWC_MATCHER_REHASH_BURST_TH 32
#define MLX5HWS_BWC_MATCHER_ATTACH_AT_NUM 255

/* Max number of AT attach operations for the same matcher.
 * When the limit is reached, next attempt to attach new AT
 * will result in creation of a new matcher and moving all
 * the rules to this matcher.
 */
#define MLX5HWS_BWC_MATCHER_ATTACH_AT_NUM 8

#define MLX5HWS_BWC_MAX_ACTS 16

#define MLX5HWS_BWC_POLLING_TIMEOUT 60

struct mlx5hws_bwc_matcher {
	struct mlx5hws_matcher *matcher;
	struct mlx5hws_match_template *mt;
@@ -19,7 +27,7 @@ struct mlx5hws_bwc_matcher {
	u8 num_of_at;
	u16 priority;
	u8 size_log;
	u32 num_of_rules; /* atomically accessed */
	atomic_t num_of_rules;
	struct list_head *rules;
};

+17 −78
Original line number Diff line number Diff line
@@ -257,6 +257,12 @@ int mlx5hws_cmd_set_fte(struct mlx5_core_dev *mdev,
						 dest->ext_reformat_id);
				}
				break;
			case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
				MLX5_SET(dest_format, in_dests,
					 destination_type, ifc_dest_type);
				MLX5_SET(dest_format, in_dests, destination_id,
					 dest->destination_id);
				break;
			default:
				ret = -EOPNOTSUPP;
				goto out;
@@ -359,7 +365,7 @@ void mlx5hws_cmd_set_attr_connect_miss_tbl(struct mlx5hws_context *ctx,
	ft_attr->type = fw_ft_type;
	ft_attr->table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL;

	default_miss_tbl = ctx->common_res[type].default_miss->ft_id;
	default_miss_tbl = ctx->common_res.default_miss->ft_id;
	if (!default_miss_tbl) {
		pr_warn("HWS: no flow table ID for default miss\n");
		return;
@@ -622,12 +628,12 @@ int mlx5hws_cmd_arg_create(struct mlx5_core_dev *mdev,
			   u32 pd,
			   u32 *arg_id)
{
	u32 in[MLX5_ST_SZ_DW(create_modify_header_arg_in)] = {0};
	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
	u32 in[MLX5_ST_SZ_DW(create_arg_in)] = {0};
	void *attr;
	int ret;

	attr = MLX5_ADDR_OF(create_arg_in, in, hdr);
	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, hdr);
	MLX5_SET(general_obj_in_cmd_hdr,
		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
	MLX5_SET(general_obj_in_cmd_hdr,
@@ -635,8 +641,8 @@ int mlx5hws_cmd_arg_create(struct mlx5_core_dev *mdev,
	MLX5_SET(general_obj_in_cmd_hdr,
		 attr, op_param.create.log_obj_range, log_obj_range);

	attr = MLX5_ADDR_OF(create_arg_in, in, arg);
	MLX5_SET(arg, attr, access_pd, pd);
	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, arg);
	MLX5_SET(modify_header_arg, attr, access_pd, pd);

	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
	if (ret) {
@@ -812,7 +818,7 @@ int mlx5hws_cmd_packet_reformat_create(struct mlx5_core_dev *mdev,
				       struct mlx5hws_cmd_packet_reformat_create_attr *attr,
				       u32 *reformat_id)
{
	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_out)] = {0};
	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {0};
	size_t insz, cmd_data_sz, cmd_total_sz;
	void *prctx;
	void *pdata;
@@ -845,7 +851,7 @@ int mlx5hws_cmd_packet_reformat_create(struct mlx5_core_dev *mdev,
		goto out;
	}

	*reformat_id = MLX5_GET(alloc_packet_reformat_out, out, packet_reformat_id);
	*reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
out:
	kfree(in);
	return ret;
@@ -854,13 +860,13 @@ int mlx5hws_cmd_packet_reformat_create(struct mlx5_core_dev *mdev,
int mlx5hws_cmd_packet_reformat_destroy(struct mlx5_core_dev *mdev,
					u32 reformat_id)
{
	u32 out[MLX5_ST_SZ_DW(dealloc_packet_reformat_out)] = {0};
	u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_in)] = {0};
	u32 out[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_out)] = {0};
	u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {0};
	int ret;

	MLX5_SET(dealloc_packet_reformat_in, in, opcode,
	MLX5_SET(dealloc_packet_reformat_context_in, in, opcode,
		 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
	MLX5_SET(dealloc_packet_reformat_in, in,
	MLX5_SET(dealloc_packet_reformat_context_in, in,
		 packet_reformat_id, reformat_id);

	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
@@ -889,73 +895,6 @@ int mlx5hws_cmd_sq_modify_rdy(struct mlx5_core_dev *mdev, u32 sqn)
	return ret;
}

int mlx5hws_cmd_allow_other_vhca_access(struct mlx5_core_dev *mdev,
					struct mlx5hws_cmd_allow_other_vhca_access_attr *attr)
{
	u32 out[MLX5_ST_SZ_DW(allow_other_vhca_access_out)] = {0};
	u32 in[MLX5_ST_SZ_DW(allow_other_vhca_access_in)] = {0};
	void *key;
	int ret;

	MLX5_SET(allow_other_vhca_access_in,
		 in, opcode, MLX5_CMD_OP_ALLOW_OTHER_VHCA_ACCESS);
	MLX5_SET(allow_other_vhca_access_in,
		 in, object_type_to_be_accessed, attr->obj_type);
	MLX5_SET(allow_other_vhca_access_in,
		 in, object_id_to_be_accessed, attr->obj_id);

	key = MLX5_ADDR_OF(allow_other_vhca_access_in, in, access_key);
	memcpy(key, attr->access_key, sizeof(attr->access_key));

	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
	if (ret)
		mlx5_core_err(mdev, "Failed to execute ALLOW_OTHER_VHCA_ACCESS command\n");

	return ret;
}

int mlx5hws_cmd_alias_obj_create(struct mlx5_core_dev *mdev,
				 struct mlx5hws_cmd_alias_obj_create_attr *alias_attr,
				 u32 *obj_id)
{
	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
	u32 in[MLX5_ST_SZ_DW(create_alias_obj_in)] = {0};
	void *attr;
	void *key;
	int ret;

	attr = MLX5_ADDR_OF(create_alias_obj_in, in, hdr);
	MLX5_SET(general_obj_in_cmd_hdr,
		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
	MLX5_SET(general_obj_in_cmd_hdr,
		 attr, obj_type, alias_attr->obj_type);
	MLX5_SET(general_obj_in_cmd_hdr, attr, op_param.create.alias_object, 1);

	attr = MLX5_ADDR_OF(create_alias_obj_in, in, alias_ctx);
	MLX5_SET(alias_context, attr, vhca_id_to_be_accessed, alias_attr->vhca_id);
	MLX5_SET(alias_context, attr, object_id_to_be_accessed, alias_attr->obj_id);

	key = MLX5_ADDR_OF(alias_context, attr, access_key);
	memcpy(key, alias_attr->access_key, sizeof(alias_attr->access_key));

	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
	if (ret) {
		mlx5_core_err(mdev, "Failed to create ALIAS OBJ\n");
		goto out;
	}

	*obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
out:
	return ret;
}

int mlx5hws_cmd_alias_obj_destroy(struct mlx5_core_dev *mdev,
				  u16 obj_type,
				  u32 obj_id)
{
	return hws_cmd_general_obj_destroy(mdev, obj_type, obj_id);
}

int mlx5hws_cmd_generate_wqe(struct mlx5_core_dev *mdev,
			     struct mlx5hws_cmd_generate_wqe_attr *attr,
			     struct mlx5_cqe64 *ret_cqe)
Loading