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