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