1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 #include <linux/debugfs.h>
5 #include <linux/kernel.h>
6 #include <linux/seq_file.h>
7 #include <linux/version.h>
10 #define DR_DBG_PTR_TO_ID(p) ((u64)(uintptr_t)(p) & 0xFFFFFFFFULL)
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,
20 DR_DUMP_REC_TYPE_TABLE
= 3100,
21 DR_DUMP_REC_TYPE_TABLE_RX
= 3101,
22 DR_DUMP_REC_TYPE_TABLE_TX
= 3102,
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,
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,
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,
57 static struct mlx5dr_dbg_dump_buff
*
58 mlx5dr_dbg_dump_data_init_new_buff(struct mlx5dr_dbg_dump_data
*dump_data
)
60 struct mlx5dr_dbg_dump_buff
*new_buff
;
62 new_buff
= kzalloc(sizeof(*new_buff
), GFP_KERNEL
);
66 new_buff
->buff
= kvzalloc(MLX5DR_DEBUG_DUMP_BUFF_SIZE
, GFP_KERNEL
);
67 if (!new_buff
->buff
) {
72 INIT_LIST_HEAD(&new_buff
->node
);
73 list_add_tail(&new_buff
->node
, &dump_data
->buff_list
);
78 static struct mlx5dr_dbg_dump_data
*
79 mlx5dr_dbg_create_dump_data(void)
81 struct mlx5dr_dbg_dump_data
*dump_data
;
83 dump_data
= kzalloc(sizeof(*dump_data
), GFP_KERNEL
);
87 INIT_LIST_HEAD(&dump_data
->buff_list
);
89 if (!mlx5dr_dbg_dump_data_init_new_buff(dump_data
)) {
98 mlx5dr_dbg_destroy_dump_data(struct mlx5dr_dbg_dump_data
*dump_data
)
100 struct mlx5dr_dbg_dump_buff
*dump_buff
, *tmp_buff
;
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
);
115 mlx5dr_dbg_dump_data_print(struct seq_file
*file
, char *str
, u32 size
)
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
;
123 if (size
>= MLX5DR_DEBUG_DUMP_BUFF_SIZE
)
126 dump_data
= dmn
->dump_info
.dump_data
;
127 buff
= list_last_entry(&dump_data
->buff_list
,
128 struct mlx5dr_dbg_dump_buff
, node
);
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
;
134 if (likely(write_size
)) {
135 ret
= snprintf(buff
->buff
+ buff
->index
, write_size
+ 1, "%s", str
);
139 buff
->index
+= write_size
;
142 if (remain_size
< 0) {
144 buff
= mlx5dr_dbg_dump_data_init_new_buff(dump_data
);
148 ret
= snprintf(buff
->buff
, remain_size
+ 1, "%s", str
+ write_size
);
152 buff
->index
+= remain_size
;
158 void mlx5dr_dbg_tbl_add(struct mlx5dr_table
*tbl
)
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
);
165 void mlx5dr_dbg_tbl_del(struct mlx5dr_table
*tbl
)
167 mutex_lock(&tbl
->dmn
->dump_info
.dbg_mutex
);
168 list_del(&tbl
->dbg_node
);
169 mutex_unlock(&tbl
->dmn
->dump_info
.dbg_mutex
);
172 void mlx5dr_dbg_rule_add(struct mlx5dr_rule
*rule
)
174 struct mlx5dr_domain
*dmn
= rule
->matcher
->tbl
->dmn
;
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
);
181 void mlx5dr_dbg_rule_del(struct mlx5dr_rule
*rule
)
183 struct mlx5dr_domain
*dmn
= rule
->matcher
->tbl
->dmn
;
185 mutex_lock(&dmn
->dump_info
.dbg_mutex
);
186 list_del(&rule
->dbg_node
);
187 mutex_unlock(&dmn
->dump_info
.dbg_mutex
);
190 static u64
dr_dump_icm_to_idx(u64 icm_addr
)
192 return (icm_addr
>> 6) & 0xffffffff;
195 #define DR_HEX_SIZE 256
198 dr_dump_hex_print(char hex
[DR_HEX_SIZE
], char *src
, u32 size
)
200 if (WARN_ON_ONCE(DR_HEX_SIZE
< 2 * size
+ 1))
201 size
= DR_HEX_SIZE
/ 2 - 1; /* truncate */
203 bin2hex(hex
, src
, size
);
204 hex
[2 * size
] = 0; /* NULL-terminate */
208 dr_dump_rule_action_mem(struct seq_file
*file
, char *buff
, const u64 rule_id
,
209 struct mlx5dr_rule_action_member
*action_mem
)
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
;
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
,
226 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
,
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
));
247 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
);
259 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
);
271 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
275 case DR_ACTION_TYP_MODIFY_HDR
:
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
;
283 ptrn_arg
= !action
->rewrite
->single_action_opt
&& ptrn
&& arg
;
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);
296 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
301 for (i
= 0; i
< action
->rewrite
->num_of_actions
; i
++) {
302 ret
= snprintf(buff
, MLX5DR_DEBUG_DUMP_BUFF_LENGTH
,
304 be64_to_cpu(((__be64
*)rewrite_data
)[i
]));
308 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
314 ret
= snprintf(buff
, MLX5DR_DEBUG_DUMP_BUFF_LENGTH
, "\n");
317 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
);
330 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
,
342 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
,
351 (action
->rewrite
->ptrn
&& action
->rewrite
->arg
) ?
352 mlx5dr_arg_get_obj_id(action
->rewrite
->arg
) :
353 action
->rewrite
->index
);
357 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
);
369 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
);
381 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
,
393 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
);
405 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
);
419 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
);
433 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
);
447 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
;
456 hit_tbl_id
= action
->range
->hit_tbl_action
->dest_tbl
->tbl
->table_id
;
458 DR_DBG_PTR_TO_ID(action
->range
->hit_tbl_action
->dest_tbl
->tbl
);
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
;
465 miss_tbl_id
= action
->range
->miss_tbl_action
->dest_tbl
->tbl
->table_id
;
467 DR_DBG_PTR_TO_ID(action
->range
->miss_tbl_action
->dest_tbl
->tbl
);
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
);
478 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
)
493 char hw_ste_dump
[DR_HEX_SIZE
];
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
;
501 mem_rec_type
= is_rx
? DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V1
:
502 DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V1
;
505 dr_dump_hex_print(hw_ste_dump
, (char *)mlx5dr_ste_get_hw_ste(ste
),
506 DR_STE_SIZE_REDUCED
);
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
);
515 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
)
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
;
531 if (mlx5dr_rule_get_reverse_rule_members(ste_arr
, curr_ste
, &i
))
535 ret
= dr_dump_rule_mem(file
, buff
, ste_arr
[i
], is_rx
, rule_id
,
544 static noinline_for_stack
int
545 dr_dump_rule(struct seq_file
*file
, struct mlx5dr_rule
*rule
)
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
;
555 format_ver
= rule
->matcher
->tbl
->dmn
->info
.caps
.sw_format_ver
;
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
));
563 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
567 if (rx
->nic_matcher
) {
568 ret
= dr_dump_rule_rx_tx(file
, buff
, rx
, true, rule_id
, format_ver
);
573 if (tx
->nic_matcher
) {
574 ret
= dr_dump_rule_rx_tx(file
, buff
, tx
, false, rule_id
, format_ver
);
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
);
589 dr_dump_matcher_mask(struct seq_file
*file
, char *buff
,
590 struct mlx5dr_match_param
*mask
,
591 u8 criteria
, const u64 matcher_id
)
593 char dump
[DR_HEX_SIZE
];
596 ret
= snprintf(buff
, MLX5DR_DEBUG_DUMP_BUFF_LENGTH
, "%d,0x%llx,",
597 DR_DUMP_REC_TYPE_MATCHER_MASK
, matcher_id
);
601 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
,
610 ret
= snprintf(buff
, MLX5DR_DEBUG_DUMP_BUFF_LENGTH
, ",");
616 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
,
625 ret
= snprintf(buff
, MLX5DR_DEBUG_DUMP_BUFF_LENGTH
, ",");
631 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
,
640 ret
= snprintf(buff
, MLX5DR_DEBUG_DUMP_BUFF_LENGTH
, ",");
646 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
,
655 ret
= snprintf(buff
, MLX5DR_DEBUG_DUMP_BUFF_LENGTH
, ",");
661 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
,
670 ret
= snprintf(buff
, MLX5DR_DEBUG_DUMP_BUFF_LENGTH
, ",\n");
676 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
)
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
);
697 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
)
709 enum dr_dump_rec_type rec_type
;
710 u64 s_icm_addr
, e_icm_addr
;
713 rec_type
= is_rx
? DR_DUMP_REC_TYPE_MATCHER_RX
:
714 DR_DUMP_REC_TYPE_MATCHER_TX
;
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
));
728 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
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
);
743 static noinline_for_stack
int
744 dr_dump_matcher(struct seq_file
*file
, struct mlx5dr_matcher
*matcher
)
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
];
752 matcher_id
= DR_DBG_PTR_TO_ID(matcher
);
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
),
761 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
765 ret
= dr_dump_matcher_mask(file
, buff
, &matcher
->mask
,
766 matcher
->match_criteria
, matcher_id
);
771 ret
= dr_dump_matcher_rx_tx(file
, buff
, true, rx
, matcher_id
);
777 ret
= dr_dump_matcher_rx_tx(file
, buff
, false, tx
, matcher_id
);
786 dr_dump_matcher_all(struct seq_file
*file
, struct mlx5dr_matcher
*matcher
)
788 struct mlx5dr_rule
*rule
;
791 ret
= dr_dump_matcher(file
, matcher
);
795 list_for_each_entry(rule
, &matcher
->dbg_rule_list
, dbg_node
) {
796 ret
= dr_dump_rule(file
, rule
);
805 dr_dump_table_rx_tx(struct seq_file
*file
, char *buff
, bool is_rx
,
806 struct mlx5dr_table_rx_tx
*table_rx_tx
,
809 enum dr_dump_rec_type rec_type
;
813 rec_type
= is_rx
? DR_DUMP_REC_TYPE_TABLE_RX
:
814 DR_DUMP_REC_TYPE_TABLE_TX
;
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
));
823 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
830 static noinline_for_stack
int
831 dr_dump_table(struct seq_file
*file
, struct mlx5dr_table
*table
)
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
];
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
);
845 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
850 ret
= dr_dump_table_rx_tx(file
, buff
, true, rx
,
851 DR_DBG_PTR_TO_ID(table
));
857 ret
= dr_dump_table_rx_tx(file
, buff
, false, tx
,
858 DR_DBG_PTR_TO_ID(table
));
865 static int dr_dump_table_all(struct seq_file
*file
, struct mlx5dr_table
*tbl
)
867 struct mlx5dr_matcher
*matcher
;
870 ret
= dr_dump_table(file
, tbl
);
874 list_for_each_entry(matcher
, &tbl
->matcher_list
, list_node
) {
875 ret
= dr_dump_matcher_all(file
, matcher
);
883 dr_dump_send_ring(struct seq_file
*file
, char *buff
,
884 struct mlx5dr_send_ring
*ring
,
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
);
897 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
905 dr_dump_domain_info_flex_parser(struct seq_file
*file
,
907 const char *flex_parser_name
,
908 const u8 flex_parser_value
,
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
);
920 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
928 dr_dump_domain_info_caps(struct seq_file
*file
, char *buff
,
929 struct mlx5dr_cmd_caps
*caps
,
932 struct mlx5dr_cmd_vport_cap
*vport_caps
;
933 unsigned long i
, vports_num
;
936 xa_for_each(&caps
->vports
.vports_caps_xa
, vports_num
, vport_caps
)
937 ; /* count the number of vports in xarray */
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
);
947 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
951 xa_for_each(&caps
->vports
.vports_caps_xa
, i
, vport_caps
) {
952 vport_caps
= xa_load(&caps
->vports
.vports_caps_xa
, i
);
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
);
963 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
971 dr_dump_domain_info(struct seq_file
*file
, char *buff
,
972 struct mlx5dr_domain_info
*info
,
977 ret
= dr_dump_domain_info_caps(file
, buff
, &info
->caps
, domain_id
);
981 ret
= dr_dump_domain_info_flex_parser(file
, buff
, "icmp_dw0",
982 info
->caps
.flex_parser_id_icmp_dw0
,
987 ret
= dr_dump_domain_info_flex_parser(file
, buff
, "icmp_dw1",
988 info
->caps
.flex_parser_id_icmp_dw1
,
993 ret
= dr_dump_domain_info_flex_parser(file
, buff
, "icmpv6_dw0",
994 info
->caps
.flex_parser_id_icmpv6_dw0
,
999 ret
= dr_dump_domain_info_flex_parser(file
, buff
, "icmpv6_dw1",
1000 info
->caps
.flex_parser_id_icmpv6_dw1
,
1008 static noinline_for_stack
int
1009 dr_dump_domain(struct seq_file
*file
, struct mlx5dr_domain
*dmn
)
1011 char buff
[MLX5DR_DEBUG_DUMP_BUFF_LENGTH
];
1012 u64 domain_id
= DR_DBG_PTR_TO_ID(dmn
);
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
]);
1031 ret
= mlx5dr_dbg_dump_data_print(file
, buff
, ret
);
1035 ret
= dr_dump_domain_info(file
, buff
, &dmn
->info
, domain_id
);
1039 if (dmn
->info
.supp_sw_steering
) {
1040 ret
= dr_dump_send_ring(file
, buff
, dmn
->send_ring
, domain_id
);
1048 static int dr_dump_domain_all(struct seq_file
*file
, struct mlx5dr_domain
*dmn
)
1050 struct mlx5dr_table
*tbl
;
1053 mutex_lock(&dmn
->dump_info
.dbg_mutex
);
1054 mlx5dr_domain_lock(dmn
);
1056 ret
= dr_dump_domain(file
, dmn
);
1060 list_for_each_entry(tbl
, &dmn
->dbg_tbl_list
, dbg_node
) {
1061 ret
= dr_dump_table_all(file
, tbl
);
1067 mlx5dr_domain_unlock(dmn
);
1068 mutex_unlock(&dmn
->dump_info
.dbg_mutex
);
1073 dr_dump_start(struct seq_file
*file
, loff_t
*pos
)
1075 struct mlx5dr_domain
*dmn
= file
->private;
1076 struct mlx5dr_dbg_dump_data
*dump_data
;
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
);
1083 atomic_set(&dmn
->dump_info
.state
, MLX5DR_DEBUG_DUMP_STATE_IN_PROGRESS
);
1084 dump_data
= dmn
->dump_info
.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();
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
;
1100 return seq_list_start(&dump_data
->buff_list
, *pos
);
1104 atomic_set(&dmn
->dump_info
.state
, MLX5DR_DEBUG_DUMP_STATE_FREE
);
1109 dr_dump_next(struct seq_file
*file
, void *v
, loff_t
*pos
)
1111 struct mlx5dr_domain
*dmn
= file
->private;
1112 struct mlx5dr_dbg_dump_data
*dump_data
;
1114 dump_data
= dmn
->dump_info
.dump_data
;
1116 return seq_list_next(v
, &dump_data
->buff_list
, pos
);
1120 dr_dump_stop(struct seq_file
*file
, void *v
)
1122 struct mlx5dr_domain
*dmn
= file
->private;
1123 struct mlx5dr_dbg_dump_data
*dump_data
;
1129 dump_data
= dmn
->dump_info
.dump_data
;
1131 mlx5dr_dbg_destroy_dump_data(dump_data
);
1132 dmn
->dump_info
.dump_data
= NULL
;
1136 atomic_set(&dmn
->dump_info
.state
, MLX5DR_DEBUG_DUMP_STATE_FREE
);
1140 dr_dump_show(struct seq_file
*file
, void *v
)
1142 struct mlx5dr_dbg_dump_buff
*entry
;
1144 entry
= list_entry(v
, struct mlx5dr_dbg_dump_buff
, node
);
1145 seq_printf(file
, "%s", entry
->buff
);
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
,
1156 DEFINE_SEQ_ATTRIBUTE(dr_dump
);
1158 void mlx5dr_dbg_init_dump(struct mlx5dr_domain
*dmn
)
1160 struct mlx5_core_dev
*dev
= dmn
->mdev
;
1161 char file_name
[128];
1163 if (dmn
->type
!= MLX5DR_DOMAIN_TYPE_FDB
) {
1165 "Steering dump is not supported for NIC RX/TX domains\n");
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
);
1174 sprintf(file_name
, "dmn_%p", dmn
);
1175 debugfs_create_file(file_name
, 0444, dmn
->dump_info
.fdb_debugfs
,
1176 dmn
, &dr_dump_fops
);
1178 INIT_LIST_HEAD(&dmn
->dbg_tbl_list
);
1179 mutex_init(&dmn
->dump_info
.dbg_mutex
);
1182 void mlx5dr_dbg_uninit_dump(struct mlx5dr_domain
*dmn
)
1184 debugfs_remove_recursive(dmn
->dump_info
.steering_debugfs
);
1185 mutex_destroy(&dmn
->dump_info
.dbg_mutex
);