1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
4 #include <linux/debugfs.h>
5 #include <linux/kernel.h>
6 #include <linux/seq_file.h>
7 #include "dr_types.h"
8
9 #define DR_DBG_PTR_TO_ID(p) ((u64)(uintptr_t)(p) & 0xFFFFFFFFULL)
10
11 enum dr_dump_rec_type {
12 DR_DUMP_REC_TYPE_DOMAIN = 3000,
13 DR_DUMP_REC_TYPE_DOMAIN_INFO_FLEX_PARSER = 3001,
14 DR_DUMP_REC_TYPE_DOMAIN_INFO_DEV_ATTR = 3002,
15 DR_DUMP_REC_TYPE_DOMAIN_INFO_VPORT = 3003,
16 DR_DUMP_REC_TYPE_DOMAIN_INFO_CAPS = 3004,
17 DR_DUMP_REC_TYPE_DOMAIN_SEND_RING = 3005,
18
19 DR_DUMP_REC_TYPE_TABLE = 3100,
20 DR_DUMP_REC_TYPE_TABLE_RX = 3101,
21 DR_DUMP_REC_TYPE_TABLE_TX = 3102,
22
23 DR_DUMP_REC_TYPE_MATCHER = 3200,
24 DR_DUMP_REC_TYPE_MATCHER_MASK_DEPRECATED = 3201,
25 DR_DUMP_REC_TYPE_MATCHER_RX = 3202,
26 DR_DUMP_REC_TYPE_MATCHER_TX = 3203,
27 DR_DUMP_REC_TYPE_MATCHER_BUILDER = 3204,
28 DR_DUMP_REC_TYPE_MATCHER_MASK = 3205,
29
30 DR_DUMP_REC_TYPE_RULE = 3300,
31 DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V0 = 3301,
32 DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V0 = 3302,
33 DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V1 = 3303,
34 DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V1 = 3304,
35
36 DR_DUMP_REC_TYPE_ACTION_ENCAP_L2 = 3400,
37 DR_DUMP_REC_TYPE_ACTION_ENCAP_L3 = 3401,
38 DR_DUMP_REC_TYPE_ACTION_MODIFY_HDR = 3402,
39 DR_DUMP_REC_TYPE_ACTION_DROP = 3403,
40 DR_DUMP_REC_TYPE_ACTION_QP = 3404,
41 DR_DUMP_REC_TYPE_ACTION_FT = 3405,
42 DR_DUMP_REC_TYPE_ACTION_CTR = 3406,
43 DR_DUMP_REC_TYPE_ACTION_TAG = 3407,
44 DR_DUMP_REC_TYPE_ACTION_VPORT = 3408,
45 DR_DUMP_REC_TYPE_ACTION_DECAP_L2 = 3409,
46 DR_DUMP_REC_TYPE_ACTION_DECAP_L3 = 3410,
47 DR_DUMP_REC_TYPE_ACTION_DEVX_TIR = 3411,
48 DR_DUMP_REC_TYPE_ACTION_PUSH_VLAN = 3412,
49 DR_DUMP_REC_TYPE_ACTION_POP_VLAN = 3413,
50 DR_DUMP_REC_TYPE_ACTION_SAMPLER = 3415,
51 DR_DUMP_REC_TYPE_ACTION_INSERT_HDR = 3420,
52 DR_DUMP_REC_TYPE_ACTION_REMOVE_HDR = 3421
53 };
54
mlx5dr_dbg_tbl_add(struct mlx5dr_table * tbl)55 void mlx5dr_dbg_tbl_add(struct mlx5dr_table *tbl)
56 {
57 mutex_lock(&tbl->dmn->dump_info.dbg_mutex);
58 list_add_tail(&tbl->dbg_node, &tbl->dmn->dbg_tbl_list);
59 mutex_unlock(&tbl->dmn->dump_info.dbg_mutex);
60 }
61
mlx5dr_dbg_tbl_del(struct mlx5dr_table * tbl)62 void mlx5dr_dbg_tbl_del(struct mlx5dr_table *tbl)
63 {
64 mutex_lock(&tbl->dmn->dump_info.dbg_mutex);
65 list_del(&tbl->dbg_node);
66 mutex_unlock(&tbl->dmn->dump_info.dbg_mutex);
67 }
68
mlx5dr_dbg_rule_add(struct mlx5dr_rule * rule)69 void mlx5dr_dbg_rule_add(struct mlx5dr_rule *rule)
70 {
71 struct mlx5dr_domain *dmn = rule->matcher->tbl->dmn;
72
73 mutex_lock(&dmn->dump_info.dbg_mutex);
74 list_add_tail(&rule->dbg_node, &rule->matcher->dbg_rule_list);
75 mutex_unlock(&dmn->dump_info.dbg_mutex);
76 }
77
mlx5dr_dbg_rule_del(struct mlx5dr_rule * rule)78 void mlx5dr_dbg_rule_del(struct mlx5dr_rule *rule)
79 {
80 struct mlx5dr_domain *dmn = rule->matcher->tbl->dmn;
81
82 mutex_lock(&dmn->dump_info.dbg_mutex);
83 list_del(&rule->dbg_node);
84 mutex_unlock(&dmn->dump_info.dbg_mutex);
85 }
86
dr_dump_icm_to_idx(u64 icm_addr)87 static u64 dr_dump_icm_to_idx(u64 icm_addr)
88 {
89 return (icm_addr >> 6) & 0xffffffff;
90 }
91
92 #define DR_HEX_SIZE 256
93
94 static void
dr_dump_hex_print(char hex[DR_HEX_SIZE],char * src,u32 size)95 dr_dump_hex_print(char hex[DR_HEX_SIZE], char *src, u32 size)
96 {
97 if (WARN_ON_ONCE(DR_HEX_SIZE < 2 * size + 1))
98 size = DR_HEX_SIZE / 2 - 1; /* truncate */
99
100 bin2hex(hex, src, size);
101 hex[2 * size] = 0; /* NULL-terminate */
102 }
103
104 static int
dr_dump_rule_action_mem(struct seq_file * file,const u64 rule_id,struct mlx5dr_rule_action_member * action_mem)105 dr_dump_rule_action_mem(struct seq_file *file, const u64 rule_id,
106 struct mlx5dr_rule_action_member *action_mem)
107 {
108 struct mlx5dr_action *action = action_mem->action;
109 const u64 action_id = DR_DBG_PTR_TO_ID(action);
110
111 switch (action->action_type) {
112 case DR_ACTION_TYP_DROP:
113 seq_printf(file, "%d,0x%llx,0x%llx\n",
114 DR_DUMP_REC_TYPE_ACTION_DROP, action_id, rule_id);
115 break;
116 case DR_ACTION_TYP_FT:
117 if (action->dest_tbl->is_fw_tbl)
118 seq_printf(file, "%d,0x%llx,0x%llx,0x%x,0x%x\n",
119 DR_DUMP_REC_TYPE_ACTION_FT, action_id,
120 rule_id, action->dest_tbl->fw_tbl.id,
121 -1);
122 else
123 seq_printf(file, "%d,0x%llx,0x%llx,0x%x,0x%llx\n",
124 DR_DUMP_REC_TYPE_ACTION_FT, action_id,
125 rule_id, action->dest_tbl->tbl->table_id,
126 DR_DBG_PTR_TO_ID(action->dest_tbl->tbl));
127
128 break;
129 case DR_ACTION_TYP_CTR:
130 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n",
131 DR_DUMP_REC_TYPE_ACTION_CTR, action_id, rule_id,
132 action->ctr->ctr_id + action->ctr->offset);
133 break;
134 case DR_ACTION_TYP_TAG:
135 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n",
136 DR_DUMP_REC_TYPE_ACTION_TAG, action_id, rule_id,
137 action->flow_tag->flow_tag);
138 break;
139 case DR_ACTION_TYP_MODIFY_HDR:
140 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n",
141 DR_DUMP_REC_TYPE_ACTION_MODIFY_HDR, action_id,
142 rule_id, action->rewrite->index);
143 break;
144 case DR_ACTION_TYP_VPORT:
145 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n",
146 DR_DUMP_REC_TYPE_ACTION_VPORT, action_id, rule_id,
147 action->vport->caps->num);
148 break;
149 case DR_ACTION_TYP_TNL_L2_TO_L2:
150 seq_printf(file, "%d,0x%llx,0x%llx\n",
151 DR_DUMP_REC_TYPE_ACTION_DECAP_L2, action_id,
152 rule_id);
153 break;
154 case DR_ACTION_TYP_TNL_L3_TO_L2:
155 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n",
156 DR_DUMP_REC_TYPE_ACTION_DECAP_L3, action_id,
157 rule_id, action->rewrite->index);
158 break;
159 case DR_ACTION_TYP_L2_TO_TNL_L2:
160 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n",
161 DR_DUMP_REC_TYPE_ACTION_ENCAP_L2, action_id,
162 rule_id, action->reformat->id);
163 break;
164 case DR_ACTION_TYP_L2_TO_TNL_L3:
165 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n",
166 DR_DUMP_REC_TYPE_ACTION_ENCAP_L3, action_id,
167 rule_id, action->reformat->id);
168 break;
169 case DR_ACTION_TYP_POP_VLAN:
170 seq_printf(file, "%d,0x%llx,0x%llx\n",
171 DR_DUMP_REC_TYPE_ACTION_POP_VLAN, action_id,
172 rule_id);
173 break;
174 case DR_ACTION_TYP_PUSH_VLAN:
175 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n",
176 DR_DUMP_REC_TYPE_ACTION_PUSH_VLAN, action_id,
177 rule_id, action->push_vlan->vlan_hdr);
178 break;
179 case DR_ACTION_TYP_INSERT_HDR:
180 seq_printf(file, "%d,0x%llx,0x%llx,0x%x,0x%x,0x%x\n",
181 DR_DUMP_REC_TYPE_ACTION_INSERT_HDR, action_id,
182 rule_id, action->reformat->id,
183 action->reformat->param_0,
184 action->reformat->param_1);
185 break;
186 case DR_ACTION_TYP_REMOVE_HDR:
187 seq_printf(file, "%d,0x%llx,0x%llx,0x%x,0x%x,0x%x\n",
188 DR_DUMP_REC_TYPE_ACTION_REMOVE_HDR, action_id,
189 rule_id, action->reformat->id,
190 action->reformat->param_0,
191 action->reformat->param_1);
192 break;
193 case DR_ACTION_TYP_SAMPLER:
194 seq_printf(file,
195 "%d,0x%llx,0x%llx,0x%x,0x%x,0x%x,0x%llx,0x%llx\n",
196 DR_DUMP_REC_TYPE_ACTION_SAMPLER, action_id, rule_id,
197 0, 0, action->sampler->sampler_id,
198 action->sampler->rx_icm_addr,
199 action->sampler->tx_icm_addr);
200 break;
201 default:
202 return 0;
203 }
204
205 return 0;
206 }
207
208 static int
dr_dump_rule_mem(struct seq_file * file,struct mlx5dr_ste * ste,bool is_rx,const u64 rule_id,u8 format_ver)209 dr_dump_rule_mem(struct seq_file *file, struct mlx5dr_ste *ste,
210 bool is_rx, const u64 rule_id, u8 format_ver)
211 {
212 char hw_ste_dump[DR_HEX_SIZE];
213 u32 mem_rec_type;
214
215 if (format_ver == MLX5_STEERING_FORMAT_CONNECTX_5) {
216 mem_rec_type = is_rx ? DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V0 :
217 DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V0;
218 } else {
219 mem_rec_type = is_rx ? DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V1 :
220 DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V1;
221 }
222
223 dr_dump_hex_print(hw_ste_dump, (char *)mlx5dr_ste_get_hw_ste(ste),
224 DR_STE_SIZE_REDUCED);
225
226 seq_printf(file, "%d,0x%llx,0x%llx,%s\n", mem_rec_type,
227 dr_dump_icm_to_idx(mlx5dr_ste_get_icm_addr(ste)), rule_id,
228 hw_ste_dump);
229
230 return 0;
231 }
232
233 static int
dr_dump_rule_rx_tx(struct seq_file * file,struct mlx5dr_rule_rx_tx * rule_rx_tx,bool is_rx,const u64 rule_id,u8 format_ver)234 dr_dump_rule_rx_tx(struct seq_file *file, struct mlx5dr_rule_rx_tx *rule_rx_tx,
235 bool is_rx, const u64 rule_id, u8 format_ver)
236 {
237 struct mlx5dr_ste *ste_arr[DR_RULE_MAX_STES + DR_ACTION_MAX_STES];
238 struct mlx5dr_ste *curr_ste = rule_rx_tx->last_rule_ste;
239 int ret, i;
240
241 if (mlx5dr_rule_get_reverse_rule_members(ste_arr, curr_ste, &i))
242 return 0;
243
244 while (i--) {
245 ret = dr_dump_rule_mem(file, ste_arr[i], is_rx, rule_id,
246 format_ver);
247 if (ret < 0)
248 return ret;
249 }
250
251 return 0;
252 }
253
dr_dump_rule(struct seq_file * file,struct mlx5dr_rule * rule)254 static int dr_dump_rule(struct seq_file *file, struct mlx5dr_rule *rule)
255 {
256 struct mlx5dr_rule_action_member *action_mem;
257 const u64 rule_id = DR_DBG_PTR_TO_ID(rule);
258 struct mlx5dr_rule_rx_tx *rx = &rule->rx;
259 struct mlx5dr_rule_rx_tx *tx = &rule->tx;
260 u8 format_ver;
261 int ret;
262
263 format_ver = rule->matcher->tbl->dmn->info.caps.sw_format_ver;
264
265 seq_printf(file, "%d,0x%llx,0x%llx\n", DR_DUMP_REC_TYPE_RULE, rule_id,
266 DR_DBG_PTR_TO_ID(rule->matcher));
267
268 if (rx->nic_matcher) {
269 ret = dr_dump_rule_rx_tx(file, rx, true, rule_id, format_ver);
270 if (ret < 0)
271 return ret;
272 }
273
274 if (tx->nic_matcher) {
275 ret = dr_dump_rule_rx_tx(file, tx, false, rule_id, format_ver);
276 if (ret < 0)
277 return ret;
278 }
279
280 list_for_each_entry(action_mem, &rule->rule_actions_list, list) {
281 ret = dr_dump_rule_action_mem(file, rule_id, action_mem);
282 if (ret < 0)
283 return ret;
284 }
285
286 return 0;
287 }
288
289 static int
dr_dump_matcher_mask(struct seq_file * file,struct mlx5dr_match_param * mask,u8 criteria,const u64 matcher_id)290 dr_dump_matcher_mask(struct seq_file *file, struct mlx5dr_match_param *mask,
291 u8 criteria, const u64 matcher_id)
292 {
293 char dump[DR_HEX_SIZE];
294
295 seq_printf(file, "%d,0x%llx,", DR_DUMP_REC_TYPE_MATCHER_MASK,
296 matcher_id);
297
298 if (criteria & DR_MATCHER_CRITERIA_OUTER) {
299 dr_dump_hex_print(dump, (char *)&mask->outer, sizeof(mask->outer));
300 seq_printf(file, "%s,", dump);
301 } else {
302 seq_puts(file, ",");
303 }
304
305 if (criteria & DR_MATCHER_CRITERIA_INNER) {
306 dr_dump_hex_print(dump, (char *)&mask->inner, sizeof(mask->inner));
307 seq_printf(file, "%s,", dump);
308 } else {
309 seq_puts(file, ",");
310 }
311
312 if (criteria & DR_MATCHER_CRITERIA_MISC) {
313 dr_dump_hex_print(dump, (char *)&mask->misc, sizeof(mask->misc));
314 seq_printf(file, "%s,", dump);
315 } else {
316 seq_puts(file, ",");
317 }
318
319 if (criteria & DR_MATCHER_CRITERIA_MISC2) {
320 dr_dump_hex_print(dump, (char *)&mask->misc2, sizeof(mask->misc2));
321 seq_printf(file, "%s,", dump);
322 } else {
323 seq_puts(file, ",");
324 }
325
326 if (criteria & DR_MATCHER_CRITERIA_MISC3) {
327 dr_dump_hex_print(dump, (char *)&mask->misc3, sizeof(mask->misc3));
328 seq_printf(file, "%s\n", dump);
329 } else {
330 seq_puts(file, ",\n");
331 }
332
333 return 0;
334 }
335
336 static int
dr_dump_matcher_builder(struct seq_file * file,struct mlx5dr_ste_build * builder,u32 index,bool is_rx,const u64 matcher_id)337 dr_dump_matcher_builder(struct seq_file *file, struct mlx5dr_ste_build *builder,
338 u32 index, bool is_rx, const u64 matcher_id)
339 {
340 seq_printf(file, "%d,0x%llx,%d,%d,0x%x\n",
341 DR_DUMP_REC_TYPE_MATCHER_BUILDER, matcher_id, index, is_rx,
342 builder->lu_type);
343
344 return 0;
345 }
346
347 static int
dr_dump_matcher_rx_tx(struct seq_file * file,bool is_rx,struct mlx5dr_matcher_rx_tx * matcher_rx_tx,const u64 matcher_id)348 dr_dump_matcher_rx_tx(struct seq_file *file, bool is_rx,
349 struct mlx5dr_matcher_rx_tx *matcher_rx_tx,
350 const u64 matcher_id)
351 {
352 enum dr_dump_rec_type rec_type;
353 u64 s_icm_addr, e_icm_addr;
354 int i, ret;
355
356 rec_type = is_rx ? DR_DUMP_REC_TYPE_MATCHER_RX :
357 DR_DUMP_REC_TYPE_MATCHER_TX;
358
359 s_icm_addr = mlx5dr_icm_pool_get_chunk_icm_addr(matcher_rx_tx->s_htbl->chunk);
360 e_icm_addr = mlx5dr_icm_pool_get_chunk_icm_addr(matcher_rx_tx->e_anchor->chunk);
361 seq_printf(file, "%d,0x%llx,0x%llx,%d,0x%llx,0x%llx\n",
362 rec_type, DR_DBG_PTR_TO_ID(matcher_rx_tx),
363 matcher_id, matcher_rx_tx->num_of_builders,
364 dr_dump_icm_to_idx(s_icm_addr),
365 dr_dump_icm_to_idx(e_icm_addr));
366
367 for (i = 0; i < matcher_rx_tx->num_of_builders; i++) {
368 ret = dr_dump_matcher_builder(file,
369 &matcher_rx_tx->ste_builder[i],
370 i, is_rx, matcher_id);
371 if (ret < 0)
372 return ret;
373 }
374
375 return 0;
376 }
377
378 static int
dr_dump_matcher(struct seq_file * file,struct mlx5dr_matcher * matcher)379 dr_dump_matcher(struct seq_file *file, struct mlx5dr_matcher *matcher)
380 {
381 struct mlx5dr_matcher_rx_tx *rx = &matcher->rx;
382 struct mlx5dr_matcher_rx_tx *tx = &matcher->tx;
383 u64 matcher_id;
384 int ret;
385
386 matcher_id = DR_DBG_PTR_TO_ID(matcher);
387
388 seq_printf(file, "%d,0x%llx,0x%llx,%d\n", DR_DUMP_REC_TYPE_MATCHER,
389 matcher_id, DR_DBG_PTR_TO_ID(matcher->tbl), matcher->prio);
390
391 ret = dr_dump_matcher_mask(file, &matcher->mask,
392 matcher->match_criteria, matcher_id);
393 if (ret < 0)
394 return ret;
395
396 if (rx->nic_tbl) {
397 ret = dr_dump_matcher_rx_tx(file, true, rx, matcher_id);
398 if (ret < 0)
399 return ret;
400 }
401
402 if (tx->nic_tbl) {
403 ret = dr_dump_matcher_rx_tx(file, false, tx, matcher_id);
404 if (ret < 0)
405 return ret;
406 }
407
408 return 0;
409 }
410
411 static int
dr_dump_matcher_all(struct seq_file * file,struct mlx5dr_matcher * matcher)412 dr_dump_matcher_all(struct seq_file *file, struct mlx5dr_matcher *matcher)
413 {
414 struct mlx5dr_rule *rule;
415 int ret;
416
417 ret = dr_dump_matcher(file, matcher);
418 if (ret < 0)
419 return ret;
420
421 list_for_each_entry(rule, &matcher->dbg_rule_list, dbg_node) {
422 ret = dr_dump_rule(file, rule);
423 if (ret < 0)
424 return ret;
425 }
426
427 return 0;
428 }
429
430 static int
dr_dump_table_rx_tx(struct seq_file * file,bool is_rx,struct mlx5dr_table_rx_tx * table_rx_tx,const u64 table_id)431 dr_dump_table_rx_tx(struct seq_file *file, bool is_rx,
432 struct mlx5dr_table_rx_tx *table_rx_tx,
433 const u64 table_id)
434 {
435 enum dr_dump_rec_type rec_type;
436 u64 s_icm_addr;
437
438 rec_type = is_rx ? DR_DUMP_REC_TYPE_TABLE_RX :
439 DR_DUMP_REC_TYPE_TABLE_TX;
440
441 s_icm_addr = mlx5dr_icm_pool_get_chunk_icm_addr(table_rx_tx->s_anchor->chunk);
442 seq_printf(file, "%d,0x%llx,0x%llx\n", rec_type, table_id,
443 dr_dump_icm_to_idx(s_icm_addr));
444
445 return 0;
446 }
447
dr_dump_table(struct seq_file * file,struct mlx5dr_table * table)448 static int dr_dump_table(struct seq_file *file, struct mlx5dr_table *table)
449 {
450 struct mlx5dr_table_rx_tx *rx = &table->rx;
451 struct mlx5dr_table_rx_tx *tx = &table->tx;
452 int ret;
453
454 seq_printf(file, "%d,0x%llx,0x%llx,%d,%d\n", DR_DUMP_REC_TYPE_TABLE,
455 DR_DBG_PTR_TO_ID(table), DR_DBG_PTR_TO_ID(table->dmn),
456 table->table_type, table->level);
457
458 if (rx->nic_dmn) {
459 ret = dr_dump_table_rx_tx(file, true, rx,
460 DR_DBG_PTR_TO_ID(table));
461 if (ret < 0)
462 return ret;
463 }
464
465 if (tx->nic_dmn) {
466 ret = dr_dump_table_rx_tx(file, false, tx,
467 DR_DBG_PTR_TO_ID(table));
468 if (ret < 0)
469 return ret;
470 }
471 return 0;
472 }
473
dr_dump_table_all(struct seq_file * file,struct mlx5dr_table * tbl)474 static int dr_dump_table_all(struct seq_file *file, struct mlx5dr_table *tbl)
475 {
476 struct mlx5dr_matcher *matcher;
477 int ret;
478
479 ret = dr_dump_table(file, tbl);
480 if (ret < 0)
481 return ret;
482
483 list_for_each_entry(matcher, &tbl->matcher_list, list_node) {
484 ret = dr_dump_matcher_all(file, matcher);
485 if (ret < 0)
486 return ret;
487 }
488 return 0;
489 }
490
491 static int
dr_dump_send_ring(struct seq_file * file,struct mlx5dr_send_ring * ring,const u64 domain_id)492 dr_dump_send_ring(struct seq_file *file, struct mlx5dr_send_ring *ring,
493 const u64 domain_id)
494 {
495 seq_printf(file, "%d,0x%llx,0x%llx,0x%x,0x%x\n",
496 DR_DUMP_REC_TYPE_DOMAIN_SEND_RING, DR_DBG_PTR_TO_ID(ring),
497 domain_id, ring->cq->mcq.cqn, ring->qp->qpn);
498 return 0;
499 }
500
501 static int
dr_dump_domain_info_flex_parser(struct seq_file * file,const char * flex_parser_name,const u8 flex_parser_value,const u64 domain_id)502 dr_dump_domain_info_flex_parser(struct seq_file *file,
503 const char *flex_parser_name,
504 const u8 flex_parser_value,
505 const u64 domain_id)
506 {
507 seq_printf(file, "%d,0x%llx,%s,0x%x\n",
508 DR_DUMP_REC_TYPE_DOMAIN_INFO_FLEX_PARSER, domain_id,
509 flex_parser_name, flex_parser_value);
510 return 0;
511 }
512
513 static int
dr_dump_domain_info_caps(struct seq_file * file,struct mlx5dr_cmd_caps * caps,const u64 domain_id)514 dr_dump_domain_info_caps(struct seq_file *file, struct mlx5dr_cmd_caps *caps,
515 const u64 domain_id)
516 {
517 struct mlx5dr_cmd_vport_cap *vport_caps;
518 unsigned long i, vports_num;
519
520 xa_for_each(&caps->vports.vports_caps_xa, vports_num, vport_caps)
521 ; /* count the number of vports in xarray */
522
523 seq_printf(file, "%d,0x%llx,0x%x,0x%llx,0x%llx,0x%x,%lu,%d\n",
524 DR_DUMP_REC_TYPE_DOMAIN_INFO_CAPS, domain_id, caps->gvmi,
525 caps->nic_rx_drop_address, caps->nic_tx_drop_address,
526 caps->flex_protocols, vports_num, caps->eswitch_manager);
527
528 xa_for_each(&caps->vports.vports_caps_xa, i, vport_caps) {
529 vport_caps = xa_load(&caps->vports.vports_caps_xa, i);
530
531 seq_printf(file, "%d,0x%llx,%lu,0x%x,0x%llx,0x%llx\n",
532 DR_DUMP_REC_TYPE_DOMAIN_INFO_VPORT, domain_id, i,
533 vport_caps->vport_gvmi, vport_caps->icm_address_rx,
534 vport_caps->icm_address_tx);
535 }
536 return 0;
537 }
538
539 static int
dr_dump_domain_info(struct seq_file * file,struct mlx5dr_domain_info * info,const u64 domain_id)540 dr_dump_domain_info(struct seq_file *file, struct mlx5dr_domain_info *info,
541 const u64 domain_id)
542 {
543 int ret;
544
545 ret = dr_dump_domain_info_caps(file, &info->caps, domain_id);
546 if (ret < 0)
547 return ret;
548
549 ret = dr_dump_domain_info_flex_parser(file, "icmp_dw0",
550 info->caps.flex_parser_id_icmp_dw0,
551 domain_id);
552 if (ret < 0)
553 return ret;
554
555 ret = dr_dump_domain_info_flex_parser(file, "icmp_dw1",
556 info->caps.flex_parser_id_icmp_dw1,
557 domain_id);
558 if (ret < 0)
559 return ret;
560
561 ret = dr_dump_domain_info_flex_parser(file, "icmpv6_dw0",
562 info->caps.flex_parser_id_icmpv6_dw0,
563 domain_id);
564 if (ret < 0)
565 return ret;
566
567 ret = dr_dump_domain_info_flex_parser(file, "icmpv6_dw1",
568 info->caps.flex_parser_id_icmpv6_dw1,
569 domain_id);
570 if (ret < 0)
571 return ret;
572
573 return 0;
574 }
575
576 static int
dr_dump_domain(struct seq_file * file,struct mlx5dr_domain * dmn)577 dr_dump_domain(struct seq_file *file, struct mlx5dr_domain *dmn)
578 {
579 u64 domain_id = DR_DBG_PTR_TO_ID(dmn);
580 int ret;
581
582 seq_printf(file, "%d,0x%llx,%d,0%x,%d,%s\n", DR_DUMP_REC_TYPE_DOMAIN,
583 domain_id, dmn->type, dmn->info.caps.gvmi,
584 dmn->info.supp_sw_steering, pci_name(dmn->mdev->pdev));
585
586 ret = dr_dump_domain_info(file, &dmn->info, domain_id);
587 if (ret < 0)
588 return ret;
589
590 if (dmn->info.supp_sw_steering) {
591 ret = dr_dump_send_ring(file, dmn->send_ring, domain_id);
592 if (ret < 0)
593 return ret;
594 }
595
596 return 0;
597 }
598
dr_dump_domain_all(struct seq_file * file,struct mlx5dr_domain * dmn)599 static int dr_dump_domain_all(struct seq_file *file, struct mlx5dr_domain *dmn)
600 {
601 struct mlx5dr_table *tbl;
602 int ret;
603
604 mutex_lock(&dmn->dump_info.dbg_mutex);
605 mlx5dr_domain_lock(dmn);
606
607 ret = dr_dump_domain(file, dmn);
608 if (ret < 0)
609 goto unlock_mutex;
610
611 list_for_each_entry(tbl, &dmn->dbg_tbl_list, dbg_node) {
612 ret = dr_dump_table_all(file, tbl);
613 if (ret < 0)
614 break;
615 }
616
617 unlock_mutex:
618 mlx5dr_domain_unlock(dmn);
619 mutex_unlock(&dmn->dump_info.dbg_mutex);
620 return ret;
621 }
622
dr_dump_show(struct seq_file * file,void * priv)623 static int dr_dump_show(struct seq_file *file, void *priv)
624 {
625 return dr_dump_domain_all(file, file->private);
626 }
627 DEFINE_SHOW_ATTRIBUTE(dr_dump);
628
mlx5dr_dbg_init_dump(struct mlx5dr_domain * dmn)629 void mlx5dr_dbg_init_dump(struct mlx5dr_domain *dmn)
630 {
631 struct mlx5_core_dev *dev = dmn->mdev;
632 char file_name[128];
633
634 if (dmn->type != MLX5DR_DOMAIN_TYPE_FDB) {
635 mlx5_core_warn(dev,
636 "Steering dump is not supported for NIC RX/TX domains\n");
637 return;
638 }
639
640 dmn->dump_info.steering_debugfs =
641 debugfs_create_dir("steering", mlx5_debugfs_get_dev_root(dev));
642 dmn->dump_info.fdb_debugfs =
643 debugfs_create_dir("fdb", dmn->dump_info.steering_debugfs);
644
645 sprintf(file_name, "dmn_%p", dmn);
646 debugfs_create_file(file_name, 0444, dmn->dump_info.fdb_debugfs,
647 dmn, &dr_dump_fops);
648
649 INIT_LIST_HEAD(&dmn->dbg_tbl_list);
650 mutex_init(&dmn->dump_info.dbg_mutex);
651 }
652
mlx5dr_dbg_uninit_dump(struct mlx5dr_domain * dmn)653 void mlx5dr_dbg_uninit_dump(struct mlx5dr_domain *dmn)
654 {
655 debugfs_remove_recursive(dmn->dump_info.steering_debugfs);
656 mutex_destroy(&dmn->dump_info.dbg_mutex);
657 }
658