xref: /linux/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_debug.c (revision 9410645520e9b820069761f3450ef6661418e279)
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
3 
4 #include <linux/debugfs.h>
5 #include <linux/kernel.h>
6 #include <linux/seq_file.h>
7 #include <linux/version.h>
8 #include "mlx5hws_internal.h"
9 
10 static int
hws_debug_dump_matcher_template_definer(struct seq_file * f,void * parent_obj,struct mlx5hws_definer * definer,enum mlx5hws_debug_res_type type)11 hws_debug_dump_matcher_template_definer(struct seq_file *f,
12 					void *parent_obj,
13 					struct mlx5hws_definer *definer,
14 					enum mlx5hws_debug_res_type type)
15 {
16 	int i;
17 
18 	if (!definer)
19 		return 0;
20 
21 	seq_printf(f, "%d,0x%llx,0x%llx,%d,%d,",
22 		   type,
23 		   HWS_PTR_TO_ID(definer),
24 		   HWS_PTR_TO_ID(parent_obj),
25 		   definer->obj_id,
26 		   definer->type);
27 
28 	for (i = 0; i < DW_SELECTORS; i++)
29 		seq_printf(f, "0x%x%s", definer->dw_selector[i],
30 			   (i == DW_SELECTORS - 1) ? "," : "-");
31 
32 	for (i = 0; i < BYTE_SELECTORS; i++)
33 		seq_printf(f, "0x%x%s", definer->byte_selector[i],
34 			   (i == BYTE_SELECTORS - 1) ? "," : "-");
35 
36 	for (i = 0; i < MLX5HWS_JUMBO_TAG_SZ; i++)
37 		seq_printf(f, "%02x", definer->mask.jumbo[i]);
38 
39 	seq_puts(f, "\n");
40 
41 	return 0;
42 }
43 
44 static int
hws_debug_dump_matcher_match_template(struct seq_file * f,struct mlx5hws_matcher * matcher)45 hws_debug_dump_matcher_match_template(struct seq_file *f, struct mlx5hws_matcher *matcher)
46 {
47 	enum mlx5hws_debug_res_type type;
48 	int i, ret;
49 
50 	for (i = 0; i < matcher->num_of_mt; i++) {
51 		struct mlx5hws_match_template *mt = &matcher->mt[i];
52 
53 		seq_printf(f, "%d,0x%llx,0x%llx,%d,%d,%d\n",
54 			   MLX5HWS_DEBUG_RES_TYPE_MATCHER_MATCH_TEMPLATE,
55 			   HWS_PTR_TO_ID(mt),
56 			   HWS_PTR_TO_ID(matcher),
57 			   mt->fc_sz,
58 			   0, 0);
59 
60 		type = MLX5HWS_DEBUG_RES_TYPE_MATCHER_TEMPLATE_MATCH_DEFINER;
61 		ret = hws_debug_dump_matcher_template_definer(f, mt, mt->definer, type);
62 		if (ret)
63 			return ret;
64 	}
65 
66 	return 0;
67 }
68 
69 static int
hws_debug_dump_matcher_action_template(struct seq_file * f,struct mlx5hws_matcher * matcher)70 hws_debug_dump_matcher_action_template(struct seq_file *f, struct mlx5hws_matcher *matcher)
71 {
72 	enum mlx5hws_action_type action_type;
73 	int i, j;
74 
75 	for (i = 0; i < matcher->num_of_at; i++) {
76 		struct mlx5hws_action_template *at = &matcher->at[i];
77 
78 		seq_printf(f, "%d,0x%llx,0x%llx,%d,%d,%d",
79 			   MLX5HWS_DEBUG_RES_TYPE_MATCHER_ACTION_TEMPLATE,
80 			   HWS_PTR_TO_ID(at),
81 			   HWS_PTR_TO_ID(matcher),
82 			   at->only_term,
83 			   at->num_of_action_stes,
84 			   at->num_actions);
85 
86 		for (j = 0; j < at->num_actions; j++) {
87 			action_type = at->action_type_arr[j];
88 			seq_printf(f, ",%s", mlx5hws_action_type_to_str(action_type));
89 		}
90 
91 		seq_puts(f, "\n");
92 	}
93 
94 	return 0;
95 }
96 
97 static int
hws_debug_dump_matcher_attr(struct seq_file * f,struct mlx5hws_matcher * matcher)98 hws_debug_dump_matcher_attr(struct seq_file *f, struct mlx5hws_matcher *matcher)
99 {
100 	struct mlx5hws_matcher_attr *attr = &matcher->attr;
101 
102 	seq_printf(f, "%d,0x%llx,%d,%d,%d,%d,%d,%d,%d,%d\n",
103 		   MLX5HWS_DEBUG_RES_TYPE_MATCHER_ATTR,
104 		   HWS_PTR_TO_ID(matcher),
105 		   attr->priority,
106 		   attr->mode,
107 		   attr->table.sz_row_log,
108 		   attr->table.sz_col_log,
109 		   attr->optimize_using_rule_idx,
110 		   attr->optimize_flow_src,
111 		   attr->insert_mode,
112 		   attr->distribute_mode);
113 
114 	return 0;
115 }
116 
hws_debug_dump_matcher(struct seq_file * f,struct mlx5hws_matcher * matcher)117 static int hws_debug_dump_matcher(struct seq_file *f, struct mlx5hws_matcher *matcher)
118 {
119 	enum mlx5hws_table_type tbl_type = matcher->tbl->type;
120 	struct mlx5hws_cmd_ft_query_attr ft_attr = {0};
121 	struct mlx5hws_pool_chunk *ste;
122 	struct mlx5hws_pool *ste_pool;
123 	u64 icm_addr_0 = 0;
124 	u64 icm_addr_1 = 0;
125 	u32 ste_0_id = -1;
126 	u32 ste_1_id = -1;
127 	int ret;
128 
129 	seq_printf(f, "%d,0x%llx,0x%llx,%d,%d,0x%llx",
130 		   MLX5HWS_DEBUG_RES_TYPE_MATCHER,
131 		   HWS_PTR_TO_ID(matcher),
132 		   HWS_PTR_TO_ID(matcher->tbl),
133 		   matcher->num_of_mt,
134 		   matcher->end_ft_id,
135 		   matcher->col_matcher ? HWS_PTR_TO_ID(matcher->col_matcher) : 0);
136 
137 	ste = &matcher->match_ste.ste;
138 	ste_pool = matcher->match_ste.pool;
139 	if (ste_pool) {
140 		ste_0_id = mlx5hws_pool_chunk_get_base_id(ste_pool, ste);
141 		if (tbl_type == MLX5HWS_TABLE_TYPE_FDB)
142 			ste_1_id = mlx5hws_pool_chunk_get_base_mirror_id(ste_pool, ste);
143 	}
144 
145 	seq_printf(f, ",%d,%d,%d,%d",
146 		   matcher->match_ste.rtc_0_id,
147 		   (int)ste_0_id,
148 		   matcher->match_ste.rtc_1_id,
149 		   (int)ste_1_id);
150 
151 	ste = &matcher->action_ste[0].ste;
152 	ste_pool = matcher->action_ste[0].pool;
153 	if (ste_pool) {
154 		ste_0_id = mlx5hws_pool_chunk_get_base_id(ste_pool, ste);
155 		if (tbl_type == MLX5HWS_TABLE_TYPE_FDB)
156 			ste_1_id = mlx5hws_pool_chunk_get_base_mirror_id(ste_pool, ste);
157 		else
158 			ste_1_id = -1;
159 	} else {
160 		ste_0_id = -1;
161 		ste_1_id = -1;
162 	}
163 
164 	ft_attr.type = matcher->tbl->fw_ft_type;
165 	ret = mlx5hws_cmd_flow_table_query(matcher->tbl->ctx->mdev,
166 					   matcher->end_ft_id,
167 					   &ft_attr,
168 					   &icm_addr_0,
169 					   &icm_addr_1);
170 	if (ret)
171 		return ret;
172 
173 	seq_printf(f, ",%d,%d,%d,%d,%d,0x%llx,0x%llx\n",
174 		   matcher->action_ste[0].rtc_0_id,
175 		   (int)ste_0_id,
176 		   matcher->action_ste[0].rtc_1_id,
177 		   (int)ste_1_id,
178 		   0,
179 		   mlx5hws_debug_icm_to_idx(icm_addr_0),
180 		   mlx5hws_debug_icm_to_idx(icm_addr_1));
181 
182 	ret = hws_debug_dump_matcher_attr(f, matcher);
183 	if (ret)
184 		return ret;
185 
186 	ret = hws_debug_dump_matcher_match_template(f, matcher);
187 	if (ret)
188 		return ret;
189 
190 	ret = hws_debug_dump_matcher_action_template(f, matcher);
191 	if (ret)
192 		return ret;
193 
194 	return 0;
195 }
196 
hws_debug_dump_table(struct seq_file * f,struct mlx5hws_table * tbl)197 static int hws_debug_dump_table(struct seq_file *f, struct mlx5hws_table *tbl)
198 {
199 	struct mlx5hws_cmd_ft_query_attr ft_attr = {0};
200 	struct mlx5hws_matcher *matcher;
201 	u64 local_icm_addr_0 = 0;
202 	u64 local_icm_addr_1 = 0;
203 	u64 icm_addr_0 = 0;
204 	u64 icm_addr_1 = 0;
205 	int ret;
206 
207 	seq_printf(f, "%d,0x%llx,0x%llx,%d,%d,%d,%d,%d",
208 		   MLX5HWS_DEBUG_RES_TYPE_TABLE,
209 		   HWS_PTR_TO_ID(tbl),
210 		   HWS_PTR_TO_ID(tbl->ctx),
211 		   tbl->ft_id,
212 		   MLX5HWS_TABLE_TYPE_BASE + tbl->type,
213 		   tbl->fw_ft_type,
214 		   tbl->level,
215 		   0);
216 
217 	ft_attr.type = tbl->fw_ft_type;
218 	ret = mlx5hws_cmd_flow_table_query(tbl->ctx->mdev,
219 					   tbl->ft_id,
220 					   &ft_attr,
221 					   &icm_addr_0,
222 					   &icm_addr_1);
223 	if (ret)
224 		return ret;
225 
226 	seq_printf(f, ",0x%llx,0x%llx,0x%llx,0x%llx,0x%llx\n",
227 		   mlx5hws_debug_icm_to_idx(icm_addr_0),
228 		   mlx5hws_debug_icm_to_idx(icm_addr_1),
229 		   mlx5hws_debug_icm_to_idx(local_icm_addr_0),
230 		   mlx5hws_debug_icm_to_idx(local_icm_addr_1),
231 		   HWS_PTR_TO_ID(tbl->default_miss.miss_tbl));
232 
233 	list_for_each_entry(matcher, &tbl->matchers_list, list_node) {
234 		ret = hws_debug_dump_matcher(f, matcher);
235 		if (ret)
236 			return ret;
237 	}
238 
239 	return 0;
240 }
241 
242 static int
hws_debug_dump_context_send_engine(struct seq_file * f,struct mlx5hws_context * ctx)243 hws_debug_dump_context_send_engine(struct seq_file *f, struct mlx5hws_context *ctx)
244 {
245 	struct mlx5hws_send_engine *send_queue;
246 	struct mlx5hws_send_ring *send_ring;
247 	struct mlx5hws_send_ring_cq *cq;
248 	struct mlx5hws_send_ring_sq *sq;
249 	int i;
250 
251 	for (i = 0; i < (int)ctx->queues; i++) {
252 		send_queue = &ctx->send_queue[i];
253 		seq_printf(f, "%d,0x%llx,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
254 			   MLX5HWS_DEBUG_RES_TYPE_CONTEXT_SEND_ENGINE,
255 			   HWS_PTR_TO_ID(ctx),
256 			   i,
257 			   send_queue->used_entries,
258 			   send_queue->num_entries,
259 			   1, /* one send ring per queue */
260 			   send_queue->num_entries,
261 			   send_queue->err,
262 			   send_queue->completed.ci,
263 			   send_queue->completed.pi,
264 			   send_queue->completed.mask);
265 
266 		send_ring = &send_queue->send_ring;
267 		cq = &send_ring->send_cq;
268 		sq = &send_ring->send_sq;
269 
270 		seq_printf(f, "%d,0x%llx,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
271 			   MLX5HWS_DEBUG_RES_TYPE_CONTEXT_SEND_RING,
272 			   HWS_PTR_TO_ID(ctx),
273 			   0, /* one send ring per send queue */
274 			   i,
275 			   cq->mcq.cqn,
276 			   0,
277 			   0,
278 			   0,
279 			   0,
280 			   0,
281 			   0,
282 			   cq->mcq.cqe_sz,
283 			   sq->sqn,
284 			   0,
285 			   0,
286 			   0);
287 	}
288 
289 	return 0;
290 }
291 
hws_debug_dump_context_caps(struct seq_file * f,struct mlx5hws_context * ctx)292 static int hws_debug_dump_context_caps(struct seq_file *f, struct mlx5hws_context *ctx)
293 {
294 	struct mlx5hws_cmd_query_caps *caps = ctx->caps;
295 
296 	seq_printf(f, "%d,0x%llx,%s,%d,%d,%d,%d,",
297 		   MLX5HWS_DEBUG_RES_TYPE_CONTEXT_CAPS,
298 		   HWS_PTR_TO_ID(ctx),
299 		   caps->fw_ver,
300 		   caps->wqe_based_update,
301 		   caps->ste_format,
302 		   caps->ste_alloc_log_max,
303 		   caps->log_header_modify_argument_max_alloc);
304 
305 	seq_printf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s\n",
306 		   caps->flex_protocols,
307 		   caps->rtc_reparse_mode,
308 		   caps->rtc_index_mode,
309 		   caps->ste_alloc_log_gran,
310 		   caps->stc_alloc_log_max,
311 		   caps->stc_alloc_log_gran,
312 		   caps->rtc_log_depth_max,
313 		   caps->format_select_gtpu_dw_0,
314 		   caps->format_select_gtpu_dw_1,
315 		   caps->format_select_gtpu_dw_2,
316 		   caps->format_select_gtpu_ext_dw_0,
317 		   caps->nic_ft.max_level,
318 		   caps->nic_ft.reparse,
319 		   caps->fdb_ft.max_level,
320 		   caps->fdb_ft.reparse,
321 		   caps->log_header_modify_argument_granularity,
322 		   caps->linear_match_definer,
323 		   "regc_3");
324 
325 	return 0;
326 }
327 
hws_debug_dump_context_attr(struct seq_file * f,struct mlx5hws_context * ctx)328 static int hws_debug_dump_context_attr(struct seq_file *f, struct mlx5hws_context *ctx)
329 {
330 	seq_printf(f, "%u,0x%llx,%d,%zu,%d,%s,%d,%d\n",
331 		   MLX5HWS_DEBUG_RES_TYPE_CONTEXT_ATTR,
332 		   HWS_PTR_TO_ID(ctx),
333 		   ctx->pd_num,
334 		   ctx->queues,
335 		   ctx->send_queue->num_entries,
336 		   "None", /* no shared gvmi */
337 		   ctx->caps->vhca_id,
338 		   0xffff); /* no shared gvmi */
339 
340 	return 0;
341 }
342 
hws_debug_dump_context_info(struct seq_file * f,struct mlx5hws_context * ctx)343 static int hws_debug_dump_context_info(struct seq_file *f, struct mlx5hws_context *ctx)
344 {
345 	struct mlx5_core_dev *dev = ctx->mdev;
346 	int ret;
347 
348 	seq_printf(f, "%d,0x%llx,%d,%s,%s.KERNEL_%u_%u_%u\n",
349 		   MLX5HWS_DEBUG_RES_TYPE_CONTEXT,
350 		   HWS_PTR_TO_ID(ctx),
351 		   ctx->flags & MLX5HWS_CONTEXT_FLAG_HWS_SUPPORT,
352 		   pci_name(dev->pdev),
353 		   HWS_DEBUG_FORMAT_VERSION,
354 		   LINUX_VERSION_MAJOR,
355 		   LINUX_VERSION_PATCHLEVEL,
356 		   LINUX_VERSION_SUBLEVEL);
357 
358 	ret = hws_debug_dump_context_attr(f, ctx);
359 	if (ret)
360 		return ret;
361 
362 	ret = hws_debug_dump_context_caps(f, ctx);
363 	if (ret)
364 		return ret;
365 
366 	return 0;
367 }
368 
hws_debug_dump_context_stc_resource(struct seq_file * f,struct mlx5hws_context * ctx,u32 tbl_type,struct mlx5hws_pool_resource * resource)369 static int hws_debug_dump_context_stc_resource(struct seq_file *f,
370 					       struct mlx5hws_context *ctx,
371 					       u32 tbl_type,
372 					       struct mlx5hws_pool_resource *resource)
373 {
374 	seq_printf(f, "%d,0x%llx,%u,%u\n",
375 		   MLX5HWS_DEBUG_RES_TYPE_CONTEXT_STC,
376 		   HWS_PTR_TO_ID(ctx),
377 		   tbl_type,
378 		   resource->base_id);
379 
380 	return 0;
381 }
382 
hws_debug_dump_context_stc(struct seq_file * f,struct mlx5hws_context * ctx)383 static int hws_debug_dump_context_stc(struct seq_file *f, struct mlx5hws_context *ctx)
384 {
385 	struct mlx5hws_pool *stc_pool;
386 	u32 table_type;
387 	int ret;
388 	int i;
389 
390 	for (i = 0; i < MLX5HWS_TABLE_TYPE_MAX; i++) {
391 		stc_pool = ctx->stc_pool[i];
392 		table_type = MLX5HWS_TABLE_TYPE_BASE + i;
393 
394 		if (!stc_pool)
395 			continue;
396 
397 		if (stc_pool->resource[0]) {
398 			ret = hws_debug_dump_context_stc_resource(f, ctx, table_type,
399 								  stc_pool->resource[0]);
400 			if (ret)
401 				return ret;
402 		}
403 
404 		if (i == MLX5HWS_TABLE_TYPE_FDB && stc_pool->mirror_resource[0]) {
405 			ret = hws_debug_dump_context_stc_resource(f, ctx, table_type,
406 								  stc_pool->mirror_resource[0]);
407 			if (ret)
408 				return ret;
409 		}
410 	}
411 
412 	return 0;
413 }
414 
hws_debug_dump_context(struct seq_file * f,struct mlx5hws_context * ctx)415 static int hws_debug_dump_context(struct seq_file *f, struct mlx5hws_context *ctx)
416 {
417 	struct mlx5hws_table *tbl;
418 	int ret;
419 
420 	ret = hws_debug_dump_context_info(f, ctx);
421 	if (ret)
422 		return ret;
423 
424 	ret = hws_debug_dump_context_send_engine(f, ctx);
425 	if (ret)
426 		return ret;
427 
428 	ret = hws_debug_dump_context_stc(f, ctx);
429 	if (ret)
430 		return ret;
431 
432 	list_for_each_entry(tbl, &ctx->tbl_list, tbl_list_node) {
433 		ret = hws_debug_dump_table(f, tbl);
434 		if (ret)
435 			return ret;
436 	}
437 
438 	return 0;
439 }
440 
441 static int
hws_debug_dump(struct seq_file * f,struct mlx5hws_context * ctx)442 hws_debug_dump(struct seq_file *f, struct mlx5hws_context *ctx)
443 {
444 	int ret;
445 
446 	if (!f || !ctx)
447 		return -EINVAL;
448 
449 	mutex_lock(&ctx->ctrl_lock);
450 	ret = hws_debug_dump_context(f, ctx);
451 	mutex_unlock(&ctx->ctrl_lock);
452 
453 	return ret;
454 }
455 
hws_dump_show(struct seq_file * file,void * priv)456 static int hws_dump_show(struct seq_file *file, void *priv)
457 {
458 	return hws_debug_dump(file, file->private);
459 }
460 DEFINE_SHOW_ATTRIBUTE(hws_dump);
461 
mlx5hws_debug_init_dump(struct mlx5hws_context * ctx)462 void mlx5hws_debug_init_dump(struct mlx5hws_context *ctx)
463 {
464 	struct mlx5_core_dev *dev = ctx->mdev;
465 	char file_name[128];
466 
467 	ctx->debug_info.steering_debugfs =
468 		debugfs_create_dir("steering", mlx5_debugfs_get_dev_root(dev));
469 	ctx->debug_info.fdb_debugfs =
470 		debugfs_create_dir("fdb", ctx->debug_info.steering_debugfs);
471 
472 	sprintf(file_name, "ctx_%p", ctx);
473 	debugfs_create_file(file_name, 0444, ctx->debug_info.fdb_debugfs,
474 			    ctx, &hws_dump_fops);
475 }
476 
mlx5hws_debug_uninit_dump(struct mlx5hws_context * ctx)477 void mlx5hws_debug_uninit_dump(struct mlx5hws_context *ctx)
478 {
479 	debugfs_remove_recursive(ctx->debug_info.steering_debugfs);
480 }
481