File Index
Files and directories
Sign in
FILE

context.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.c C
  1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2/* Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. */
  3
  4#include "internal.h"
  5
  6bool mlx5hws_context_cap_dynamic_reparse(struct mlx5hws_context *ctx)
  7{
  8	return IS_BIT_SET(ctx->caps->rtc_reparse_mode, MLX5_IFC_RTC_REPARSE_BY_STC);
  9}
 10
 11u8 mlx5hws_context_get_reparse_mode(struct mlx5hws_context *ctx)
 12{
 13	/* Prefer to use dynamic reparse, reparse only specific actions */
 14	if (mlx5hws_context_cap_dynamic_reparse(ctx))
 15		return MLX5_IFC_RTC_REPARSE_NEVER;
 16
 17	/* Otherwise use less efficient static */
 18	return MLX5_IFC_RTC_REPARSE_ALWAYS;
 19}
 20
 21static int hws_context_pools_init(struct mlx5hws_context *ctx)
 22{
 23	struct mlx5hws_pool_attr pool_attr = {0};
 24	u8 max_log_sz;
 25	int ret;
 26
 27	ret = mlx5hws_pat_init_pattern_cache(&ctx->pattern_cache);
 28	if (ret)
 29		return ret;
 30
 31	ret = mlx5hws_definer_init_cache(&ctx->definer_cache);
 32	if (ret)
 33		goto uninit_pat_cache;
 34
 35	/* Create an STC pool per FT type */
 36	pool_attr.pool_type = MLX5HWS_POOL_TYPE_STC;
 37	max_log_sz = min(MLX5HWS_POOL_STC_LOG_SZ, ctx->caps->stc_alloc_log_max);
 38	pool_attr.alloc_log_sz = max(max_log_sz, ctx->caps->stc_alloc_log_gran);
 39
 40	pool_attr.table_type = MLX5HWS_TABLE_TYPE_FDB;
 41	ctx->stc_pool = mlx5hws_pool_create(ctx, &pool_attr);
 42	if (!ctx->stc_pool) {
 43		mlx5hws_err(ctx, "Failed to allocate STC pool\n");
 44		ret = -ENOMEM;
 45		goto uninit_cache;
 46	}
 47
 48	return 0;
 49
 50uninit_cache:
 51	mlx5hws_definer_uninit_cache(ctx->definer_cache);
 52uninit_pat_cache:
 53	mlx5hws_pat_uninit_pattern_cache(ctx->pattern_cache);
 54	return ret;
 55}
 56
 57static void hws_context_pools_uninit(struct mlx5hws_context *ctx)
 58{
 59	if (ctx->stc_pool)
 60		mlx5hws_pool_destroy(ctx->stc_pool);
 61
 62	mlx5hws_definer_uninit_cache(ctx->definer_cache);
 63	mlx5hws_pat_uninit_pattern_cache(ctx->pattern_cache);
 64}
 65
 66static int hws_context_init_pd(struct mlx5hws_context *ctx)
 67{
 68	int ret = 0;
 69
 70	ret = mlx5_core_alloc_pd(ctx->mdev, &ctx->pd_num);
 71	if (ret) {
 72		mlx5hws_err(ctx, "Failed to allocate PD\n");
 73		return ret;
 74	}
 75
 76	ctx->flags |= MLX5HWS_CONTEXT_FLAG_PRIVATE_PD;
 77
 78	return 0;
 79}
 80
 81static int hws_context_uninit_pd(struct mlx5hws_context *ctx)
 82{
 83	if (ctx->flags & MLX5HWS_CONTEXT_FLAG_PRIVATE_PD)
 84		mlx5_core_dealloc_pd(ctx->mdev, ctx->pd_num);
 85
 86	return 0;
 87}
 88
 89static void hws_context_check_hws_supp(struct mlx5hws_context *ctx)
 90{
 91	struct mlx5hws_cmd_query_caps *caps = ctx->caps;
 92
 93	/* HWS not supported on device / FW */
 94	if (!caps->wqe_based_update) {
 95		mlx5hws_err(ctx, "Required HWS WQE based insertion cap not supported\n");
 96		return;
 97	}
 98
 99	if (!caps->eswitch_manager) {
100		mlx5hws_err(ctx, "HWS is not supported for non eswitch manager port\n");
101		return;
102	}
103
104	/* Current solution requires all rules to set reparse bit */
105	if ((!caps->nic_ft.reparse ||
106	     (!caps->fdb_ft.reparse && caps->eswitch_manager)) ||
107	    !IS_BIT_SET(caps->rtc_reparse_mode, MLX5_IFC_RTC_REPARSE_ALWAYS)) {
108		mlx5hws_err(ctx, "Required HWS reparse cap not supported\n");
109		return;
110	}
111
112	/* FW/HW must support 8DW STE */
113	if (!IS_BIT_SET(caps->ste_format, MLX5_IFC_RTC_STE_FORMAT_8DW)) {
114		mlx5hws_err(ctx, "Required HWS STE format not supported\n");
115		return;
116	}
117
118	/* Adding rules by hash and by offset are requirements */
119	if (!IS_BIT_SET(caps->rtc_index_mode, MLX5_IFC_RTC_STE_UPDATE_MODE_BY_HASH) ||
120	    !IS_BIT_SET(caps->rtc_index_mode, MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET)) {
121		mlx5hws_err(ctx, "Required HWS RTC update mode not supported\n");
122		return;
123	}
124
125	/* Support for SELECT definer ID is required */
126	if (!IS_BIT_SET(caps->definer_format_sup, MLX5_IFC_DEFINER_FORMAT_ID_SELECT)) {
127		mlx5hws_err(ctx, "Required HWS Dynamic definer not supported\n");
128		return;
129	}
130
131	ctx->flags |= MLX5HWS_CONTEXT_FLAG_HWS_SUPPORT;
132}
133
134static int hws_context_init_hws(struct mlx5hws_context *ctx,
135				struct mlx5hws_context_attr *attr)
136{
137	int ret;
138
139	hws_context_check_hws_supp(ctx);
140
141	if (!(ctx->flags & MLX5HWS_CONTEXT_FLAG_HWS_SUPPORT))
142		return 0;
143
144	ret = hws_context_init_pd(ctx);
145	if (ret)
146		return ret;
147
148	ret = hws_context_pools_init(ctx);
149	if (ret)
150		goto uninit_pd;
151
152	/* Context has support for backward compatible API,
153	 * and does not have support for native HWS API.
154	 */
155	ctx->flags |= MLX5HWS_CONTEXT_FLAG_BWC_SUPPORT;
156
157	ret = mlx5hws_send_queues_open(ctx, attr->queues, attr->queue_size);
158	if (ret)
159		goto pools_uninit;
160
161	ret = mlx5hws_action_ste_pool_init(ctx);
162	if (ret)
163		goto close_queues;
164
165	INIT_LIST_HEAD(&ctx->tbl_list);
166
167	return 0;
168
169close_queues:
170	mlx5hws_send_queues_close(ctx);
171pools_uninit:
172	hws_context_pools_uninit(ctx);
173uninit_pd:
174	hws_context_uninit_pd(ctx);
175	return ret;
176}
177
178static void hws_context_uninit_hws(struct mlx5hws_context *ctx)
179{
180	if (!(ctx->flags & MLX5HWS_CONTEXT_FLAG_HWS_SUPPORT))
181		return;
182
183	mlx5hws_action_ste_pool_uninit(ctx);
184	mlx5hws_send_queues_close(ctx);
185	hws_context_pools_uninit(ctx);
186	hws_context_uninit_pd(ctx);
187}
188
189struct mlx5hws_context *mlx5hws_context_open(struct mlx5_core_dev *mdev,
190					     struct mlx5hws_context_attr *attr)
191{
192	struct mlx5hws_context *ctx;
193	int ret;
194
195	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
196	if (!ctx)
197		return NULL;
198
199	ctx->mdev = mdev;
200
201	mutex_init(&ctx->ctrl_lock);
202	xa_init(&ctx->peer_ctx_xa);
203
204	ctx->caps = kzalloc(sizeof(*ctx->caps), GFP_KERNEL);
205	if (!ctx->caps)
206		goto free_ctx;
207
208	ret = mlx5hws_cmd_query_caps(mdev, ctx->caps);
209	if (ret)
210		goto free_caps;
211
212	ret = mlx5hws_vport_init_vports(ctx);
213	if (ret)
214		goto free_caps;
215
216	ret = hws_context_init_hws(ctx, attr);
217	if (ret)
218		goto uninit_vports;
219
220	mlx5hws_debug_init_dump(ctx);
221
222	return ctx;
223
224uninit_vports:
225	mlx5hws_vport_uninit_vports(ctx);
226free_caps:
227	kfree(ctx->caps);
228free_ctx:
229	xa_destroy(&ctx->peer_ctx_xa);
230	mutex_destroy(&ctx->ctrl_lock);
231	kfree(ctx);
232	return NULL;
233}
234
235int mlx5hws_context_close(struct mlx5hws_context *ctx)
236{
237	mlx5hws_debug_uninit_dump(ctx);
238	hws_context_uninit_hws(ctx);
239	mlx5hws_vport_uninit_vports(ctx);
240	kfree(ctx->caps);
241	xa_destroy(&ctx->peer_ctx_xa);
242	mutex_destroy(&ctx->ctrl_lock);
243	kfree(ctx);
244	return 0;
245}
246
247void mlx5hws_context_set_peer(struct mlx5hws_context *ctx,
248			      struct mlx5hws_context *peer_ctx,
249			      u16 peer_vhca_id)
250{
251	mutex_lock(&ctx->ctrl_lock);
252
253	if (xa_err(xa_store(&ctx->peer_ctx_xa, peer_vhca_id, peer_ctx, GFP_KERNEL)))
254		pr_warn("HWS: failed storing peer vhca ID in peer xarray\n");
255
256	mutex_unlock(&ctx->ctrl_lock);
257}
~/ Read-only file preview.