1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 
4 #include <linux/debugfs.h>
5 #include <linux/kernel.h>
6 #include <linux/seq_file.h>
7 #include <linux/version.h>
8 #include "dr_types.h"
9 
10 #define DR_DBG_PTR_TO_ID(p) ((u64)(uintptr_t)(p) & 0xFFFFFFFFULL)
11 
12 enum dr_dump_rec_type {
13 	DR_DUMP_REC_TYPE_DOMAIN = 3000,
14 	DR_DUMP_REC_TYPE_DOMAIN_INFO_FLEX_PARSER = 3001,
15 	DR_DUMP_REC_TYPE_DOMAIN_INFO_DEV_ATTR = 3002,
16 	DR_DUMP_REC_TYPE_DOMAIN_INFO_VPORT = 3003,
17 	DR_DUMP_REC_TYPE_DOMAIN_INFO_CAPS = 3004,
18 	DR_DUMP_REC_TYPE_DOMAIN_SEND_RING = 3005,
19 
20 	DR_DUMP_REC_TYPE_TABLE = 3100,
21 	DR_DUMP_REC_TYPE_TABLE_RX = 3101,
22 	DR_DUMP_REC_TYPE_TABLE_TX = 3102,
23 
24 	DR_DUMP_REC_TYPE_MATCHER = 3200,
25 	DR_DUMP_REC_TYPE_MATCHER_MASK_DEPRECATED = 3201,
26 	DR_DUMP_REC_TYPE_MATCHER_RX = 3202,
27 	DR_DUMP_REC_TYPE_MATCHER_TX = 3203,
28 	DR_DUMP_REC_TYPE_MATCHER_BUILDER = 3204,
29 	DR_DUMP_REC_TYPE_MATCHER_MASK = 3205,
30 
31 	DR_DUMP_REC_TYPE_RULE = 3300,
32 	DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V0 = 3301,
33 	DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V0 = 3302,
34 	DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V1 = 3303,
35 	DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V1 = 3304,
36 
37 	DR_DUMP_REC_TYPE_ACTION_ENCAP_L2 = 3400,
38 	DR_DUMP_REC_TYPE_ACTION_ENCAP_L3 = 3401,
39 	DR_DUMP_REC_TYPE_ACTION_MODIFY_HDR = 3402,
40 	DR_DUMP_REC_TYPE_ACTION_DROP = 3403,
41 	DR_DUMP_REC_TYPE_ACTION_QP = 3404,
42 	DR_DUMP_REC_TYPE_ACTION_FT = 3405,
43 	DR_DUMP_REC_TYPE_ACTION_CTR = 3406,
44 	DR_DUMP_REC_TYPE_ACTION_TAG = 3407,
45 	DR_DUMP_REC_TYPE_ACTION_VPORT = 3408,
46 	DR_DUMP_REC_TYPE_ACTION_DECAP_L2 = 3409,
47 	DR_DUMP_REC_TYPE_ACTION_DECAP_L3 = 3410,
48 	DR_DUMP_REC_TYPE_ACTION_DEVX_TIR = 3411,
49 	DR_DUMP_REC_TYPE_ACTION_PUSH_VLAN = 3412,
50 	DR_DUMP_REC_TYPE_ACTION_POP_VLAN = 3413,
51 	DR_DUMP_REC_TYPE_ACTION_SAMPLER = 3415,
52 	DR_DUMP_REC_TYPE_ACTION_INSERT_HDR = 3420,
53 	DR_DUMP_REC_TYPE_ACTION_REMOVE_HDR = 3421,
54 	DR_DUMP_REC_TYPE_ACTION_MATCH_RANGE = 3425,
55 };
56 
57 static struct mlx5dr_dbg_dump_buff *
58 mlx5dr_dbg_dump_data_init_new_buff(struct mlx5dr_dbg_dump_data *dump_data)
59 {
60 	struct mlx5dr_dbg_dump_buff *new_buff;
61 
62 	new_buff = kzalloc(sizeof(*new_buff), GFP_KERNEL);
63 	if (!new_buff)
64 		return NULL;
65 
66 	new_buff->buff = kvzalloc(MLX5DR_DEBUG_DUMP_BUFF_SIZE, GFP_KERNEL);
67 	if (!new_buff->buff) {
68 		kfree(new_buff);
69 		return NULL;
70 	}
71 
72 	INIT_LIST_HEAD(&new_buff->node);
73 	list_add_tail(&new_buff->node, &dump_data->buff_list);
74 
75 	return new_buff;
76 }
77 
78 static struct mlx5dr_dbg_dump_data *
79 mlx5dr_dbg_create_dump_data(void)
80 {
81 	struct mlx5dr_dbg_dump_data *dump_data;
82 
83 	dump_data = kzalloc(sizeof(*dump_data), GFP_KERNEL);
84 	if (!dump_data)
85 		return NULL;
86 
87 	INIT_LIST_HEAD(&dump_data->buff_list);
88 
89 	if (!mlx5dr_dbg_dump_data_init_new_buff(dump_data)) {
90 		kfree(dump_data);
91 		return NULL;
92 	}
93 
94 	return dump_data;
95 }
96 
97 static void
98 mlx5dr_dbg_destroy_dump_data(struct mlx5dr_dbg_dump_data *dump_data)
99 {
100 	struct mlx5dr_dbg_dump_buff *dump_buff, *tmp_buff;
101 
102 	if (!dump_data)
103 		return;
104 
105 	list_for_each_entry_safe(dump_buff, tmp_buff, &dump_data->buff_list, node) {
106 		kvfree(dump_buff->buff);
107 		list_del(&dump_buff->node);
108 		kfree(dump_buff);
109 	}
110 
111 	kfree(dump_data);
112 }
113 
114 static int
115 mlx5dr_dbg_dump_data_print(struct seq_file *file, char *str, u32 size)
116 {
117 	struct mlx5dr_domain *dmn = file->private;
118 	struct mlx5dr_dbg_dump_data *dump_data;
119 	struct mlx5dr_dbg_dump_buff *buff;
120 	u32 buff_capacity, write_size;
121 	int remain_size, ret;
122 
123 	if (size >= MLX5DR_DEBUG_DUMP_BUFF_SIZE)
124 		return -EINVAL;
125 
126 	dump_data = dmn->dump_info.dump_data;
127 	buff = list_last_entry(&dump_data->buff_list,
128 			       struct mlx5dr_dbg_dump_buff, node);
129 
130 	buff_capacity = (MLX5DR_DEBUG_DUMP_BUFF_SIZE - 1) - buff->index;
131 	remain_size = buff_capacity - size;
132 	write_size = (remain_size > 0) ? size : buff_capacity;
133 
134 	if (likely(write_size)) {
135 		ret = snprintf(buff->buff + buff->index, write_size + 1, "%s", str);
136 		if (ret < 0)
137 			return ret;
138 
139 		buff->index += write_size;
140 	}
141 
142 	if (remain_size < 0) {
143 		remain_size *= -1;
144 		buff = mlx5dr_dbg_dump_data_init_new_buff(dump_data);
145 		if (!buff)
146 			return -ENOMEM;
147 
148 		ret = snprintf(buff->buff, remain_size + 1, "%s", str + write_size);
149 		if (ret < 0)
150 			return ret;
151 
152 		buff->index += remain_size;
153 	}
154 
155 	return 0;
156 }
157 
158 void mlx5dr_dbg_tbl_add(struct mlx5dr_table *tbl)
159 {
160 	mutex_lock(&tbl->dmn->dump_info.dbg_mutex);
161 	list_add_tail(&tbl->dbg_node, &tbl->dmn->dbg_tbl_list);
162 	mutex_unlock(&tbl->dmn->dump_info.dbg_mutex);
163 }
164 
165 void mlx5dr_dbg_tbl_del(struct mlx5dr_table *tbl)
166 {
167 	mutex_lock(&tbl->dmn->dump_info.dbg_mutex);
168 	list_del(&tbl->dbg_node);
169 	mutex_unlock(&tbl->dmn->dump_info.dbg_mutex);
170 }
171 
172 void mlx5dr_dbg_rule_add(struct mlx5dr_rule *rule)
173 {
174 	struct mlx5dr_domain *dmn = rule->matcher->tbl->dmn;
175 
176 	mutex_lock(&dmn->dump_info.dbg_mutex);
177 	list_add_tail(&rule->dbg_node, &rule->matcher->dbg_rule_list);
178 	mutex_unlock(&dmn->dump_info.dbg_mutex);
179 }
180 
181 void mlx5dr_dbg_rule_del(struct mlx5dr_rule *rule)
182 {
183 	struct mlx5dr_domain *dmn = rule->matcher->tbl->dmn;
184 
185 	mutex_lock(&dmn->dump_info.dbg_mutex);
186 	list_del(&rule->dbg_node);
187 	mutex_unlock(&dmn->dump_info.dbg_mutex);
188 }
189 
190 static u64 dr_dump_icm_to_idx(u64 icm_addr)
191 {
192 	return (icm_addr >> 6) & 0xffffffff;
193 }
194 
195 #define DR_HEX_SIZE 256
196 
197 static void
198 dr_dump_hex_print(char hex[DR_HEX_SIZE], char *src, u32 size)
199 {
200 	if (WARN_ON_ONCE(DR_HEX_SIZE < 2 * size + 1))
201 		size = DR_HEX_SIZE / 2 - 1; /* truncate */
202 
203 	bin2hex(hex, src, size);
204 	hex[2 * size] = 0; /* NULL-terminate */
205 }
206 
207 static int
208 dr_dump_rule_action_mem(struct seq_file *file, char *buff, const u64 rule_id,
209 			struct mlx5dr_rule_action_member *action_mem)
210 {
211 	struct mlx5dr_action *action = action_mem->action;
212 	const u64 action_id = DR_DBG_PTR_TO_ID(action);
213 	u64 hit_tbl_ptr, miss_tbl_ptr;
214 	u32 hit_tbl_id, miss_tbl_id;
215 	int ret;
216 
217 	switch (action->action_type) {
218 	case DR_ACTION_TYP_DROP:
219 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
220 			       "%d,0x%llx,0x%llx\n",
221 			       DR_DUMP_REC_TYPE_ACTION_DROP, action_id,
222 			       rule_id);
223 		if (ret < 0)
224 			return ret;
225 
226 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
227 		if (ret)
228 			return ret;
229 		break;
230 	case DR_ACTION_TYP_FT:
231 		if (action->dest_tbl->is_fw_tbl)
232 			ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
233 				       "%d,0x%llx,0x%llx,0x%x,0x%x\n",
234 				       DR_DUMP_REC_TYPE_ACTION_FT, action_id,
235 				       rule_id, action->dest_tbl->fw_tbl.id,
236 				       -1);
237 		else
238 			ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
239 				       "%d,0x%llx,0x%llx,0x%x,0x%llx\n",
240 				       DR_DUMP_REC_TYPE_ACTION_FT, action_id,
241 				       rule_id, action->dest_tbl->tbl->table_id,
242 				       DR_DBG_PTR_TO_ID(action->dest_tbl->tbl));
243 
244 		if (ret < 0)
245 			return ret;
246 
247 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
248 		if (ret)
249 			return ret;
250 		break;
251 	case DR_ACTION_TYP_CTR:
252 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
253 			       "%d,0x%llx,0x%llx,0x%x\n",
254 			       DR_DUMP_REC_TYPE_ACTION_CTR, action_id, rule_id,
255 			       action->ctr->ctr_id + action->ctr->offset);
256 		if (ret < 0)
257 			return ret;
258 
259 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
260 		if (ret)
261 			return ret;
262 		break;
263 	case DR_ACTION_TYP_TAG:
264 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
265 			       "%d,0x%llx,0x%llx,0x%x\n",
266 			       DR_DUMP_REC_TYPE_ACTION_TAG, action_id, rule_id,
267 			       action->flow_tag->flow_tag);
268 		if (ret < 0)
269 			return ret;
270 
271 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
272 		if (ret)
273 			return ret;
274 		break;
275 	case DR_ACTION_TYP_MODIFY_HDR:
276 	{
277 		struct mlx5dr_ptrn_obj *ptrn = action->rewrite->ptrn;
278 		struct mlx5dr_arg_obj *arg = action->rewrite->arg;
279 		u8 *rewrite_data = action->rewrite->data;
280 		bool ptrn_arg;
281 		int i;
282 
283 		ptrn_arg = !action->rewrite->single_action_opt && ptrn && arg;
284 
285 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
286 			       "%d,0x%llx,0x%llx,0x%x,%d,0x%x,0x%x,0x%x",
287 			       DR_DUMP_REC_TYPE_ACTION_MODIFY_HDR, action_id,
288 			       rule_id, action->rewrite->index,
289 			       action->rewrite->single_action_opt,
290 			       ptrn_arg ? action->rewrite->num_of_actions : 0,
291 			       ptrn_arg ? ptrn->index : 0,
292 			       ptrn_arg ? mlx5dr_arg_get_obj_id(arg) : 0);
293 		if (ret < 0)
294 			return ret;
295 
296 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
297 		if (ret)
298 			return ret;
299 
300 		if (ptrn_arg) {
301 			for (i = 0; i < action->rewrite->num_of_actions; i++) {
302 				ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
303 					       ",0x%016llx",
304 					       be64_to_cpu(((__be64 *)rewrite_data)[i]));
305 				if (ret < 0)
306 					return ret;
307 
308 				ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
309 				if (ret)
310 					return ret;
311 			}
312 		}
313 
314 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH, "\n");
315 		if (ret < 0)
316 			return ret;
317 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
318 		if (ret)
319 			return ret;
320 		break;
321 	}
322 	case DR_ACTION_TYP_VPORT:
323 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
324 			       "%d,0x%llx,0x%llx,0x%x\n",
325 			       DR_DUMP_REC_TYPE_ACTION_VPORT, action_id, rule_id,
326 			       action->vport->caps->num);
327 		if (ret < 0)
328 			return ret;
329 
330 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
331 		if (ret)
332 			return ret;
333 		break;
334 	case DR_ACTION_TYP_TNL_L2_TO_L2:
335 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
336 			       "%d,0x%llx,0x%llx\n",
337 			       DR_DUMP_REC_TYPE_ACTION_DECAP_L2, action_id,
338 			       rule_id);
339 		if (ret < 0)
340 			return ret;
341 
342 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
343 		if (ret)
344 			return ret;
345 		break;
346 	case DR_ACTION_TYP_TNL_L3_TO_L2:
347 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
348 			       "%d,0x%llx,0x%llx,0x%x\n",
349 			       DR_DUMP_REC_TYPE_ACTION_DECAP_L3, action_id,
350 			       rule_id,
351 			       (action->rewrite->ptrn && action->rewrite->arg) ?
352 			       mlx5dr_arg_get_obj_id(action->rewrite->arg) :
353 			       action->rewrite->index);
354 		if (ret < 0)
355 			return ret;
356 
357 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
358 		if (ret)
359 			return ret;
360 		break;
361 	case DR_ACTION_TYP_L2_TO_TNL_L2:
362 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
363 			       "%d,0x%llx,0x%llx,0x%x\n",
364 			       DR_DUMP_REC_TYPE_ACTION_ENCAP_L2, action_id,
365 			       rule_id, action->reformat->id);
366 		if (ret < 0)
367 			return ret;
368 
369 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
370 		if (ret)
371 			return ret;
372 		break;
373 	case DR_ACTION_TYP_L2_TO_TNL_L3:
374 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
375 			       "%d,0x%llx,0x%llx,0x%x\n",
376 			       DR_DUMP_REC_TYPE_ACTION_ENCAP_L3, action_id,
377 			       rule_id, action->reformat->id);
378 		if (ret < 0)
379 			return ret;
380 
381 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
382 		if (ret)
383 			return ret;
384 		break;
385 	case DR_ACTION_TYP_POP_VLAN:
386 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
387 			       "%d,0x%llx,0x%llx\n",
388 			       DR_DUMP_REC_TYPE_ACTION_POP_VLAN, action_id,
389 			       rule_id);
390 		if (ret < 0)
391 			return ret;
392 
393 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
394 		if (ret)
395 			return ret;
396 		break;
397 	case DR_ACTION_TYP_PUSH_VLAN:
398 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
399 			       "%d,0x%llx,0x%llx,0x%x\n",
400 			       DR_DUMP_REC_TYPE_ACTION_PUSH_VLAN, action_id,
401 			       rule_id, action->push_vlan->vlan_hdr);
402 		if (ret < 0)
403 			return ret;
404 
405 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
406 		if (ret)
407 			return ret;
408 		break;
409 	case DR_ACTION_TYP_INSERT_HDR:
410 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
411 			       "%d,0x%llx,0x%llx,0x%x,0x%x,0x%x\n",
412 			       DR_DUMP_REC_TYPE_ACTION_INSERT_HDR, action_id,
413 			       rule_id, action->reformat->id,
414 			       action->reformat->param_0,
415 			       action->reformat->param_1);
416 		if (ret < 0)
417 			return ret;
418 
419 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
420 		if (ret)
421 			return ret;
422 		break;
423 	case DR_ACTION_TYP_REMOVE_HDR:
424 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
425 			       "%d,0x%llx,0x%llx,0x%x,0x%x,0x%x\n",
426 			       DR_DUMP_REC_TYPE_ACTION_REMOVE_HDR, action_id,
427 			       rule_id, action->reformat->id,
428 			       action->reformat->param_0,
429 			       action->reformat->param_1);
430 		if (ret < 0)
431 			return ret;
432 
433 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
434 		if (ret)
435 			return ret;
436 		break;
437 	case DR_ACTION_TYP_SAMPLER:
438 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
439 			       "%d,0x%llx,0x%llx,0x%x,0x%x,0x%x,0x%llx,0x%llx\n",
440 			       DR_DUMP_REC_TYPE_ACTION_SAMPLER, action_id,
441 			       rule_id, 0, 0, action->sampler->sampler_id,
442 			       action->sampler->rx_icm_addr,
443 			       action->sampler->tx_icm_addr);
444 		if (ret < 0)
445 			return ret;
446 
447 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
448 		if (ret)
449 			return ret;
450 		break;
451 	case DR_ACTION_TYP_RANGE:
452 		if (action->range->hit_tbl_action->dest_tbl->is_fw_tbl) {
453 			hit_tbl_id = action->range->hit_tbl_action->dest_tbl->fw_tbl.id;
454 			hit_tbl_ptr = 0;
455 		} else {
456 			hit_tbl_id = action->range->hit_tbl_action->dest_tbl->tbl->table_id;
457 			hit_tbl_ptr =
458 				DR_DBG_PTR_TO_ID(action->range->hit_tbl_action->dest_tbl->tbl);
459 		}
460 
461 		if (action->range->miss_tbl_action->dest_tbl->is_fw_tbl) {
462 			miss_tbl_id = action->range->miss_tbl_action->dest_tbl->fw_tbl.id;
463 			miss_tbl_ptr = 0;
464 		} else {
465 			miss_tbl_id = action->range->miss_tbl_action->dest_tbl->tbl->table_id;
466 			miss_tbl_ptr =
467 				DR_DBG_PTR_TO_ID(action->range->miss_tbl_action->dest_tbl->tbl);
468 		}
469 
470 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
471 			       "%d,0x%llx,0x%llx,0x%x,0x%llx,0x%x,0x%llx,0x%x\n",
472 			       DR_DUMP_REC_TYPE_ACTION_MATCH_RANGE, action_id,
473 			       rule_id, hit_tbl_id, hit_tbl_ptr, miss_tbl_id,
474 			       miss_tbl_ptr, action->range->definer_id);
475 		if (ret < 0)
476 			return ret;
477 
478 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
479 		if (ret)
480 			return ret;
481 		break;
482 	default:
483 		return 0;
484 	}
485 
486 	return 0;
487 }
488 
489 static int
490 dr_dump_rule_mem(struct seq_file *file, char *buff, struct mlx5dr_ste *ste,
491 		 bool is_rx, const u64 rule_id, u8 format_ver)
492 {
493 	char hw_ste_dump[DR_HEX_SIZE];
494 	u32 mem_rec_type;
495 	int ret;
496 
497 	if (format_ver == MLX5_STEERING_FORMAT_CONNECTX_5) {
498 		mem_rec_type = is_rx ? DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V0 :
499 				       DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V0;
500 	} else {
501 		mem_rec_type = is_rx ? DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V1 :
502 				       DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V1;
503 	}
504 
505 	dr_dump_hex_print(hw_ste_dump, (char *)mlx5dr_ste_get_hw_ste(ste),
506 			  DR_STE_SIZE_REDUCED);
507 
508 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
509 		       "%d,0x%llx,0x%llx,%s\n", mem_rec_type,
510 		       dr_dump_icm_to_idx(mlx5dr_ste_get_icm_addr(ste)),
511 		       rule_id, hw_ste_dump);
512 	if (ret < 0)
513 		return ret;
514 
515 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
516 	if (ret)
517 		return ret;
518 
519 	return 0;
520 }
521 
522 static int
523 dr_dump_rule_rx_tx(struct seq_file *file, char *buff,
524 		   struct mlx5dr_rule_rx_tx *rule_rx_tx,
525 		   bool is_rx, const u64 rule_id, u8 format_ver)
526 {
527 	struct mlx5dr_ste *ste_arr[DR_RULE_MAX_STES + DR_ACTION_MAX_STES];
528 	struct mlx5dr_ste *curr_ste = rule_rx_tx->last_rule_ste;
529 	int ret, i;
530 
531 	if (mlx5dr_rule_get_reverse_rule_members(ste_arr, curr_ste, &i))
532 		return 0;
533 
534 	while (i--) {
535 		ret = dr_dump_rule_mem(file, buff, ste_arr[i], is_rx, rule_id,
536 				       format_ver);
537 		if (ret < 0)
538 			return ret;
539 	}
540 
541 	return 0;
542 }
543 
544 static noinline_for_stack int
545 dr_dump_rule(struct seq_file *file, struct mlx5dr_rule *rule)
546 {
547 	struct mlx5dr_rule_action_member *action_mem;
548 	const u64 rule_id = DR_DBG_PTR_TO_ID(rule);
549 	char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH];
550 	struct mlx5dr_rule_rx_tx *rx = &rule->rx;
551 	struct mlx5dr_rule_rx_tx *tx = &rule->tx;
552 	u8 format_ver;
553 	int ret;
554 
555 	format_ver = rule->matcher->tbl->dmn->info.caps.sw_format_ver;
556 
557 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
558 		       "%d,0x%llx,0x%llx\n", DR_DUMP_REC_TYPE_RULE,
559 		       rule_id, DR_DBG_PTR_TO_ID(rule->matcher));
560 	if (ret < 0)
561 		return ret;
562 
563 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
564 	if (ret)
565 		return ret;
566 
567 	if (rx->nic_matcher) {
568 		ret = dr_dump_rule_rx_tx(file, buff, rx, true, rule_id, format_ver);
569 		if (ret < 0)
570 			return ret;
571 	}
572 
573 	if (tx->nic_matcher) {
574 		ret = dr_dump_rule_rx_tx(file, buff, tx, false, rule_id, format_ver);
575 		if (ret < 0)
576 			return ret;
577 	}
578 
579 	list_for_each_entry(action_mem, &rule->rule_actions_list, list) {
580 		ret = dr_dump_rule_action_mem(file, buff, rule_id, action_mem);
581 		if (ret < 0)
582 			return ret;
583 	}
584 
585 	return 0;
586 }
587 
588 static int
589 dr_dump_matcher_mask(struct seq_file *file, char *buff,
590 		     struct mlx5dr_match_param *mask,
591 		     u8 criteria, const u64 matcher_id)
592 {
593 	char dump[DR_HEX_SIZE];
594 	int ret;
595 
596 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH, "%d,0x%llx,",
597 		       DR_DUMP_REC_TYPE_MATCHER_MASK, matcher_id);
598 	if (ret < 0)
599 		return ret;
600 
601 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
602 	if (ret)
603 		return ret;
604 
605 	if (criteria & DR_MATCHER_CRITERIA_OUTER) {
606 		dr_dump_hex_print(dump, (char *)&mask->outer, sizeof(mask->outer));
607 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
608 			       "%s,", dump);
609 	} else {
610 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH, ",");
611 	}
612 
613 	if (ret < 0)
614 		return ret;
615 
616 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
617 	if (ret)
618 		return ret;
619 
620 	if (criteria & DR_MATCHER_CRITERIA_INNER) {
621 		dr_dump_hex_print(dump, (char *)&mask->inner, sizeof(mask->inner));
622 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
623 			       "%s,", dump);
624 	} else {
625 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH, ",");
626 	}
627 
628 	if (ret < 0)
629 		return ret;
630 
631 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
632 	if (ret)
633 		return ret;
634 
635 	if (criteria & DR_MATCHER_CRITERIA_MISC) {
636 		dr_dump_hex_print(dump, (char *)&mask->misc, sizeof(mask->misc));
637 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
638 			       "%s,", dump);
639 	} else {
640 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH, ",");
641 	}
642 
643 	if (ret < 0)
644 		return ret;
645 
646 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
647 	if (ret)
648 		return ret;
649 
650 	if (criteria & DR_MATCHER_CRITERIA_MISC2) {
651 		dr_dump_hex_print(dump, (char *)&mask->misc2, sizeof(mask->misc2));
652 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
653 			       "%s,", dump);
654 	} else {
655 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH, ",");
656 	}
657 
658 	if (ret < 0)
659 		return ret;
660 
661 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
662 	if (ret)
663 		return ret;
664 
665 	if (criteria & DR_MATCHER_CRITERIA_MISC3) {
666 		dr_dump_hex_print(dump, (char *)&mask->misc3, sizeof(mask->misc3));
667 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
668 			       "%s\n", dump);
669 	} else {
670 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH, ",\n");
671 	}
672 
673 	if (ret < 0)
674 		return ret;
675 
676 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
677 	if (ret)
678 		return ret;
679 
680 	return 0;
681 }
682 
683 static int
684 dr_dump_matcher_builder(struct seq_file *file, char *buff,
685 			struct mlx5dr_ste_build *builder,
686 			u32 index, bool is_rx, const u64 matcher_id)
687 {
688 	int ret;
689 
690 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
691 		       "%d,0x%llx,%d,%d,0x%x\n",
692 		       DR_DUMP_REC_TYPE_MATCHER_BUILDER, matcher_id, index,
693 		       is_rx, builder->lu_type);
694 	if (ret < 0)
695 		return ret;
696 
697 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
698 	if (ret)
699 		return ret;
700 
701 	return 0;
702 }
703 
704 static int
705 dr_dump_matcher_rx_tx(struct seq_file *file, char *buff, bool is_rx,
706 		      struct mlx5dr_matcher_rx_tx *matcher_rx_tx,
707 		      const u64 matcher_id)
708 {
709 	enum dr_dump_rec_type rec_type;
710 	u64 s_icm_addr, e_icm_addr;
711 	int i, ret;
712 
713 	rec_type = is_rx ? DR_DUMP_REC_TYPE_MATCHER_RX :
714 			   DR_DUMP_REC_TYPE_MATCHER_TX;
715 
716 	s_icm_addr = mlx5dr_icm_pool_get_chunk_icm_addr(matcher_rx_tx->s_htbl->chunk);
717 	e_icm_addr = mlx5dr_icm_pool_get_chunk_icm_addr(matcher_rx_tx->e_anchor->chunk);
718 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
719 		       "%d,0x%llx,0x%llx,%d,0x%llx,0x%llx\n",
720 		       rec_type, DR_DBG_PTR_TO_ID(matcher_rx_tx),
721 		       matcher_id, matcher_rx_tx->num_of_builders,
722 		       dr_dump_icm_to_idx(s_icm_addr),
723 		       dr_dump_icm_to_idx(e_icm_addr));
724 
725 	if (ret < 0)
726 		return ret;
727 
728 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
729 	if (ret)
730 		return ret;
731 
732 	for (i = 0; i < matcher_rx_tx->num_of_builders; i++) {
733 		ret = dr_dump_matcher_builder(file, buff,
734 					      &matcher_rx_tx->ste_builder[i],
735 					      i, is_rx, matcher_id);
736 		if (ret < 0)
737 			return ret;
738 	}
739 
740 	return 0;
741 }
742 
743 static noinline_for_stack int
744 dr_dump_matcher(struct seq_file *file, struct mlx5dr_matcher *matcher)
745 {
746 	struct mlx5dr_matcher_rx_tx *rx = &matcher->rx;
747 	struct mlx5dr_matcher_rx_tx *tx = &matcher->tx;
748 	char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH];
749 	u64 matcher_id;
750 	int ret;
751 
752 	matcher_id = DR_DBG_PTR_TO_ID(matcher);
753 
754 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
755 		       "%d,0x%llx,0x%llx,%d\n", DR_DUMP_REC_TYPE_MATCHER,
756 		       matcher_id, DR_DBG_PTR_TO_ID(matcher->tbl),
757 		       matcher->prio);
758 	if (ret < 0)
759 		return ret;
760 
761 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
762 	if (ret)
763 		return ret;
764 
765 	ret = dr_dump_matcher_mask(file, buff, &matcher->mask,
766 				   matcher->match_criteria, matcher_id);
767 	if (ret < 0)
768 		return ret;
769 
770 	if (rx->nic_tbl) {
771 		ret = dr_dump_matcher_rx_tx(file, buff, true, rx, matcher_id);
772 		if (ret < 0)
773 			return ret;
774 	}
775 
776 	if (tx->nic_tbl) {
777 		ret = dr_dump_matcher_rx_tx(file, buff, false, tx, matcher_id);
778 		if (ret < 0)
779 			return ret;
780 	}
781 
782 	return 0;
783 }
784 
785 static int
786 dr_dump_matcher_all(struct seq_file *file, struct mlx5dr_matcher *matcher)
787 {
788 	struct mlx5dr_rule *rule;
789 	int ret;
790 
791 	ret = dr_dump_matcher(file, matcher);
792 	if (ret < 0)
793 		return ret;
794 
795 	list_for_each_entry(rule, &matcher->dbg_rule_list, dbg_node) {
796 		ret = dr_dump_rule(file, rule);
797 		if (ret < 0)
798 			return ret;
799 	}
800 
801 	return 0;
802 }
803 
804 static int
805 dr_dump_table_rx_tx(struct seq_file *file, char *buff, bool is_rx,
806 		    struct mlx5dr_table_rx_tx *table_rx_tx,
807 		    const u64 table_id)
808 {
809 	enum dr_dump_rec_type rec_type;
810 	u64 s_icm_addr;
811 	int ret;
812 
813 	rec_type = is_rx ? DR_DUMP_REC_TYPE_TABLE_RX :
814 			   DR_DUMP_REC_TYPE_TABLE_TX;
815 
816 	s_icm_addr = mlx5dr_icm_pool_get_chunk_icm_addr(table_rx_tx->s_anchor->chunk);
817 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
818 		       "%d,0x%llx,0x%llx\n", rec_type, table_id,
819 		       dr_dump_icm_to_idx(s_icm_addr));
820 	if (ret < 0)
821 		return ret;
822 
823 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
824 	if (ret)
825 		return ret;
826 
827 	return 0;
828 }
829 
830 static noinline_for_stack int
831 dr_dump_table(struct seq_file *file, struct mlx5dr_table *table)
832 {
833 	struct mlx5dr_table_rx_tx *rx = &table->rx;
834 	struct mlx5dr_table_rx_tx *tx = &table->tx;
835 	char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH];
836 	int ret;
837 
838 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
839 		       "%d,0x%llx,0x%llx,%d,%d\n", DR_DUMP_REC_TYPE_TABLE,
840 		       DR_DBG_PTR_TO_ID(table), DR_DBG_PTR_TO_ID(table->dmn),
841 		       table->table_type, table->level);
842 	if (ret < 0)
843 		return ret;
844 
845 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
846 	if (ret)
847 		return ret;
848 
849 	if (rx->nic_dmn) {
850 		ret = dr_dump_table_rx_tx(file, buff, true, rx,
851 					  DR_DBG_PTR_TO_ID(table));
852 		if (ret < 0)
853 			return ret;
854 	}
855 
856 	if (tx->nic_dmn) {
857 		ret = dr_dump_table_rx_tx(file, buff, false, tx,
858 					  DR_DBG_PTR_TO_ID(table));
859 		if (ret < 0)
860 			return ret;
861 	}
862 	return 0;
863 }
864 
865 static int dr_dump_table_all(struct seq_file *file, struct mlx5dr_table *tbl)
866 {
867 	struct mlx5dr_matcher *matcher;
868 	int ret;
869 
870 	ret = dr_dump_table(file, tbl);
871 	if (ret < 0)
872 		return ret;
873 
874 	list_for_each_entry(matcher, &tbl->matcher_list, list_node) {
875 		ret = dr_dump_matcher_all(file, matcher);
876 		if (ret < 0)
877 			return ret;
878 	}
879 	return 0;
880 }
881 
882 static int
883 dr_dump_send_ring(struct seq_file *file, char *buff,
884 		  struct mlx5dr_send_ring *ring,
885 		  const u64 domain_id)
886 {
887 	int ret;
888 
889 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
890 		       "%d,0x%llx,0x%llx,0x%x,0x%x\n",
891 		       DR_DUMP_REC_TYPE_DOMAIN_SEND_RING,
892 		       DR_DBG_PTR_TO_ID(ring), domain_id,
893 		       ring->cq->mcq.cqn, ring->qp->qpn);
894 	if (ret < 0)
895 		return ret;
896 
897 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
898 	if (ret)
899 		return ret;
900 
901 	return 0;
902 }
903 
904 static int
905 dr_dump_domain_info_flex_parser(struct seq_file *file,
906 				char *buff,
907 				const char *flex_parser_name,
908 				const u8 flex_parser_value,
909 				const u64 domain_id)
910 {
911 	int ret;
912 
913 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
914 		       "%d,0x%llx,%s,0x%x\n",
915 		       DR_DUMP_REC_TYPE_DOMAIN_INFO_FLEX_PARSER, domain_id,
916 		       flex_parser_name, flex_parser_value);
917 	if (ret < 0)
918 		return ret;
919 
920 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
921 	if (ret)
922 		return ret;
923 
924 	return 0;
925 }
926 
927 static int
928 dr_dump_domain_info_caps(struct seq_file *file, char *buff,
929 			 struct mlx5dr_cmd_caps *caps,
930 			 const u64 domain_id)
931 {
932 	struct mlx5dr_cmd_vport_cap *vport_caps;
933 	unsigned long i, vports_num;
934 	int ret;
935 
936 	xa_for_each(&caps->vports.vports_caps_xa, vports_num, vport_caps)
937 		; /* count the number of vports in xarray */
938 
939 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
940 		       "%d,0x%llx,0x%x,0x%llx,0x%llx,0x%x,%lu,%d\n",
941 		       DR_DUMP_REC_TYPE_DOMAIN_INFO_CAPS, domain_id, caps->gvmi,
942 		       caps->nic_rx_drop_address, caps->nic_tx_drop_address,
943 		       caps->flex_protocols, vports_num, caps->eswitch_manager);
944 	if (ret < 0)
945 		return ret;
946 
947 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
948 	if (ret)
949 		return ret;
950 
951 	xa_for_each(&caps->vports.vports_caps_xa, i, vport_caps) {
952 		vport_caps = xa_load(&caps->vports.vports_caps_xa, i);
953 
954 		ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
955 			       "%d,0x%llx,%lu,0x%x,0x%llx,0x%llx\n",
956 			       DR_DUMP_REC_TYPE_DOMAIN_INFO_VPORT,
957 			       domain_id, i, vport_caps->vport_gvmi,
958 			       vport_caps->icm_address_rx,
959 			       vport_caps->icm_address_tx);
960 		if (ret < 0)
961 			return ret;
962 
963 		ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
964 		if (ret)
965 			return ret;
966 	}
967 	return 0;
968 }
969 
970 static int
971 dr_dump_domain_info(struct seq_file *file, char *buff,
972 		    struct mlx5dr_domain_info *info,
973 		    const u64 domain_id)
974 {
975 	int ret;
976 
977 	ret = dr_dump_domain_info_caps(file, buff, &info->caps, domain_id);
978 	if (ret < 0)
979 		return ret;
980 
981 	ret = dr_dump_domain_info_flex_parser(file, buff, "icmp_dw0",
982 					      info->caps.flex_parser_id_icmp_dw0,
983 					      domain_id);
984 	if (ret < 0)
985 		return ret;
986 
987 	ret = dr_dump_domain_info_flex_parser(file, buff, "icmp_dw1",
988 					      info->caps.flex_parser_id_icmp_dw1,
989 					      domain_id);
990 	if (ret < 0)
991 		return ret;
992 
993 	ret = dr_dump_domain_info_flex_parser(file, buff, "icmpv6_dw0",
994 					      info->caps.flex_parser_id_icmpv6_dw0,
995 					      domain_id);
996 	if (ret < 0)
997 		return ret;
998 
999 	ret = dr_dump_domain_info_flex_parser(file, buff, "icmpv6_dw1",
1000 					      info->caps.flex_parser_id_icmpv6_dw1,
1001 					      domain_id);
1002 	if (ret < 0)
1003 		return ret;
1004 
1005 	return 0;
1006 }
1007 
1008 static noinline_for_stack int
1009 dr_dump_domain(struct seq_file *file, struct mlx5dr_domain *dmn)
1010 {
1011 	char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH];
1012 	u64 domain_id = DR_DBG_PTR_TO_ID(dmn);
1013 	int ret;
1014 
1015 	ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH,
1016 		       "%d,0x%llx,%d,0%x,%d,%u.%u.%u,%s,%d,%u,%u,%u\n",
1017 		       DR_DUMP_REC_TYPE_DOMAIN,
1018 		       domain_id, dmn->type, dmn->info.caps.gvmi,
1019 		       dmn->info.supp_sw_steering,
1020 		       /* package version */
1021 		       LINUX_VERSION_MAJOR, LINUX_VERSION_PATCHLEVEL,
1022 		       LINUX_VERSION_SUBLEVEL,
1023 		       pci_name(dmn->mdev->pdev),
1024 		       0, /* domain flags */
1025 		       dmn->num_buddies[DR_ICM_TYPE_STE],
1026 		       dmn->num_buddies[DR_ICM_TYPE_MODIFY_ACTION],
1027 		       dmn->num_buddies[DR_ICM_TYPE_MODIFY_HDR_PTRN]);
1028 	if (ret < 0)
1029 		return ret;
1030 
1031 	ret = mlx5dr_dbg_dump_data_print(file, buff, ret);
1032 	if (ret)
1033 		return ret;
1034 
1035 	ret = dr_dump_domain_info(file, buff, &dmn->info, domain_id);
1036 	if (ret < 0)
1037 		return ret;
1038 
1039 	if (dmn->info.supp_sw_steering) {
1040 		ret = dr_dump_send_ring(file, buff, dmn->send_ring, domain_id);
1041 		if (ret < 0)
1042 			return ret;
1043 	}
1044 
1045 	return 0;
1046 }
1047 
1048 static int dr_dump_domain_all(struct seq_file *file, struct mlx5dr_domain *dmn)
1049 {
1050 	struct mlx5dr_table *tbl;
1051 	int ret;
1052 
1053 	mutex_lock(&dmn->dump_info.dbg_mutex);
1054 	mlx5dr_domain_lock(dmn);
1055 
1056 	ret = dr_dump_domain(file, dmn);
1057 	if (ret < 0)
1058 		goto unlock_mutex;
1059 
1060 	list_for_each_entry(tbl, &dmn->dbg_tbl_list, dbg_node) {
1061 		ret = dr_dump_table_all(file, tbl);
1062 		if (ret < 0)
1063 			break;
1064 	}
1065 
1066 unlock_mutex:
1067 	mlx5dr_domain_unlock(dmn);
1068 	mutex_unlock(&dmn->dump_info.dbg_mutex);
1069 	return ret;
1070 }
1071 
1072 static void *
1073 dr_dump_start(struct seq_file *file, loff_t *pos)
1074 {
1075 	struct mlx5dr_domain *dmn = file->private;
1076 	struct mlx5dr_dbg_dump_data *dump_data;
1077 
1078 	if (atomic_read(&dmn->dump_info.state) != MLX5DR_DEBUG_DUMP_STATE_FREE) {
1079 		mlx5_core_warn(dmn->mdev, "Dump already in progress\n");
1080 		return ERR_PTR(-EBUSY);
1081 	}
1082 
1083 	atomic_set(&dmn->dump_info.state, MLX5DR_DEBUG_DUMP_STATE_IN_PROGRESS);
1084 	dump_data = dmn->dump_info.dump_data;
1085 
1086 	if (dump_data) {
1087 		return seq_list_start(&dump_data->buff_list, *pos);
1088 	} else if (*pos == 0) {
1089 		dump_data = mlx5dr_dbg_create_dump_data();
1090 		if (!dump_data)
1091 			goto exit;
1092 
1093 		dmn->dump_info.dump_data = dump_data;
1094 		if (dr_dump_domain_all(file, dmn)) {
1095 			mlx5dr_dbg_destroy_dump_data(dump_data);
1096 			dmn->dump_info.dump_data = NULL;
1097 			goto exit;
1098 		}
1099 
1100 		return seq_list_start(&dump_data->buff_list, *pos);
1101 	}
1102 
1103 exit:
1104 	atomic_set(&dmn->dump_info.state, MLX5DR_DEBUG_DUMP_STATE_FREE);
1105 	return NULL;
1106 }
1107 
1108 static void *
1109 dr_dump_next(struct seq_file *file, void *v, loff_t *pos)
1110 {
1111 	struct mlx5dr_domain *dmn = file->private;
1112 	struct mlx5dr_dbg_dump_data *dump_data;
1113 
1114 	dump_data = dmn->dump_info.dump_data;
1115 
1116 	return seq_list_next(v, &dump_data->buff_list, pos);
1117 }
1118 
1119 static void
1120 dr_dump_stop(struct seq_file *file, void *v)
1121 {
1122 	struct mlx5dr_domain *dmn = file->private;
1123 	struct mlx5dr_dbg_dump_data *dump_data;
1124 
1125 	if (v && IS_ERR(v))
1126 		return;
1127 
1128 	if (!v) {
1129 		dump_data = dmn->dump_info.dump_data;
1130 		if (dump_data) {
1131 			mlx5dr_dbg_destroy_dump_data(dump_data);
1132 			dmn->dump_info.dump_data = NULL;
1133 		}
1134 	}
1135 
1136 	atomic_set(&dmn->dump_info.state, MLX5DR_DEBUG_DUMP_STATE_FREE);
1137 }
1138 
1139 static int
1140 dr_dump_show(struct seq_file *file, void *v)
1141 {
1142 	struct mlx5dr_dbg_dump_buff *entry;
1143 
1144 	entry = list_entry(v, struct mlx5dr_dbg_dump_buff, node);
1145 	seq_printf(file, "%s", entry->buff);
1146 
1147 	return 0;
1148 }
1149 
1150 static const struct seq_operations dr_dump_sops = {
1151 	.start	= dr_dump_start,
1152 	.next	= dr_dump_next,
1153 	.stop	= dr_dump_stop,
1154 	.show	= dr_dump_show,
1155 };
1156 DEFINE_SEQ_ATTRIBUTE(dr_dump);
1157 
1158 void mlx5dr_dbg_init_dump(struct mlx5dr_domain *dmn)
1159 {
1160 	struct mlx5_core_dev *dev = dmn->mdev;
1161 	char file_name[128];
1162 
1163 	if (dmn->type != MLX5DR_DOMAIN_TYPE_FDB) {
1164 		mlx5_core_warn(dev,
1165 			       "Steering dump is not supported for NIC RX/TX domains\n");
1166 		return;
1167 	}
1168 
1169 	dmn->dump_info.steering_debugfs =
1170 		debugfs_create_dir("steering", mlx5_debugfs_get_dev_root(dev));
1171 	dmn->dump_info.fdb_debugfs =
1172 		debugfs_create_dir("fdb", dmn->dump_info.steering_debugfs);
1173 
1174 	sprintf(file_name, "dmn_%p", dmn);
1175 	debugfs_create_file(file_name, 0444, dmn->dump_info.fdb_debugfs,
1176 			    dmn, &dr_dump_fops);
1177 
1178 	INIT_LIST_HEAD(&dmn->dbg_tbl_list);
1179 	mutex_init(&dmn->dump_info.dbg_mutex);
1180 }
1181 
1182 void mlx5dr_dbg_uninit_dump(struct mlx5dr_domain *dmn)
1183 {
1184 	debugfs_remove_recursive(dmn->dump_info.steering_debugfs);
1185 	mutex_destroy(&dmn->dump_info.dbg_mutex);
1186 }
1187