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