xref: /dpdk/drivers/net/mlx5/hws/mlx5dr_debug.c (revision efb62499c623db13b7396231d0da8d1906d23d9b)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2022 NVIDIA Corporation & Affiliates
3  */
4 
5 #include "mlx5dr_internal.h"
6 
7 const char *mlx5dr_debug_action_type_str[] = {
8 	[MLX5DR_ACTION_TYP_LAST] = "LAST",
9 	[MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2] = "TNL_L2_TO_L2",
10 	[MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2] = "L2_TO_TNL_L2",
11 	[MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2] = "TNL_L3_TO_L2",
12 	[MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3] = "L2_TO_TNL_L3",
13 	[MLX5DR_ACTION_TYP_DROP] = "DROP",
14 	[MLX5DR_ACTION_TYP_TIR] = "TIR",
15 	[MLX5DR_ACTION_TYP_TBL] = "TBL",
16 	[MLX5DR_ACTION_TYP_CTR] = "CTR",
17 	[MLX5DR_ACTION_TYP_TAG] = "TAG",
18 	[MLX5DR_ACTION_TYP_MODIFY_HDR] = "MODIFY_HDR",
19 	[MLX5DR_ACTION_TYP_VPORT] = "VPORT",
20 	[MLX5DR_ACTION_TYP_MISS] = "DEFAULT_MISS",
21 	[MLX5DR_ACTION_TYP_POP_VLAN] = "POP_VLAN",
22 	[MLX5DR_ACTION_TYP_PUSH_VLAN] = "PUSH_VLAN",
23 	[MLX5DR_ACTION_TYP_ASO_METER] = "ASO_METER",
24 	[MLX5DR_ACTION_TYP_ASO_CT] = "ASO_CT",
25 	[MLX5DR_ACTION_TYP_DEST_ROOT] = "DEST_ROOT",
26 	[MLX5DR_ACTION_TYP_DEST_ARRAY] = "DEST_ARRAY",
27 	[MLX5DR_ACTION_TYP_INSERT_HEADER] = "INSERT_HEADER",
28 	[MLX5DR_ACTION_TYP_REMOVE_HEADER] = "REMOVE_HEADER",
29 	[MLX5DR_ACTION_TYP_POP_IPV6_ROUTE_EXT] = "POP_IPV6_ROUTE_EXT",
30 	[MLX5DR_ACTION_TYP_PUSH_IPV6_ROUTE_EXT] = "PUSH_IPV6_ROUTE_EXT",
31 	[MLX5DR_ACTION_TYP_NAT64] = "NAT64",
32 	[MLX5DR_ACTION_TYP_JUMP_TO_MATCHER] = "JUMP_TO_MATCHER",
33 };
34 
35 static_assert(ARRAY_SIZE(mlx5dr_debug_action_type_str) == MLX5DR_ACTION_TYP_MAX,
36 	      "Missing mlx5dr_debug_action_type_str");
37 
38 const char *mlx5dr_debug_action_type_to_str(enum mlx5dr_action_type action_type)
39 {
40 	return mlx5dr_debug_action_type_str[action_type];
41 }
42 
43 static int
44 mlx5dr_debug_dump_matcher_template_definer(FILE *f,
45 					   void *parent_obj,
46 					   struct mlx5dr_definer *definer,
47 					   enum mlx5dr_debug_res_type type)
48 {
49 	int i, ret;
50 
51 	if (!definer)
52 		return 0;
53 
54 	ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,%d,",
55 		      type,
56 		      (uint64_t)(uintptr_t)definer,
57 		      (uint64_t)(uintptr_t)parent_obj,
58 		      definer->obj->id,
59 		      definer->type);
60 	if (ret < 0) {
61 		rte_errno = EINVAL;
62 		return rte_errno;
63 	}
64 
65 	for (i = 0; i < DW_SELECTORS; i++) {
66 		ret = fprintf(f, "0x%x%s", definer->dw_selector[i],
67 			      (i == DW_SELECTORS - 1) ? "," : "-");
68 		if (ret < 0) {
69 			rte_errno = EINVAL;
70 			return rte_errno;
71 		}
72 	}
73 
74 	for (i = 0; i < BYTE_SELECTORS; i++) {
75 		ret = fprintf(f, "0x%x%s", definer->byte_selector[i],
76 			      (i == BYTE_SELECTORS - 1) ? "," : "-");
77 		if (ret < 0) {
78 			rte_errno = EINVAL;
79 			return rte_errno;
80 		}
81 	}
82 
83 	for (i = 0; i < MLX5DR_JUMBO_TAG_SZ; i++) {
84 		ret = fprintf(f, "%02x", definer->mask.jumbo[i]);
85 		if (ret < 0) {
86 			rte_errno = EINVAL;
87 			return rte_errno;
88 		}
89 	}
90 
91 	ret = fprintf(f, "\n");
92 	if (ret < 0) {
93 		rte_errno = EINVAL;
94 		return rte_errno;
95 	}
96 
97 	return 0;
98 }
99 
100 static int
101 mlx5dr_debug_dump_matcher_match_template(FILE *f, struct mlx5dr_matcher *matcher)
102 {
103 	bool is_root = matcher->tbl->level == MLX5DR_ROOT_LEVEL;
104 	bool is_compare = mlx5dr_matcher_is_compare(matcher);
105 	enum mlx5dr_debug_res_type type;
106 	int i, ret;
107 
108 	for (i = 0; i < matcher->num_of_mt; i++) {
109 		struct mlx5dr_match_template *mt = &matcher->mt[i];
110 
111 		ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,%d,%d\n",
112 			      MLX5DR_DEBUG_RES_TYPE_MATCHER_MATCH_TEMPLATE,
113 			      (uint64_t)(uintptr_t)mt,
114 			      (uint64_t)(uintptr_t)matcher,
115 			      is_root ? 0 : mt->fc_sz,
116 			      mt->flags,
117 			      is_root ? 0 : mt->fcr_sz);
118 		if (ret < 0) {
119 			rte_errno = EINVAL;
120 			return rte_errno;
121 		}
122 
123 		type = is_compare ? MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_COMPARE_MATCH_DEFINER :
124 				    MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_MATCH_DEFINER;
125 		ret = mlx5dr_debug_dump_matcher_template_definer(f, mt, mt->definer, type);
126 		if (ret)
127 			return ret;
128 
129 		type = MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_RANGE_DEFINER;
130 		ret = mlx5dr_debug_dump_matcher_template_definer(f, mt, mt->range_definer, type);
131 		if (ret)
132 			return ret;
133 	}
134 
135 	type = MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_HASH_DEFINER;
136 	ret = mlx5dr_debug_dump_matcher_template_definer(f, matcher, matcher->hash_definer, type);
137 	if (ret)
138 		return ret;
139 
140 	return 0;
141 }
142 
143 static int
144 mlx5dr_debug_dump_matcher_action_template(FILE *f, struct mlx5dr_matcher *matcher)
145 {
146 	bool is_root = matcher->tbl->level == MLX5DR_ROOT_LEVEL;
147 	enum mlx5dr_action_type action_type;
148 	int i, j, ret;
149 
150 	for (i = 0; i < matcher->num_of_at; i++) {
151 		struct mlx5dr_action_template *at = &matcher->at[i];
152 
153 		ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,%d,%d",
154 			      MLX5DR_DEBUG_RES_TYPE_MATCHER_ACTION_TEMPLATE,
155 			      (uint64_t)(uintptr_t)at,
156 			      (uint64_t)(uintptr_t)matcher,
157 			      at->only_term,
158 			      is_root ? 0 : at->num_of_action_stes,
159 			      at->num_actions);
160 		if (ret < 0) {
161 			rte_errno = EINVAL;
162 			return rte_errno;
163 		}
164 
165 		for (j = 0; j < at->num_actions; j++) {
166 			action_type = at->action_type_arr[j];
167 			ret = fprintf(f, ",%s", mlx5dr_debug_action_type_to_str(action_type));
168 			if (ret < 0) {
169 				rte_errno = EINVAL;
170 				return rte_errno;
171 			}
172 		}
173 
174 		fprintf(f, "\n");
175 	}
176 
177 	return 0;
178 }
179 
180 static int
181 mlx5dr_debug_dump_matcher_attr(FILE *f, struct mlx5dr_matcher *matcher)
182 {
183 	struct mlx5dr_matcher_attr *attr = &matcher->attr;
184 	int ret;
185 
186 	ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
187 		      MLX5DR_DEBUG_RES_TYPE_MATCHER_ATTR,
188 		      (uint64_t)(uintptr_t)matcher,
189 		      attr->priority,
190 		      attr->mode,
191 		      attr->table.sz_row_log,
192 		      attr->table.sz_col_log,
193 		      attr->optimize_using_rule_idx,
194 		      attr->optimize_flow_src,
195 		      attr->insert_mode,
196 		      attr->distribute_mode,
197 		      attr->match_mode,
198 		      attr->isolated);
199 	if (ret < 0) {
200 		rte_errno = EINVAL;
201 		return rte_errno;
202 	}
203 
204 	return 0;
205 }
206 
207 static int mlx5dr_debug_dump_matcher(FILE *f, struct mlx5dr_matcher *matcher)
208 {
209 	bool is_shared = mlx5dr_context_shared_gvmi_used(matcher->tbl->ctx);
210 	bool is_root = matcher->tbl->level == MLX5DR_ROOT_LEVEL;
211 	enum mlx5dr_table_type tbl_type = matcher->tbl->type;
212 	struct mlx5dr_matcher_resize_data *resize_data;
213 	struct mlx5dr_cmd_ft_query_attr ft_attr = {0};
214 	struct mlx5dr_devx_obj *ste_0, *ste_1 = NULL;
215 	struct mlx5dr_pool_chunk *ste;
216 	struct mlx5dr_pool *ste_pool;
217 	uint64_t icm_addr_0 = 0;
218 	uint64_t icm_addr_1 = 0;
219 	int ret;
220 
221 	ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,%d,0x%" PRIx64,
222 		      MLX5DR_DEBUG_RES_TYPE_MATCHER,
223 		      (uint64_t)(uintptr_t)matcher,
224 		      (uint64_t)(uintptr_t)matcher->tbl,
225 		      matcher->num_of_mt,
226 		      is_root ? 0 : matcher->end_ft->id,
227 		      matcher->col_matcher ? (uint64_t)(uintptr_t)matcher->col_matcher : 0);
228 	if (ret < 0)
229 		goto out_err;
230 
231 	ste = &matcher->match_ste.ste;
232 	ste_pool = matcher->match_ste.pool;
233 	if (ste_pool) {
234 		ste_0 = mlx5dr_pool_chunk_get_base_devx_obj(ste_pool, ste);
235 		if (tbl_type == MLX5DR_TABLE_TYPE_FDB)
236 			ste_1 = mlx5dr_pool_chunk_get_base_devx_obj_mirror(ste_pool, ste);
237 	} else {
238 		ste_0 = NULL;
239 		ste_1 = NULL;
240 	}
241 
242 	ret = fprintf(f, ",%d,%d,%d,%d",
243 		      matcher->match_ste.rtc_0 ? matcher->match_ste.rtc_0->id : 0,
244 		      ste_0 ? (int)ste_0->id : -1,
245 		      matcher->match_ste.rtc_1 ? matcher->match_ste.rtc_1->id : 0,
246 		      ste_1 ? (int)ste_1->id : -1);
247 	if (ret < 0)
248 		goto out_err;
249 
250 	ste = &matcher->action_ste.ste;
251 	ste_pool = matcher->action_ste.pool;
252 	if (ste_pool) {
253 		ste_0 = mlx5dr_pool_chunk_get_base_devx_obj(ste_pool, ste);
254 		if (tbl_type == MLX5DR_TABLE_TYPE_FDB)
255 			ste_1 = mlx5dr_pool_chunk_get_base_devx_obj_mirror(ste_pool, ste);
256 	} else {
257 		ste_0 = NULL;
258 		ste_1 = NULL;
259 	}
260 
261 	if (!is_root) {
262 		ft_attr.type = matcher->tbl->fw_ft_type;
263 		ret = mlx5dr_cmd_flow_table_query(matcher->end_ft,
264 						  &ft_attr,
265 						  &icm_addr_0,
266 						  &icm_addr_1);
267 		if (ret)
268 			return ret;
269 	}
270 
271 	ret = fprintf(f, ",%d,%d,%d,%d,%d,0x%" PRIx64 ",0x%" PRIx64 "\n",
272 		      matcher->action_ste.rtc_0 ? matcher->action_ste.rtc_0->id : 0,
273 		      ste_0 ? (int)ste_0->id : -1,
274 		      matcher->action_ste.rtc_1 ? matcher->action_ste.rtc_1->id : 0,
275 		      ste_1 ? (int)ste_1->id : -1,
276 		      is_shared && !is_root ?
277 		      matcher->match_ste.aliased_rtc_0->id : 0,
278 		      mlx5dr_debug_icm_to_idx(icm_addr_0),
279 		      mlx5dr_debug_icm_to_idx(icm_addr_1));
280 	if (ret < 0)
281 		goto out_err;
282 
283 	ret = mlx5dr_debug_dump_matcher_attr(f, matcher);
284 	if (ret)
285 		return ret;
286 
287 	ret = mlx5dr_debug_dump_matcher_match_template(f, matcher);
288 	if (ret)
289 		return ret;
290 
291 	ret = mlx5dr_debug_dump_matcher_action_template(f, matcher);
292 	if (ret)
293 		return ret;
294 
295 	LIST_FOREACH(resize_data, &matcher->resize_data, next) {
296 		ste = &resize_data->ste;
297 		ste_pool = resize_data->action_ste_pool;
298 		if (ste_pool) {
299 			ste_0 = mlx5dr_pool_chunk_get_base_devx_obj(ste_pool, ste);
300 			if (tbl_type == MLX5DR_TABLE_TYPE_FDB)
301 				ste_1 = mlx5dr_pool_chunk_get_base_devx_obj_mirror(ste_pool, ste);
302 		} else {
303 			ste_0 = NULL;
304 			ste_1 = NULL;
305 		}
306 		ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,%d,%d\n",
307 			      MLX5DR_DEBUG_RES_TYPE_MATCHER_RESIZABLE_ACTION_ARRAY,
308 			      (uint64_t)(uintptr_t)matcher,
309 			      resize_data->action_ste_rtc_0 ? resize_data->action_ste_rtc_0->id : 0,
310 			      ste_0 ? (int)ste_0->id : -1,
311 			      resize_data->action_ste_rtc_1 ? resize_data->action_ste_rtc_1->id : 0,
312 			      ste_1 ? (int)ste_1->id : -1);
313 		if (ret < 0)
314 			return ret;
315 	}
316 
317 	return 0;
318 
319 out_err:
320 	rte_errno = EINVAL;
321 	return rte_errno;
322 }
323 
324 static int mlx5dr_debug_dump_table(FILE *f, struct mlx5dr_table *tbl)
325 {
326 	bool is_shared = mlx5dr_context_shared_gvmi_used(tbl->ctx);
327 	bool is_root = tbl->level == MLX5DR_ROOT_LEVEL;
328 	struct mlx5dr_cmd_ft_query_attr ft_attr = {0};
329 	struct mlx5dr_matcher *matcher;
330 	uint64_t local_icm_addr_0 = 0;
331 	uint64_t local_icm_addr_1 = 0;
332 	uint64_t icm_addr_0 = 0;
333 	uint64_t icm_addr_1 = 0;
334 	int ret;
335 
336 	ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,%d,%d,%d,%d",
337 		      MLX5DR_DEBUG_RES_TYPE_TABLE,
338 		      (uint64_t)(uintptr_t)tbl,
339 		      (uint64_t)(uintptr_t)tbl->ctx,
340 		      is_root ? 0 : tbl->ft->id,
341 		      tbl->type,
342 		      is_root ? 0 : tbl->fw_ft_type,
343 		      tbl->level,
344 		      is_shared && !is_root ? tbl->local_ft->id : 0);
345 	if (ret < 0)
346 		goto out_err;
347 
348 	if (!is_root) {
349 		ft_attr.type = tbl->fw_ft_type;
350 		ret = mlx5dr_cmd_flow_table_query(tbl->ft,
351 						  &ft_attr,
352 						  &icm_addr_0,
353 						  &icm_addr_1);
354 		if (ret)
355 			return ret;
356 
357 		if (is_shared) {
358 			ft_attr.type = tbl->fw_ft_type;
359 			ret = mlx5dr_cmd_flow_table_query(tbl->local_ft,
360 							  &ft_attr,
361 							  &local_icm_addr_0,
362 							  &local_icm_addr_1);
363 			if (ret)
364 				return ret;
365 		}
366 	}
367 
368 	ret = fprintf(f, ",0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 "\n",
369 		      mlx5dr_debug_icm_to_idx(icm_addr_0),
370 		      mlx5dr_debug_icm_to_idx(icm_addr_1),
371 		      mlx5dr_debug_icm_to_idx(local_icm_addr_0),
372 		      mlx5dr_debug_icm_to_idx(local_icm_addr_1),
373 		      (uint64_t)(uintptr_t)tbl->default_miss.miss_tbl);
374 	if (ret < 0)
375 		goto out_err;
376 
377 	LIST_FOREACH(matcher, &tbl->head, next) {
378 		ret = mlx5dr_debug_dump_matcher(f, matcher);
379 		if (ret)
380 			return ret;
381 	}
382 
383 	LIST_FOREACH(matcher, &tbl->isolated_matchers, next) {
384 		ret = mlx5dr_debug_dump_matcher(f, matcher);
385 		if (ret)
386 			return ret;
387 	}
388 
389 	return 0;
390 
391 out_err:
392 	rte_errno = EINVAL;
393 	return rte_errno;
394 }
395 
396 static int
397 mlx5dr_debug_dump_context_send_engine(FILE *f, struct mlx5dr_context *ctx)
398 {
399 	struct mlx5dr_send_engine *send_queue;
400 	int ret, i, j;
401 
402 	for (i = 0; i < (int)ctx->queues; i++) {
403 		send_queue = &ctx->send_queue[i];
404 		ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
405 			      MLX5DR_DEBUG_RES_TYPE_CONTEXT_SEND_ENGINE,
406 			      (uint64_t)(uintptr_t)ctx,
407 			      i,
408 			      send_queue->used_entries,
409 			      send_queue->th_entries,
410 			      send_queue->rings,
411 			      send_queue->num_entries,
412 			      send_queue->err,
413 			      send_queue->completed.ci,
414 			      send_queue->completed.pi,
415 			      send_queue->completed.mask);
416 		if (ret < 0) {
417 			rte_errno = EINVAL;
418 			return rte_errno;
419 		}
420 
421 		for (j = 0; j < MLX5DR_NUM_SEND_RINGS; j++) {
422 			struct mlx5dr_send_ring *send_ring = &send_queue->send_ring[j];
423 			struct mlx5dr_send_ring_cq *cq = &send_ring->send_cq;
424 			struct mlx5dr_send_ring_sq *sq = &send_ring->send_sq;
425 
426 			ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
427 				      MLX5DR_DEBUG_RES_TYPE_CONTEXT_SEND_RING,
428 				      (uint64_t)(uintptr_t)ctx,
429 				      j,
430 				      i,
431 				      cq->cqn,
432 				      cq->cons_index,
433 				      cq->ncqe_mask,
434 				      cq->buf_sz,
435 				      cq->ncqe,
436 				      cq->cqe_log_sz,
437 				      cq->poll_wqe,
438 				      cq->cqe_sz,
439 				      sq->sqn,
440 				      sq->obj->id,
441 				      sq->cur_post,
442 				      sq->buf_mask);
443 			if (ret < 0) {
444 				rte_errno = EINVAL;
445 				return rte_errno;
446 			}
447 		}
448 	}
449 
450 	return 0;
451 }
452 
453 static int mlx5dr_debug_dump_context_caps(FILE *f, struct mlx5dr_context *ctx)
454 {
455 	struct mlx5dr_cmd_query_caps *caps = ctx->caps;
456 	int ret;
457 
458 	ret = fprintf(f, "%d,0x%" PRIx64 ",%s,%d,%d,%d,%d,",
459 		      MLX5DR_DEBUG_RES_TYPE_CONTEXT_CAPS,
460 		      (uint64_t)(uintptr_t)ctx,
461 		      caps->fw_ver,
462 		      caps->wqe_based_update,
463 		      caps->ste_format,
464 		      caps->ste_alloc_log_max,
465 		      caps->log_header_modify_argument_max_alloc);
466 	if (ret < 0) {
467 		rte_errno = EINVAL;
468 		return rte_errno;
469 	}
470 
471 	ret = fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
472 		      caps->flex_protocols,
473 		      caps->rtc_reparse_mode,
474 		      caps->rtc_index_mode,
475 		      caps->ste_alloc_log_gran,
476 		      caps->stc_alloc_log_max,
477 		      caps->stc_alloc_log_gran,
478 		      caps->rtc_log_depth_max,
479 		      caps->format_select_gtpu_dw_0,
480 		      caps->format_select_gtpu_dw_1,
481 		      caps->format_select_gtpu_dw_2,
482 		      caps->format_select_gtpu_ext_dw_0,
483 		      caps->nic_ft.max_level,
484 		      caps->nic_ft.reparse,
485 		      caps->fdb_ft.max_level,
486 		      caps->fdb_ft.reparse,
487 		      caps->log_header_modify_argument_granularity);
488 	if (ret < 0) {
489 		rte_errno = EINVAL;
490 		return rte_errno;
491 	}
492 
493 	return 0;
494 }
495 
496 static int mlx5dr_debug_dump_context_attr(FILE *f, struct mlx5dr_context *ctx)
497 {
498 	int ret;
499 
500 	ret = fprintf(f, "%u,0x%" PRIx64 ",%d,%zu,%d,%s,%d,%d\n",
501 		      MLX5DR_DEBUG_RES_TYPE_CONTEXT_ATTR,
502 		      (uint64_t)(uintptr_t)ctx,
503 		      ctx->pd_num,
504 		      ctx->queues,
505 		      ctx->send_queue->num_entries,
506 		      mlx5dr_context_shared_gvmi_used(ctx) ?
507 		      mlx5_glue->get_device_name(ctx->ibv_ctx->device) : "None",
508 		      ctx->caps->vhca_id,
509 		      mlx5dr_context_shared_gvmi_used(ctx) ?
510 		      ctx->caps->shared_vhca_id : 0xffff);
511 	if (ret < 0) {
512 		rte_errno = EINVAL;
513 		return rte_errno;
514 	}
515 
516 	return 0;
517 }
518 
519 static int mlx5dr_debug_dump_context_info(FILE *f, struct mlx5dr_context *ctx)
520 {
521 	int ret;
522 
523 	ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%s,%s\n",
524 		      MLX5DR_DEBUG_RES_TYPE_CONTEXT,
525 		      (uint64_t)(uintptr_t)ctx,
526 		      ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT,
527 		      mlx5_glue->get_device_name(mlx5dr_context_get_local_ibv(ctx)->device),
528 		      DEBUG_VERSION);
529 	if (ret < 0) {
530 		rte_errno = EINVAL;
531 		return rte_errno;
532 	}
533 
534 	ret = mlx5dr_debug_dump_context_attr(f, ctx);
535 	if (ret)
536 		return ret;
537 
538 	ret = mlx5dr_debug_dump_context_caps(f, ctx);
539 	if (ret)
540 		return ret;
541 
542 	return 0;
543 }
544 
545 static int
546 mlx5dr_debug_dump_context_stc_resource(FILE *f,
547 				       struct mlx5dr_context *ctx,
548 				       uint32_t tbl_type,
549 				       struct mlx5dr_pool_resource *resource)
550 {
551 	int ret;
552 
553 	ret = fprintf(f, "%d,0x%" PRIx64 ",%u,%u\n",
554 		      MLX5DR_DEBUG_RES_TYPE_CONTEXT_STC,
555 		      (uint64_t)(uintptr_t)ctx,
556 		      tbl_type,
557 		      resource->base_id);
558 	if (ret < 0) {
559 		rte_errno = EINVAL;
560 		return rte_errno;
561 	}
562 
563 	return 0;
564 }
565 
566 static int mlx5dr_debug_dump_context_stc(FILE *f, struct mlx5dr_context *ctx)
567 {
568 	struct mlx5dr_pool *stc_pool;
569 	int ret;
570 	int i;
571 
572 	for (i = 0; i < MLX5DR_TABLE_TYPE_MAX; i++) {
573 		stc_pool = ctx->stc_pool[i];
574 
575 		if (!stc_pool)
576 			continue;
577 
578 		if (stc_pool->resource[0] != NULL) {
579 			ret = mlx5dr_debug_dump_context_stc_resource(f, ctx, i,
580 								     stc_pool->resource[0]);
581 			if (ret)
582 				return ret;
583 		}
584 
585 		if (i == MLX5DR_TABLE_TYPE_FDB && stc_pool->mirror_resource[0] != NULL) {
586 			ret = mlx5dr_debug_dump_context_stc_resource(f, ctx, i,
587 								     stc_pool->mirror_resource[0]);
588 			if (ret)
589 				return ret;
590 		}
591 	}
592 
593 	return 0;
594 }
595 
596 static int mlx5dr_debug_dump_context(FILE *f, struct mlx5dr_context *ctx)
597 {
598 	struct mlx5dr_table *tbl;
599 	int ret;
600 
601 	ret = mlx5dr_debug_dump_context_info(f, ctx);
602 	if (ret)
603 		return ret;
604 
605 	ret = mlx5dr_debug_dump_context_send_engine(f, ctx);
606 	if (ret)
607 		return ret;
608 
609 	ret = mlx5dr_debug_dump_context_stc(f, ctx);
610 	if (ret)
611 		return ret;
612 
613 	LIST_FOREACH(tbl, &ctx->head, next) {
614 		ret = mlx5dr_debug_dump_table(f, tbl);
615 		if (ret)
616 			return ret;
617 	}
618 
619 	return 0;
620 }
621 
622 int mlx5dr_debug_dump(struct mlx5dr_context *ctx, FILE *f)
623 {
624 	int ret;
625 
626 	if (!f || !ctx) {
627 		rte_errno = EINVAL;
628 		return -rte_errno;
629 	}
630 
631 	pthread_spin_lock(&ctx->ctrl_lock);
632 	ret = mlx5dr_debug_dump_context(f, ctx);
633 	pthread_spin_unlock(&ctx->ctrl_lock);
634 
635 	return -ret;
636 }
637