File Index
Files and directories
Sign in
FILE

debug.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.c C
  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 "internal.h"
  9
 10static int
 11hws_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
 44static int
 45hws_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
 69static int
 70hws_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
 97static int
 98hws_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,-1,-1,%d,%d\n",
103		   MLX5HWS_DEBUG_RES_TYPE_MATCHER_ATTR,
104		   HWS_PTR_TO_ID(matcher),
105		   attr->priority,
106		   attr->mode,
107		   attr->size[MLX5HWS_MATCHER_SIZE_TYPE_RX].table.sz_row_log,
108		   attr->size[MLX5HWS_MATCHER_SIZE_TYPE_RX].table.sz_col_log,
109		   attr->optimize_using_rule_idx,
110		   attr->optimize_flow_src,
111		   attr->insert_mode,
112		   attr->distribute_mode,
113		   attr->size[MLX5HWS_MATCHER_SIZE_TYPE_TX].table.sz_row_log,
114		   attr->size[MLX5HWS_MATCHER_SIZE_TYPE_TX].table.sz_col_log);
115
116	return 0;
117}
118
119static int hws_debug_dump_matcher(struct seq_file *f, struct mlx5hws_matcher *matcher)
120{
121	enum mlx5hws_table_type tbl_type = matcher->tbl->type;
122	struct mlx5hws_cmd_ft_query_attr ft_attr = {0};
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_0_id = matcher->match_ste.ste_0_base;
138	if (tbl_type == MLX5HWS_TABLE_TYPE_FDB)
139		ste_1_id = matcher->match_ste.ste_1_base;
140
141	seq_printf(f, ",%d,%d,%d,%d",
142		   matcher->match_ste.rtc_0_id,
143		   (int)ste_0_id,
144		   matcher->match_ste.rtc_1_id,
145		   (int)ste_1_id);
146
147	ft_attr.type = matcher->tbl->fw_ft_type;
148	ret = mlx5hws_cmd_flow_table_query(matcher->tbl->ctx->mdev,
149					   matcher->end_ft_id,
150					   &ft_attr,
151					   &icm_addr_0,
152					   &icm_addr_1);
153	if (ret)
154		return ret;
155
156	seq_printf(f, ",-1,-1,-1,-1,0,0x%llx,0x%llx\n",
157		   mlx5hws_debug_icm_to_idx(icm_addr_0),
158		   mlx5hws_debug_icm_to_idx(icm_addr_1));
159
160	ret = hws_debug_dump_matcher_attr(f, matcher);
161	if (ret)
162		return ret;
163
164	ret = hws_debug_dump_matcher_match_template(f, matcher);
165	if (ret)
166		return ret;
167
168	ret = hws_debug_dump_matcher_action_template(f, matcher);
169	if (ret)
170		return ret;
171
172	return 0;
173}
174
175static int hws_debug_dump_table(struct seq_file *f, struct mlx5hws_table *tbl)
176{
177	struct mlx5hws_cmd_ft_query_attr ft_attr = {0};
178	struct mlx5hws_matcher *matcher;
179	u64 local_icm_addr_0 = 0;
180	u64 local_icm_addr_1 = 0;
181	u64 icm_addr_0 = 0;
182	u64 icm_addr_1 = 0;
183	int ret;
184
185	seq_printf(f, "%d,0x%llx,0x%llx,%d,%d,%d,%d,%d",
186		   MLX5HWS_DEBUG_RES_TYPE_TABLE,
187		   HWS_PTR_TO_ID(tbl),
188		   HWS_PTR_TO_ID(tbl->ctx),
189		   tbl->ft_id,
190		   MLX5HWS_TABLE_TYPE_BASE + tbl->type,
191		   tbl->fw_ft_type,
192		   tbl->level,
193		   0);
194
195	ft_attr.type = tbl->fw_ft_type;
196	ret = mlx5hws_cmd_flow_table_query(tbl->ctx->mdev,
197					   tbl->ft_id,
198					   &ft_attr,
199					   &icm_addr_0,
200					   &icm_addr_1);
201	if (ret)
202		return ret;
203
204	seq_printf(f, ",0x%llx,0x%llx,0x%llx,0x%llx,0x%llx\n",
205		   mlx5hws_debug_icm_to_idx(icm_addr_0),
206		   mlx5hws_debug_icm_to_idx(icm_addr_1),
207		   mlx5hws_debug_icm_to_idx(local_icm_addr_0),
208		   mlx5hws_debug_icm_to_idx(local_icm_addr_1),
209		   HWS_PTR_TO_ID(tbl->default_miss.miss_tbl));
210
211	list_for_each_entry(matcher, &tbl->matchers_list, list_node) {
212		ret = hws_debug_dump_matcher(f, matcher);
213		if (ret)
214			return ret;
215	}
216
217	return 0;
218}
219
220static int
221hws_debug_dump_context_send_engine(struct seq_file *f, struct mlx5hws_context *ctx)
222{
223	struct mlx5hws_send_engine *send_queue;
224	struct mlx5hws_send_ring *send_ring;
225	struct mlx5hws_send_ring_cq *cq;
226	struct mlx5hws_send_ring_sq *sq;
227	int i;
228
229	for (i = 0; i < (int)ctx->queues; i++) {
230		send_queue = &ctx->send_queue[i];
231		seq_printf(f, "%d,0x%llx,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
232			   MLX5HWS_DEBUG_RES_TYPE_CONTEXT_SEND_ENGINE,
233			   HWS_PTR_TO_ID(ctx),
234			   i,
235			   send_queue->used_entries,
236			   send_queue->num_entries,
237			   1, /* one send ring per queue */
238			   send_queue->num_entries,
239			   send_queue->err,
240			   send_queue->completed.ci,
241			   send_queue->completed.pi,
242			   send_queue->completed.mask);
243
244		send_ring = &send_queue->send_ring;
245		cq = &send_ring->send_cq;
246		sq = &send_ring->send_sq;
247
248		seq_printf(f, "%d,0x%llx,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
249			   MLX5HWS_DEBUG_RES_TYPE_CONTEXT_SEND_RING,
250			   HWS_PTR_TO_ID(ctx),
251			   0, /* one send ring per send queue */
252			   i,
253			   cq->mcq.cqn,
254			   0,
255			   0,
256			   0,
257			   0,
258			   0,
259			   0,
260			   cq->mcq.cqe_sz,
261			   sq->sqn,
262			   0,
263			   0,
264			   0);
265	}
266
267	return 0;
268}
269
270static int hws_debug_dump_context_caps(struct seq_file *f, struct mlx5hws_context *ctx)
271{
272	struct mlx5hws_cmd_query_caps *caps = ctx->caps;
273
274	seq_printf(f, "%d,0x%llx,%s,%d,%d,%d,%d,",
275		   MLX5HWS_DEBUG_RES_TYPE_CONTEXT_CAPS,
276		   HWS_PTR_TO_ID(ctx),
277		   caps->fw_ver,
278		   caps->wqe_based_update,
279		   caps->ste_format,
280		   caps->ste_alloc_log_max,
281		   caps->log_header_modify_argument_max_alloc);
282
283	seq_printf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s\n",
284		   caps->flex_protocols,
285		   caps->rtc_reparse_mode,
286		   caps->rtc_index_mode,
287		   caps->ste_alloc_log_gran,
288		   caps->stc_alloc_log_max,
289		   caps->stc_alloc_log_gran,
290		   caps->rtc_log_depth_max,
291		   caps->format_select_gtpu_dw_0,
292		   caps->format_select_gtpu_dw_1,
293		   caps->format_select_gtpu_dw_2,
294		   caps->format_select_gtpu_ext_dw_0,
295		   caps->nic_ft.max_level,
296		   caps->nic_ft.reparse,
297		   caps->fdb_ft.max_level,
298		   caps->fdb_ft.reparse,
299		   caps->log_header_modify_argument_granularity,
300		   caps->linear_match_definer,
301		   "regc_3");
302
303	return 0;
304}
305
306static int hws_debug_dump_context_attr(struct seq_file *f, struct mlx5hws_context *ctx)
307{
308	seq_printf(f, "%u,0x%llx,%d,%zu,%d,%s,%d,%d\n",
309		   MLX5HWS_DEBUG_RES_TYPE_CONTEXT_ATTR,
310		   HWS_PTR_TO_ID(ctx),
311		   ctx->pd_num,
312		   ctx->queues,
313		   ctx->send_queue->num_entries,
314		   "None", /* no shared gvmi */
315		   ctx->caps->vhca_id,
316		   0xffff); /* no shared gvmi */
317
318	return 0;
319}
320
321static int hws_debug_dump_context_info(struct seq_file *f, struct mlx5hws_context *ctx)
322{
323	struct mlx5_core_dev *dev = ctx->mdev;
324	int ret;
325
326	seq_printf(f, "%d,0x%llx,%d,%s,%s.KERNEL_%u_%u_%u\n",
327		   MLX5HWS_DEBUG_RES_TYPE_CONTEXT,
328		   HWS_PTR_TO_ID(ctx),
329		   ctx->flags & MLX5HWS_CONTEXT_FLAG_HWS_SUPPORT,
330		   pci_name(dev->pdev),
331		   HWS_DEBUG_FORMAT_VERSION,
332		   LINUX_VERSION_MAJOR,
333		   LINUX_VERSION_PATCHLEVEL,
334		   LINUX_VERSION_SUBLEVEL);
335
336	ret = hws_debug_dump_context_attr(f, ctx);
337	if (ret)
338		return ret;
339
340	ret = hws_debug_dump_context_caps(f, ctx);
341	if (ret)
342		return ret;
343
344	return 0;
345}
346
347static int hws_debug_dump_context_stc_resource(struct seq_file *f,
348					       struct mlx5hws_context *ctx,
349					       struct mlx5hws_pool_resource *resource)
350{
351	u32 tbl_type = MLX5HWS_TABLE_TYPE_BASE + MLX5HWS_TABLE_TYPE_FDB;
352
353	seq_printf(f, "%d,0x%llx,%u,%u\n",
354		   MLX5HWS_DEBUG_RES_TYPE_CONTEXT_STC,
355		   HWS_PTR_TO_ID(ctx),
356		   tbl_type,
357		   resource->base_id);
358
359	return 0;
360}
361
362static int hws_debug_dump_context_stc(struct seq_file *f, struct mlx5hws_context *ctx)
363{
364	struct mlx5hws_pool *stc_pool = ctx->stc_pool;
365	int ret;
366
367	if (!stc_pool)
368		return 0;
369
370	if (stc_pool->resource) {
371		ret = hws_debug_dump_context_stc_resource(f, ctx,
372							  stc_pool->resource);
373		if (ret)
374			return ret;
375	}
376
377	if (stc_pool->mirror_resource) {
378		struct mlx5hws_pool_resource *res = stc_pool->mirror_resource;
379
380		ret = hws_debug_dump_context_stc_resource(f, ctx, res);
381		if (ret)
382			return ret;
383	}
384
385	return 0;
386}
387
388static void
389hws_debug_dump_action_ste_table(struct seq_file *f,
390				struct mlx5hws_action_ste_table *action_tbl)
391{
392	int ste_0_id = mlx5hws_pool_get_base_id(action_tbl->pool);
393	int ste_1_id = mlx5hws_pool_get_base_mirror_id(action_tbl->pool);
394
395	seq_printf(f, "%d,0x%llx,%d,%d,%d,%d\n",
396		   MLX5HWS_DEBUG_RES_TYPE_ACTION_STE_TABLE,
397		   HWS_PTR_TO_ID(action_tbl),
398		   action_tbl->rtc_0_id, ste_0_id,
399		   action_tbl->rtc_1_id, ste_1_id);
400}
401
402static void hws_debug_dump_action_ste_pool(struct seq_file *f,
403					   struct mlx5hws_action_ste_pool *pool)
404{
405	struct mlx5hws_action_ste_table *action_tbl;
406	enum mlx5hws_pool_optimize opt;
407
408	mutex_lock(&pool->lock);
409	for (opt = MLX5HWS_POOL_OPTIMIZE_NONE; opt < MLX5HWS_POOL_OPTIMIZE_MAX;
410	     opt++) {
411		list_for_each_entry(action_tbl, &pool->elems[opt].available,
412				    list_node) {
413			hws_debug_dump_action_ste_table(f, action_tbl);
414		}
415	}
416	mutex_unlock(&pool->lock);
417}
418
419static int hws_debug_dump_context(struct seq_file *f, struct mlx5hws_context *ctx)
420{
421	struct mlx5hws_table *tbl;
422	int ret, i;
423
424	ret = hws_debug_dump_context_info(f, ctx);
425	if (ret)
426		return ret;
427
428	ret = hws_debug_dump_context_send_engine(f, ctx);
429	if (ret)
430		return ret;
431
432	ret = hws_debug_dump_context_stc(f, ctx);
433	if (ret)
434		return ret;
435
436	list_for_each_entry(tbl, &ctx->tbl_list, tbl_list_node) {
437		ret = hws_debug_dump_table(f, tbl);
438		if (ret)
439			return ret;
440	}
441
442	for (i = 0; i < ctx->queues; i++)
443		hws_debug_dump_action_ste_pool(f, &ctx->action_ste_pool[i]);
444
445	return 0;
446}
447
448static int
449hws_debug_dump(struct seq_file *f, struct mlx5hws_context *ctx)
450{
451	int ret;
452
453	if (!f || !ctx)
454		return -EINVAL;
455
456	mutex_lock(&ctx->ctrl_lock);
457	ret = hws_debug_dump_context(f, ctx);
458	mutex_unlock(&ctx->ctrl_lock);
459
460	return ret;
461}
462
463static int hws_dump_show(struct seq_file *file, void *priv)
464{
465	return hws_debug_dump(file, file->private);
466}
467DEFINE_SHOW_ATTRIBUTE(hws_dump);
468
469void mlx5hws_debug_init_dump(struct mlx5hws_context *ctx)
470{
471	struct mlx5_core_dev *dev = ctx->mdev;
472	char file_name[128];
473
474	ctx->debug_info.steering_debugfs =
475		debugfs_create_dir("steering", mlx5_debugfs_get_dev_root(dev));
476	ctx->debug_info.fdb_debugfs =
477		debugfs_create_dir("fdb", ctx->debug_info.steering_debugfs);
478
479	sprintf(file_name, "ctx_%p", ctx);
480	debugfs_create_file(file_name, 0444, ctx->debug_info.fdb_debugfs,
481			    ctx, &hws_dump_fops);
482}
483
484void mlx5hws_debug_uninit_dump(struct mlx5hws_context *ctx)
485{
486	debugfs_remove_recursive(ctx->debug_info.steering_debugfs);
487}
~/ Read-only file preview.