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