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
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.ste;
152 ste_pool = matcher->action_ste.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.rtc_0_id, (int)ste_0_id,
175 matcher->action_ste.rtc_1_id, (int)ste_1_id,
176 0,
177 mlx5hws_debug_icm_to_idx(icm_addr_0),
178 mlx5hws_debug_icm_to_idx(icm_addr_1));
179
180 ret = hws_debug_dump_matcher_attr(f, matcher);
181 if (ret)
182 return ret;
183
184 ret = hws_debug_dump_matcher_match_template(f, matcher);
185 if (ret)
186 return ret;
187
188 ret = hws_debug_dump_matcher_action_template(f, matcher);
189 if (ret)
190 return ret;
191
192 return 0;
193 }
194
hws_debug_dump_table(struct seq_file * f,struct mlx5hws_table * tbl)195 static int hws_debug_dump_table(struct seq_file *f, struct mlx5hws_table *tbl)
196 {
197 struct mlx5hws_cmd_ft_query_attr ft_attr = {0};
198 struct mlx5hws_matcher *matcher;
199 u64 local_icm_addr_0 = 0;
200 u64 local_icm_addr_1 = 0;
201 u64 icm_addr_0 = 0;
202 u64 icm_addr_1 = 0;
203 int ret;
204
205 seq_printf(f, "%d,0x%llx,0x%llx,%d,%d,%d,%d,%d",
206 MLX5HWS_DEBUG_RES_TYPE_TABLE,
207 HWS_PTR_TO_ID(tbl),
208 HWS_PTR_TO_ID(tbl->ctx),
209 tbl->ft_id,
210 MLX5HWS_TABLE_TYPE_BASE + tbl->type,
211 tbl->fw_ft_type,
212 tbl->level,
213 0);
214
215 ft_attr.type = tbl->fw_ft_type;
216 ret = mlx5hws_cmd_flow_table_query(tbl->ctx->mdev,
217 tbl->ft_id,
218 &ft_attr,
219 &icm_addr_0,
220 &icm_addr_1);
221 if (ret)
222 return ret;
223
224 seq_printf(f, ",0x%llx,0x%llx,0x%llx,0x%llx,0x%llx\n",
225 mlx5hws_debug_icm_to_idx(icm_addr_0),
226 mlx5hws_debug_icm_to_idx(icm_addr_1),
227 mlx5hws_debug_icm_to_idx(local_icm_addr_0),
228 mlx5hws_debug_icm_to_idx(local_icm_addr_1),
229 HWS_PTR_TO_ID(tbl->default_miss.miss_tbl));
230
231 list_for_each_entry(matcher, &tbl->matchers_list, list_node) {
232 ret = hws_debug_dump_matcher(f, matcher);
233 if (ret)
234 return ret;
235 }
236
237 return 0;
238 }
239
240 static int
hws_debug_dump_context_send_engine(struct seq_file * f,struct mlx5hws_context * ctx)241 hws_debug_dump_context_send_engine(struct seq_file *f, struct mlx5hws_context *ctx)
242 {
243 struct mlx5hws_send_engine *send_queue;
244 struct mlx5hws_send_ring *send_ring;
245 struct mlx5hws_send_ring_cq *cq;
246 struct mlx5hws_send_ring_sq *sq;
247 int i;
248
249 for (i = 0; i < (int)ctx->queues; i++) {
250 send_queue = &ctx->send_queue[i];
251 seq_printf(f, "%d,0x%llx,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
252 MLX5HWS_DEBUG_RES_TYPE_CONTEXT_SEND_ENGINE,
253 HWS_PTR_TO_ID(ctx),
254 i,
255 send_queue->used_entries,
256 send_queue->num_entries,
257 1, /* one send ring per queue */
258 send_queue->num_entries,
259 send_queue->err,
260 send_queue->completed.ci,
261 send_queue->completed.pi,
262 send_queue->completed.mask);
263
264 send_ring = &send_queue->send_ring;
265 cq = &send_ring->send_cq;
266 sq = &send_ring->send_sq;
267
268 seq_printf(f, "%d,0x%llx,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
269 MLX5HWS_DEBUG_RES_TYPE_CONTEXT_SEND_RING,
270 HWS_PTR_TO_ID(ctx),
271 0, /* one send ring per send queue */
272 i,
273 cq->mcq.cqn,
274 0,
275 0,
276 0,
277 0,
278 0,
279 0,
280 cq->mcq.cqe_sz,
281 sq->sqn,
282 0,
283 0,
284 0);
285 }
286
287 return 0;
288 }
289
hws_debug_dump_context_caps(struct seq_file * f,struct mlx5hws_context * ctx)290 static int hws_debug_dump_context_caps(struct seq_file *f, struct mlx5hws_context *ctx)
291 {
292 struct mlx5hws_cmd_query_caps *caps = ctx->caps;
293
294 seq_printf(f, "%d,0x%llx,%s,%d,%d,%d,%d,",
295 MLX5HWS_DEBUG_RES_TYPE_CONTEXT_CAPS,
296 HWS_PTR_TO_ID(ctx),
297 caps->fw_ver,
298 caps->wqe_based_update,
299 caps->ste_format,
300 caps->ste_alloc_log_max,
301 caps->log_header_modify_argument_max_alloc);
302
303 seq_printf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s\n",
304 caps->flex_protocols,
305 caps->rtc_reparse_mode,
306 caps->rtc_index_mode,
307 caps->ste_alloc_log_gran,
308 caps->stc_alloc_log_max,
309 caps->stc_alloc_log_gran,
310 caps->rtc_log_depth_max,
311 caps->format_select_gtpu_dw_0,
312 caps->format_select_gtpu_dw_1,
313 caps->format_select_gtpu_dw_2,
314 caps->format_select_gtpu_ext_dw_0,
315 caps->nic_ft.max_level,
316 caps->nic_ft.reparse,
317 caps->fdb_ft.max_level,
318 caps->fdb_ft.reparse,
319 caps->log_header_modify_argument_granularity,
320 caps->linear_match_definer,
321 "regc_3");
322
323 return 0;
324 }
325
hws_debug_dump_context_attr(struct seq_file * f,struct mlx5hws_context * ctx)326 static int hws_debug_dump_context_attr(struct seq_file *f, struct mlx5hws_context *ctx)
327 {
328 seq_printf(f, "%u,0x%llx,%d,%zu,%d,%s,%d,%d\n",
329 MLX5HWS_DEBUG_RES_TYPE_CONTEXT_ATTR,
330 HWS_PTR_TO_ID(ctx),
331 ctx->pd_num,
332 ctx->queues,
333 ctx->send_queue->num_entries,
334 "None", /* no shared gvmi */
335 ctx->caps->vhca_id,
336 0xffff); /* no shared gvmi */
337
338 return 0;
339 }
340
hws_debug_dump_context_info(struct seq_file * f,struct mlx5hws_context * ctx)341 static int hws_debug_dump_context_info(struct seq_file *f, struct mlx5hws_context *ctx)
342 {
343 struct mlx5_core_dev *dev = ctx->mdev;
344 int ret;
345
346 seq_printf(f, "%d,0x%llx,%d,%s,%s.KERNEL_%u_%u_%u\n",
347 MLX5HWS_DEBUG_RES_TYPE_CONTEXT,
348 HWS_PTR_TO_ID(ctx),
349 ctx->flags & MLX5HWS_CONTEXT_FLAG_HWS_SUPPORT,
350 pci_name(dev->pdev),
351 HWS_DEBUG_FORMAT_VERSION,
352 LINUX_VERSION_MAJOR,
353 LINUX_VERSION_PATCHLEVEL,
354 LINUX_VERSION_SUBLEVEL);
355
356 ret = hws_debug_dump_context_attr(f, ctx);
357 if (ret)
358 return ret;
359
360 ret = hws_debug_dump_context_caps(f, ctx);
361 if (ret)
362 return ret;
363
364 return 0;
365 }
366
hws_debug_dump_context_stc_resource(struct seq_file * f,struct mlx5hws_context * ctx,struct mlx5hws_pool_resource * resource)367 static int hws_debug_dump_context_stc_resource(struct seq_file *f,
368 struct mlx5hws_context *ctx,
369 struct mlx5hws_pool_resource *resource)
370 {
371 u32 tbl_type = MLX5HWS_TABLE_TYPE_BASE + MLX5HWS_TABLE_TYPE_FDB;
372
373 seq_printf(f, "%d,0x%llx,%u,%u\n",
374 MLX5HWS_DEBUG_RES_TYPE_CONTEXT_STC,
375 HWS_PTR_TO_ID(ctx),
376 tbl_type,
377 resource->base_id);
378
379 return 0;
380 }
381
hws_debug_dump_context_stc(struct seq_file * f,struct mlx5hws_context * ctx)382 static int hws_debug_dump_context_stc(struct seq_file *f, struct mlx5hws_context *ctx)
383 {
384 struct mlx5hws_pool *stc_pool = ctx->stc_pool;
385 int ret;
386
387 if (!stc_pool)
388 return 0;
389
390 if (stc_pool->resource[0]) {
391 ret = hws_debug_dump_context_stc_resource(f, ctx, stc_pool->resource[0]);
392 if (ret)
393 return ret;
394 }
395
396 if (stc_pool->mirror_resource[0]) {
397 ret = hws_debug_dump_context_stc_resource(f, ctx, stc_pool->mirror_resource[0]);
398 if (ret)
399 return ret;
400 }
401
402 return 0;
403 }
404
hws_debug_dump_context(struct seq_file * f,struct mlx5hws_context * ctx)405 static int hws_debug_dump_context(struct seq_file *f, struct mlx5hws_context *ctx)
406 {
407 struct mlx5hws_table *tbl;
408 int ret;
409
410 ret = hws_debug_dump_context_info(f, ctx);
411 if (ret)
412 return ret;
413
414 ret = hws_debug_dump_context_send_engine(f, ctx);
415 if (ret)
416 return ret;
417
418 ret = hws_debug_dump_context_stc(f, ctx);
419 if (ret)
420 return ret;
421
422 list_for_each_entry(tbl, &ctx->tbl_list, tbl_list_node) {
423 ret = hws_debug_dump_table(f, tbl);
424 if (ret)
425 return ret;
426 }
427
428 return 0;
429 }
430
431 static int
hws_debug_dump(struct seq_file * f,struct mlx5hws_context * ctx)432 hws_debug_dump(struct seq_file *f, struct mlx5hws_context *ctx)
433 {
434 int ret;
435
436 if (!f || !ctx)
437 return -EINVAL;
438
439 mutex_lock(&ctx->ctrl_lock);
440 ret = hws_debug_dump_context(f, ctx);
441 mutex_unlock(&ctx->ctrl_lock);
442
443 return ret;
444 }
445
hws_dump_show(struct seq_file * file,void * priv)446 static int hws_dump_show(struct seq_file *file, void *priv)
447 {
448 return hws_debug_dump(file, file->private);
449 }
450 DEFINE_SHOW_ATTRIBUTE(hws_dump);
451
mlx5hws_debug_init_dump(struct mlx5hws_context * ctx)452 void mlx5hws_debug_init_dump(struct mlx5hws_context *ctx)
453 {
454 struct mlx5_core_dev *dev = ctx->mdev;
455 char file_name[128];
456
457 ctx->debug_info.steering_debugfs =
458 debugfs_create_dir("steering", mlx5_debugfs_get_dev_root(dev));
459 ctx->debug_info.fdb_debugfs =
460 debugfs_create_dir("fdb", ctx->debug_info.steering_debugfs);
461
462 sprintf(file_name, "ctx_%p", ctx);
463 debugfs_create_file(file_name, 0444, ctx->debug_info.fdb_debugfs,
464 ctx, &hws_dump_fops);
465 }
466
mlx5hws_debug_uninit_dump(struct mlx5hws_context * ctx)467 void mlx5hws_debug_uninit_dump(struct mlx5hws_context *ctx)
468 {
469 debugfs_remove_recursive(ctx->debug_info.steering_debugfs);
470 }
471