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/module.h> 7 #include <linux/seq_file.h> 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, 25 DR_DUMP_REC_TYPE_MATCHER_MASK = 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 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 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 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 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 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 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 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 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\n", 119 DR_DUMP_REC_TYPE_ACTION_FT, action_id, 120 rule_id, action->dest_tbl->fw_tbl.id); 121 else 122 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n", 123 DR_DUMP_REC_TYPE_ACTION_FT, action_id, 124 rule_id, action->dest_tbl->tbl->table_id); 125 126 break; 127 case DR_ACTION_TYP_CTR: 128 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n", 129 DR_DUMP_REC_TYPE_ACTION_CTR, action_id, rule_id, 130 action->ctr->ctr_id + action->ctr->offset); 131 break; 132 case DR_ACTION_TYP_TAG: 133 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n", 134 DR_DUMP_REC_TYPE_ACTION_TAG, action_id, rule_id, 135 action->flow_tag->flow_tag); 136 break; 137 case DR_ACTION_TYP_MODIFY_HDR: 138 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n", 139 DR_DUMP_REC_TYPE_ACTION_MODIFY_HDR, action_id, 140 rule_id, action->rewrite->index); 141 break; 142 case DR_ACTION_TYP_VPORT: 143 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n", 144 DR_DUMP_REC_TYPE_ACTION_VPORT, action_id, rule_id, 145 action->vport->caps->num); 146 break; 147 case DR_ACTION_TYP_TNL_L2_TO_L2: 148 seq_printf(file, "%d,0x%llx,0x%llx\n", 149 DR_DUMP_REC_TYPE_ACTION_DECAP_L2, action_id, 150 rule_id); 151 break; 152 case DR_ACTION_TYP_TNL_L3_TO_L2: 153 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n", 154 DR_DUMP_REC_TYPE_ACTION_DECAP_L3, action_id, 155 rule_id, action->rewrite->index); 156 break; 157 case DR_ACTION_TYP_L2_TO_TNL_L2: 158 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n", 159 DR_DUMP_REC_TYPE_ACTION_ENCAP_L2, action_id, 160 rule_id, action->reformat->id); 161 break; 162 case DR_ACTION_TYP_L2_TO_TNL_L3: 163 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n", 164 DR_DUMP_REC_TYPE_ACTION_ENCAP_L3, action_id, 165 rule_id, action->reformat->id); 166 break; 167 case DR_ACTION_TYP_POP_VLAN: 168 seq_printf(file, "%d,0x%llx,0x%llx\n", 169 DR_DUMP_REC_TYPE_ACTION_POP_VLAN, action_id, 170 rule_id); 171 break; 172 case DR_ACTION_TYP_PUSH_VLAN: 173 seq_printf(file, "%d,0x%llx,0x%llx,0x%x\n", 174 DR_DUMP_REC_TYPE_ACTION_PUSH_VLAN, action_id, 175 rule_id, action->push_vlan->vlan_hdr); 176 break; 177 case DR_ACTION_TYP_INSERT_HDR: 178 seq_printf(file, "%d,0x%llx,0x%llx,0x%x,0x%x,0x%x\n", 179 DR_DUMP_REC_TYPE_ACTION_INSERT_HDR, action_id, 180 rule_id, action->reformat->id, 181 action->reformat->param_0, 182 action->reformat->param_1); 183 break; 184 case DR_ACTION_TYP_REMOVE_HDR: 185 seq_printf(file, "%d,0x%llx,0x%llx,0x%x,0x%x,0x%x\n", 186 DR_DUMP_REC_TYPE_ACTION_REMOVE_HDR, action_id, 187 rule_id, action->reformat->id, 188 action->reformat->param_0, 189 action->reformat->param_1); 190 break; 191 case DR_ACTION_TYP_SAMPLER: 192 seq_printf(file, 193 "%d,0x%llx,0x%llx,0x%x,0x%x,0x%x,0x%llx,0x%llx\n", 194 DR_DUMP_REC_TYPE_ACTION_SAMPLER, action_id, rule_id, 195 0, 0, action->sampler->sampler_id, 196 action->sampler->rx_icm_addr, 197 action->sampler->tx_icm_addr); 198 break; 199 default: 200 return 0; 201 } 202 203 return 0; 204 } 205 206 static int 207 dr_dump_rule_mem(struct seq_file *file, struct mlx5dr_ste *ste, 208 bool is_rx, const u64 rule_id, u8 format_ver) 209 { 210 char hw_ste_dump[DR_HEX_SIZE]; 211 u32 mem_rec_type; 212 213 if (format_ver == MLX5_STEERING_FORMAT_CONNECTX_5) { 214 mem_rec_type = is_rx ? DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V0 : 215 DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V0; 216 } else { 217 mem_rec_type = is_rx ? DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V1 : 218 DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V1; 219 } 220 221 dr_dump_hex_print(hw_ste_dump, (char *)ste->hw_ste, 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 int i, ret; 351 352 rec_type = is_rx ? DR_DUMP_REC_TYPE_MATCHER_RX : 353 DR_DUMP_REC_TYPE_MATCHER_TX; 354 355 seq_printf(file, "%d,0x%llx,0x%llx,%d,0x%llx,0x%llx\n", 356 rec_type, DR_DBG_PTR_TO_ID(matcher_rx_tx), 357 matcher_id, matcher_rx_tx->num_of_builders, 358 dr_dump_icm_to_idx(matcher_rx_tx->s_htbl->chunk->icm_addr), 359 dr_dump_icm_to_idx(matcher_rx_tx->e_anchor->chunk->icm_addr)); 360 361 for (i = 0; i < matcher_rx_tx->num_of_builders; i++) { 362 ret = dr_dump_matcher_builder(file, 363 &matcher_rx_tx->ste_builder[i], 364 i, is_rx, matcher_id); 365 if (ret < 0) 366 return ret; 367 } 368 369 return 0; 370 } 371 372 static int 373 dr_dump_matcher(struct seq_file *file, struct mlx5dr_matcher *matcher) 374 { 375 struct mlx5dr_matcher_rx_tx *rx = &matcher->rx; 376 struct mlx5dr_matcher_rx_tx *tx = &matcher->tx; 377 u64 matcher_id; 378 int ret; 379 380 matcher_id = DR_DBG_PTR_TO_ID(matcher); 381 382 seq_printf(file, "%d,0x%llx,0x%llx,%d\n", DR_DUMP_REC_TYPE_MATCHER, 383 matcher_id, DR_DBG_PTR_TO_ID(matcher->tbl), matcher->prio); 384 385 ret = dr_dump_matcher_mask(file, &matcher->mask, 386 matcher->match_criteria, matcher_id); 387 if (ret < 0) 388 return ret; 389 390 if (rx->nic_tbl) { 391 ret = dr_dump_matcher_rx_tx(file, true, rx, matcher_id); 392 if (ret < 0) 393 return ret; 394 } 395 396 if (tx->nic_tbl) { 397 ret = dr_dump_matcher_rx_tx(file, false, tx, matcher_id); 398 if (ret < 0) 399 return ret; 400 } 401 402 return 0; 403 } 404 405 static int 406 dr_dump_matcher_all(struct seq_file *file, struct mlx5dr_matcher *matcher) 407 { 408 struct mlx5dr_rule *rule; 409 int ret; 410 411 ret = dr_dump_matcher(file, matcher); 412 if (ret < 0) 413 return ret; 414 415 list_for_each_entry(rule, &matcher->dbg_rule_list, dbg_node) { 416 ret = dr_dump_rule(file, rule); 417 if (ret < 0) 418 return ret; 419 } 420 421 return 0; 422 } 423 424 static int 425 dr_dump_table_rx_tx(struct seq_file *file, bool is_rx, 426 struct mlx5dr_table_rx_tx *table_rx_tx, 427 const u64 table_id) 428 { 429 enum dr_dump_rec_type rec_type; 430 431 rec_type = is_rx ? DR_DUMP_REC_TYPE_TABLE_RX : 432 DR_DUMP_REC_TYPE_TABLE_TX; 433 434 seq_printf(file, "%d,0x%llx,0x%llx\n", rec_type, table_id, 435 dr_dump_icm_to_idx(table_rx_tx->s_anchor->chunk->icm_addr)); 436 437 return 0; 438 } 439 440 static int dr_dump_table(struct seq_file *file, struct mlx5dr_table *table) 441 { 442 struct mlx5dr_table_rx_tx *rx = &table->rx; 443 struct mlx5dr_table_rx_tx *tx = &table->tx; 444 int ret; 445 446 seq_printf(file, "%d,0x%llx,0x%llx,%d,%d\n", DR_DUMP_REC_TYPE_TABLE, 447 DR_DBG_PTR_TO_ID(table), DR_DBG_PTR_TO_ID(table->dmn), 448 table->table_type, table->level); 449 450 if (rx->nic_dmn) { 451 ret = dr_dump_table_rx_tx(file, true, rx, 452 DR_DBG_PTR_TO_ID(table)); 453 if (ret < 0) 454 return ret; 455 } 456 457 if (tx->nic_dmn) { 458 ret = dr_dump_table_rx_tx(file, false, tx, 459 DR_DBG_PTR_TO_ID(table)); 460 if (ret < 0) 461 return ret; 462 } 463 return 0; 464 } 465 466 static int dr_dump_table_all(struct seq_file *file, struct mlx5dr_table *tbl) 467 { 468 struct mlx5dr_matcher *matcher; 469 int ret; 470 471 ret = dr_dump_table(file, tbl); 472 if (ret < 0) 473 return ret; 474 475 list_for_each_entry(matcher, &tbl->matcher_list, list_node) { 476 ret = dr_dump_matcher_all(file, matcher); 477 if (ret < 0) 478 return ret; 479 } 480 return 0; 481 } 482 483 static int 484 dr_dump_send_ring(struct seq_file *file, struct mlx5dr_send_ring *ring, 485 const u64 domain_id) 486 { 487 seq_printf(file, "%d,0x%llx,0x%llx,0x%x,0x%x\n", 488 DR_DUMP_REC_TYPE_DOMAIN_SEND_RING, DR_DBG_PTR_TO_ID(ring), 489 domain_id, ring->cq->mcq.cqn, ring->qp->qpn); 490 return 0; 491 } 492 493 static int 494 dr_dump_domain_info_flex_parser(struct seq_file *file, 495 const char *flex_parser_name, 496 const u8 flex_parser_value, 497 const u64 domain_id) 498 { 499 seq_printf(file, "%d,0x%llx,%s,0x%x\n", 500 DR_DUMP_REC_TYPE_DOMAIN_INFO_FLEX_PARSER, domain_id, 501 flex_parser_name, flex_parser_value); 502 return 0; 503 } 504 505 static int 506 dr_dump_domain_info_caps(struct seq_file *file, struct mlx5dr_cmd_caps *caps, 507 const u64 domain_id) 508 { 509 struct mlx5dr_cmd_vport_cap *vport_caps; 510 unsigned long i, vports_num; 511 512 xa_for_each(&caps->vports.vports_caps_xa, vports_num, vport_caps) 513 ; /* count the number of vports in xarray */ 514 515 seq_printf(file, "%d,0x%llx,0x%x,0x%llx,0x%llx,0x%x,%lu,%d\n", 516 DR_DUMP_REC_TYPE_DOMAIN_INFO_CAPS, domain_id, caps->gvmi, 517 caps->nic_rx_drop_address, caps->nic_tx_drop_address, 518 caps->flex_protocols, vports_num, caps->eswitch_manager); 519 520 xa_for_each(&caps->vports.vports_caps_xa, i, vport_caps) { 521 vport_caps = xa_load(&caps->vports.vports_caps_xa, i); 522 523 seq_printf(file, "%d,0x%llx,%lu,0x%x,0x%llx,0x%llx\n", 524 DR_DUMP_REC_TYPE_DOMAIN_INFO_VPORT, domain_id, i, 525 vport_caps->vport_gvmi, vport_caps->icm_address_rx, 526 vport_caps->icm_address_tx); 527 } 528 return 0; 529 } 530 531 static int 532 dr_dump_domain_info(struct seq_file *file, struct mlx5dr_domain_info *info, 533 const u64 domain_id) 534 { 535 int ret; 536 537 ret = dr_dump_domain_info_caps(file, &info->caps, domain_id); 538 if (ret < 0) 539 return ret; 540 541 ret = dr_dump_domain_info_flex_parser(file, "icmp_dw0", 542 info->caps.flex_parser_id_icmp_dw0, 543 domain_id); 544 if (ret < 0) 545 return ret; 546 547 ret = dr_dump_domain_info_flex_parser(file, "icmp_dw1", 548 info->caps.flex_parser_id_icmp_dw1, 549 domain_id); 550 if (ret < 0) 551 return ret; 552 553 ret = dr_dump_domain_info_flex_parser(file, "icmpv6_dw0", 554 info->caps.flex_parser_id_icmpv6_dw0, 555 domain_id); 556 if (ret < 0) 557 return ret; 558 559 ret = dr_dump_domain_info_flex_parser(file, "icmpv6_dw1", 560 info->caps.flex_parser_id_icmpv6_dw1, 561 domain_id); 562 if (ret < 0) 563 return ret; 564 565 return 0; 566 } 567 568 static int 569 dr_dump_domain(struct seq_file *file, struct mlx5dr_domain *dmn) 570 { 571 u64 domain_id = DR_DBG_PTR_TO_ID(dmn); 572 int ret; 573 574 seq_printf(file, "%d,0x%llx,%d,0%x,%d,%s\n", DR_DUMP_REC_TYPE_DOMAIN, 575 domain_id, dmn->type, dmn->info.caps.gvmi, 576 dmn->info.supp_sw_steering, pci_name(dmn->mdev->pdev)); 577 578 ret = dr_dump_domain_info(file, &dmn->info, domain_id); 579 if (ret < 0) 580 return ret; 581 582 if (dmn->info.supp_sw_steering) { 583 ret = dr_dump_send_ring(file, dmn->send_ring, domain_id); 584 if (ret < 0) 585 return ret; 586 } 587 588 return 0; 589 } 590 591 static int dr_dump_domain_all(struct seq_file *file, struct mlx5dr_domain *dmn) 592 { 593 struct mlx5dr_table *tbl; 594 int ret; 595 596 mutex_lock(&dmn->dump_info.dbg_mutex); 597 mlx5dr_domain_lock(dmn); 598 599 ret = dr_dump_domain(file, dmn); 600 if (ret < 0) 601 goto unlock_mutex; 602 603 list_for_each_entry(tbl, &dmn->dbg_tbl_list, dbg_node) { 604 ret = dr_dump_table_all(file, tbl); 605 if (ret < 0) 606 break; 607 } 608 609 unlock_mutex: 610 mlx5dr_domain_unlock(dmn); 611 mutex_unlock(&dmn->dump_info.dbg_mutex); 612 return ret; 613 } 614 615 static int dr_dump_show(struct seq_file *file, void *priv) 616 { 617 return dr_dump_domain_all(file, file->private); 618 } 619 DEFINE_SHOW_ATTRIBUTE(dr_dump); 620 621 void mlx5dr_dbg_init_dump(struct mlx5dr_domain *dmn) 622 { 623 struct mlx5_core_dev *dev = dmn->mdev; 624 char file_name[128]; 625 626 if (dmn->type != MLX5DR_DOMAIN_TYPE_FDB) { 627 mlx5_core_warn(dev, 628 "Steering dump is not supported for NIC RX/TX domains\n"); 629 return; 630 } 631 632 dmn->dump_info.steering_debugfs = 633 debugfs_create_dir("steering", dev->priv.dbg_root); 634 dmn->dump_info.fdb_debugfs = 635 debugfs_create_dir("fdb", dmn->dump_info.steering_debugfs); 636 637 sprintf(file_name, "dmn_%p", dmn); 638 debugfs_create_file(file_name, 0444, dmn->dump_info.fdb_debugfs, 639 dmn, &dr_dump_fops); 640 641 INIT_LIST_HEAD(&dmn->dbg_tbl_list); 642 mutex_init(&dmn->dump_info.dbg_mutex); 643 } 644 645 void mlx5dr_dbg_uninit_dump(struct mlx5dr_domain *dmn) 646 { 647 debugfs_remove_recursive(dmn->dump_info.steering_debugfs); 648 mutex_destroy(&dmn->dump_info.dbg_mutex); 649 } 650