FILE
matcher.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */ 3 4#include "internal.h" 5 6static bool hws_matcher_requires_col_tbl(u8 log_num_of_rules) 7{ 8 /* Collision table concatenation is done only for large rule tables */ 9 return log_num_of_rules > MLX5HWS_MATCHER_ASSURED_RULES_TH; 10} 11 12static u8 hws_matcher_rules_to_tbl_depth(u8 log_num_of_rules) 13{ 14 if (hws_matcher_requires_col_tbl(log_num_of_rules)) 15 return MLX5HWS_MATCHER_ASSURED_MAIN_TBL_DEPTH; 16 17 /* For small rule tables we use a single deep table to assure insertion */ 18 return min(log_num_of_rules, MLX5HWS_MATCHER_ASSURED_COL_TBL_DEPTH); 19} 20 21static void hws_matcher_destroy_end_ft(struct mlx5hws_matcher *matcher) 22{ 23 mlx5hws_table_destroy_default_ft(matcher->tbl, matcher->end_ft_id); 24} 25 26int mlx5hws_matcher_update_end_ft_isolated(struct mlx5hws_table *tbl, 27 u32 miss_ft_id) 28{ 29 struct mlx5hws_matcher *tmp_matcher; 30 31 if (list_empty(&tbl->matchers_list)) 32 return -EINVAL; 33 34 /* Update isolated_matcher_end_ft_id attribute for all 35 * the matchers in isolated table. 36 */ 37 list_for_each_entry(tmp_matcher, &tbl->matchers_list, list_node) 38 tmp_matcher->attr.isolated_matcher_end_ft_id = miss_ft_id; 39 40 tmp_matcher = list_last_entry(&tbl->matchers_list, 41 struct mlx5hws_matcher, 42 list_node); 43 44 return mlx5hws_table_ft_set_next_ft(tbl->ctx, 45 tmp_matcher->end_ft_id, 46 tbl->fw_ft_type, 47 miss_ft_id); 48} 49 50static int hws_matcher_connect_end_ft_isolated(struct mlx5hws_matcher *matcher) 51{ 52 struct mlx5hws_table *tbl = matcher->tbl; 53 u32 end_ft_id; 54 int ret; 55 56 /* Reset end_ft next RTCs */ 57 ret = mlx5hws_table_ft_set_next_rtc(tbl->ctx, 58 matcher->end_ft_id, 59 matcher->tbl->fw_ft_type, 60 0, 0); 61 if (ret) { 62 mlx5hws_err(tbl->ctx, "Isolated matcher: failed to reset FT's next RTCs\n"); 63 return ret; 64 } 65 66 /* Connect isolated matcher's end_ft to the complex matcher's end FT */ 67 end_ft_id = matcher->attr.isolated_matcher_end_ft_id; 68 ret = mlx5hws_table_ft_set_next_ft(tbl->ctx, 69 matcher->end_ft_id, 70 matcher->tbl->fw_ft_type, 71 end_ft_id); 72 73 if (ret) { 74 mlx5hws_err(tbl->ctx, "Isolated matcher: failed to set FT's miss_ft_id\n"); 75 return ret; 76 } 77 78 return 0; 79} 80 81static int hws_matcher_create_end_ft_isolated(struct mlx5hws_matcher *matcher) 82{ 83 struct mlx5hws_table *tbl = matcher->tbl; 84 int ret; 85 86 ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, 87 tbl, 88 0, 89 &matcher->end_ft_id); 90 if (ret) { 91 mlx5hws_err(tbl->ctx, "Isolated matcher: failed to create end flow table\n"); 92 return ret; 93 } 94 95 ret = hws_matcher_connect_end_ft_isolated(matcher); 96 if (ret) { 97 mlx5hws_err(tbl->ctx, "Isolated matcher: failed to connect end FT\n"); 98 goto destroy_default_ft; 99 } 100 101 return 0; 102 103destroy_default_ft: 104 mlx5hws_table_destroy_default_ft(tbl, matcher->end_ft_id); 105 return ret; 106} 107 108static int hws_matcher_create_end_ft(struct mlx5hws_matcher *matcher) 109{ 110 struct mlx5hws_table *tbl = matcher->tbl; 111 int ret; 112 113 if (mlx5hws_matcher_is_isolated(matcher)) 114 ret = hws_matcher_create_end_ft_isolated(matcher); 115 else 116 ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, 117 tbl, 118 0, 119 &matcher->end_ft_id); 120 121 if (ret) { 122 mlx5hws_err(tbl->ctx, "Failed to create matcher end flow table\n"); 123 return ret; 124 } 125 126 return 0; 127} 128 129static int hws_matcher_connect_isolated_first(struct mlx5hws_matcher *matcher) 130{ 131 struct mlx5hws_table *tbl = matcher->tbl; 132 struct mlx5hws_context *ctx = tbl->ctx; 133 int ret; 134 135 /* Isolated matcher's end_ft is already pointing to the end_ft 136 * of the complex matcher - it was set at creation of end_ft, 137 * so no need to connect it. 138 * We still need to connect the isolated table's start FT to 139 * this matcher's RTC. 140 */ 141 ret = mlx5hws_table_ft_set_next_rtc(ctx, 142 tbl->ft_id, 143 tbl->fw_ft_type, 144 matcher->match_ste.rtc_0_id, 145 matcher->match_ste.rtc_1_id); 146 if (ret) { 147 mlx5hws_err(ctx, "Isolated matcher: failed to connect start FT to match RTC\n"); 148 return ret; 149 } 150 151 /* Reset table's FT default miss (drop refcount) */ 152 ret = mlx5hws_table_ft_set_default_next_ft(tbl, tbl->ft_id); 153 if (ret) { 154 mlx5hws_err(ctx, "Isolated matcher: failed to reset table ft default miss\n"); 155 return ret; 156 } 157 158 list_add(&matcher->list_node, &tbl->matchers_list); 159 160 return ret; 161} 162 163static int hws_matcher_connect_isolated_last(struct mlx5hws_matcher *matcher) 164{ 165 struct mlx5hws_table *tbl = matcher->tbl; 166 struct mlx5hws_context *ctx = tbl->ctx; 167 struct mlx5hws_matcher *last; 168 int ret; 169 170 last = list_last_entry(&tbl->matchers_list, 171 struct mlx5hws_matcher, 172 list_node); 173 174 /* New matcher's end_ft is already pointing to the end_ft of 175 * the complex matcher. 176 * Connect previous matcher's end_ft to this new matcher RTC. 177 */ 178 ret = mlx5hws_table_ft_set_next_rtc(ctx, 179 last->end_ft_id, 180 tbl->fw_ft_type, 181 matcher->match_ste.rtc_0_id, 182 matcher->match_ste.rtc_1_id); 183 if (ret) { 184 mlx5hws_err(ctx, 185 "Isolated matcher: failed to connect matcher end_ft to new match RTC\n"); 186 return ret; 187 } 188 189 /* Reset prev matcher FT default miss (drop refcount) */ 190 ret = mlx5hws_table_ft_set_default_next_ft(tbl, last->end_ft_id); 191 if (ret) { 192 mlx5hws_err(ctx, "Isolated matcher: failed to reset matcher ft default miss\n"); 193 return ret; 194 } 195 196 /* Insert after the last matcher */ 197 list_add(&matcher->list_node, &last->list_node); 198 199 return 0; 200} 201 202static int hws_matcher_connect_isolated(struct mlx5hws_matcher *matcher) 203{ 204 /* Isolated matcher is expected to be the only one in its table. 205 * However, it can have a collision matcher, and it can go through 206 * rehash process, in which case we will temporary have both old and 207 * new matchers in the isolated table. 208 * Check if this is the first matcher in the isolated table. 209 */ 210 if (list_empty(&matcher->tbl->matchers_list)) 211 return hws_matcher_connect_isolated_first(matcher); 212 213 /* If this wasn't the first matcher, then we have 3 possible cases: 214 * - this is a collision matcher for the first matcher 215 * - this is a new rehash dest matcher 216 * - this is a collision matcher for the new rehash dest matcher 217 * The logic to add new matcher is the same for all these cases. 218 */ 219 return hws_matcher_connect_isolated_last(matcher); 220} 221 222static int hws_matcher_connect(struct mlx5hws_matcher *matcher) 223{ 224 struct mlx5hws_table *tbl = matcher->tbl; 225 struct mlx5hws_context *ctx = tbl->ctx; 226 struct mlx5hws_matcher *prev = NULL; 227 struct mlx5hws_matcher *next = NULL; 228 struct mlx5hws_matcher *tmp_matcher; 229 int ret; 230 231 if (mlx5hws_matcher_is_isolated(matcher)) 232 return hws_matcher_connect_isolated(matcher); 233 234 /* Find location in matcher list */ 235 if (list_empty(&tbl->matchers_list)) { 236 list_add(&matcher->list_node, &tbl->matchers_list); 237 goto connect; 238 } 239 240 list_for_each_entry(tmp_matcher, &tbl->matchers_list, list_node) { 241 if (tmp_matcher->attr.priority > matcher->attr.priority) { 242 next = tmp_matcher; 243 break; 244 } 245 prev = tmp_matcher; 246 } 247 248 if (next) 249 /* insert before next */ 250 list_add_tail(&matcher->list_node, &next->list_node); 251 else 252 /* insert after prev */ 253 list_add(&matcher->list_node, &prev->list_node); 254 255connect: 256 if (next) { 257 /* Connect to next RTC */ 258 ret = mlx5hws_table_ft_set_next_rtc(ctx, 259 matcher->end_ft_id, 260 tbl->fw_ft_type, 261 next->match_ste.rtc_0_id, 262 next->match_ste.rtc_1_id); 263 if (ret) { 264 mlx5hws_err(ctx, "Failed to connect new matcher to next RTC\n"); 265 goto remove_from_list; 266 } 267 } else { 268 /* Connect last matcher to next miss_tbl if exists */ 269 ret = mlx5hws_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl); 270 if (ret) { 271 mlx5hws_err(ctx, "Failed connect new matcher to miss_tbl\n"); 272 goto remove_from_list; 273 } 274 } 275 276 /* Connect to previous FT */ 277 ret = mlx5hws_table_ft_set_next_rtc(ctx, 278 prev ? prev->end_ft_id : tbl->ft_id, 279 tbl->fw_ft_type, 280 matcher->match_ste.rtc_0_id, 281 matcher->match_ste.rtc_1_id); 282 if (ret) { 283 mlx5hws_err(ctx, "Failed to connect new matcher to previous FT\n"); 284 goto remove_from_list; 285 } 286 287 /* Reset prev matcher FT default miss (drop refcount) */ 288 ret = mlx5hws_table_ft_set_default_next_ft(tbl, prev ? prev->end_ft_id : tbl->ft_id); 289 if (ret) { 290 mlx5hws_err(ctx, "Failed to reset matcher ft default miss\n"); 291 goto remove_from_list; 292 } 293 294 if (!prev) { 295 /* Update tables missing to current matcher in the table */ 296 ret = mlx5hws_table_update_connected_miss_tables(tbl); 297 if (ret) { 298 mlx5hws_err(ctx, "Fatal error, failed to update connected miss table\n"); 299 goto remove_from_list; 300 } 301 } 302 303 return 0; 304 305remove_from_list: 306 list_del_init(&matcher->list_node); 307 return ret; 308} 309 310static int hws_matcher_disconnect_isolated(struct mlx5hws_matcher *matcher) 311{ 312 struct mlx5hws_matcher *first, *last, *prev, *next; 313 struct mlx5hws_table *tbl = matcher->tbl; 314 struct mlx5hws_context *ctx = tbl->ctx; 315 u32 end_ft_id; 316 int ret; 317 318 first = list_first_entry(&tbl->matchers_list, 319 struct mlx5hws_matcher, 320 list_node); 321 last = list_last_entry(&tbl->matchers_list, 322 struct mlx5hws_matcher, 323 list_node); 324 prev = list_prev_entry(matcher, list_node); 325 next = list_next_entry(matcher, list_node); 326 327 list_del_init(&matcher->list_node); 328 329 if (first == last) { 330 /* This was the only matcher in the list. 331 * Reset isolated table FT next RTCs and connect it 332 * to the whole complex matcher end FT instead. 333 */ 334 ret = mlx5hws_table_ft_set_next_rtc(ctx, 335 tbl->ft_id, 336 tbl->fw_ft_type, 337 0, 0); 338 if (ret) { 339 mlx5hws_err(tbl->ctx, "Isolated matcher: failed to reset FT's next RTCs\n"); 340 return ret; 341 } 342 343 end_ft_id = matcher->attr.isolated_matcher_end_ft_id; 344 ret = mlx5hws_table_ft_set_next_ft(tbl->ctx, 345 tbl->ft_id, 346 tbl->fw_ft_type, 347 end_ft_id); 348 if (ret) { 349 mlx5hws_err(tbl->ctx, "Isolated matcher: failed to set FT's miss_ft_id\n"); 350 return ret; 351 } 352 353 return 0; 354 } 355 356 /* At this point we know that there are more matchers in the list */ 357 358 if (matcher == first) { 359 /* We've disconnected the first matcher. 360 * Now update isolated table default FT. 361 */ 362 if (!next) 363 return -EINVAL; 364 return mlx5hws_table_ft_set_next_rtc(ctx, 365 tbl->ft_id, 366 tbl->fw_ft_type, 367 next->match_ste.rtc_0_id, 368 next->match_ste.rtc_1_id); 369 } 370 371 if (matcher == last) { 372 /* If we've disconnected the last matcher - update prev 373 * matcher's end_ft to point to the complex matcher end_ft. 374 */ 375 if (!prev) 376 return -EINVAL; 377 return hws_matcher_connect_end_ft_isolated(prev); 378 } 379 380 /* This wasn't the first or the last matcher, which means that it has 381 * both prev and next matchers. Note that this only happens if we're 382 * disconnecting collision matcher of the old matcher during rehash. 383 */ 384 if (!prev || !next || 385 !(matcher->flags & MLX5HWS_MATCHER_FLAGS_COLLISION)) 386 return -EINVAL; 387 388 /* Update prev end FT to point to next match RTC */ 389 return mlx5hws_table_ft_set_next_rtc(ctx, 390 prev->end_ft_id, 391 tbl->fw_ft_type, 392 next->match_ste.rtc_0_id, 393 next->match_ste.rtc_1_id); 394} 395 396static int hws_matcher_disconnect(struct mlx5hws_matcher *matcher) 397{ 398 struct mlx5hws_matcher *next = NULL, *prev = NULL; 399 struct mlx5hws_table *tbl = matcher->tbl; 400 u32 prev_ft_id = tbl->ft_id; 401 int ret; 402 403 if (mlx5hws_matcher_is_isolated(matcher)) 404 return hws_matcher_disconnect_isolated(matcher); 405 406 if (!list_is_first(&matcher->list_node, &tbl->matchers_list)) { 407 prev = list_prev_entry(matcher, list_node); 408 prev_ft_id = prev->end_ft_id; 409 } 410 411 if (!list_is_last(&matcher->list_node, &tbl->matchers_list)) 412 next = list_next_entry(matcher, list_node); 413 414 list_del_init(&matcher->list_node); 415 416 if (next) { 417 /* Connect previous end FT to next RTC */ 418 ret = mlx5hws_table_ft_set_next_rtc(tbl->ctx, 419 prev_ft_id, 420 tbl->fw_ft_type, 421 next->match_ste.rtc_0_id, 422 next->match_ste.rtc_1_id); 423 if (ret) { 424 mlx5hws_err(tbl->ctx, "Fatal error, failed to disconnect matcher\n"); 425 return ret; 426 } 427 } else { 428 ret = mlx5hws_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl); 429 if (ret) { 430 mlx5hws_err(tbl->ctx, "Fatal error, failed to disconnect last matcher\n"); 431 return ret; 432 } 433 } 434 435 /* Removing first matcher, update connected miss tables if exists */ 436 if (prev_ft_id == tbl->ft_id) { 437 ret = mlx5hws_table_update_connected_miss_tables(tbl); 438 if (ret) { 439 mlx5hws_err(tbl->ctx, 440 "Fatal error, failed to update connected miss table\n"); 441 return ret; 442 } 443 } 444 445 ret = mlx5hws_table_ft_set_default_next_ft(tbl, prev_ft_id); 446 if (ret) { 447 mlx5hws_err(tbl->ctx, "Fatal error, failed to restore matcher ft default miss\n"); 448 return ret; 449 } 450 451 return 0; 452} 453 454static void hws_matcher_set_rtc_attr_sz(struct mlx5hws_matcher *matcher, 455 struct mlx5hws_cmd_rtc_create_attr *rtc_attr, 456 bool is_mirror) 457{ 458 enum mlx5hws_matcher_flow_src flow_src = matcher->attr.optimize_flow_src; 459 460 if ((flow_src == MLX5HWS_MATCHER_FLOW_SRC_VPORT && !is_mirror) || 461 (flow_src == MLX5HWS_MATCHER_FLOW_SRC_WIRE && is_mirror)) { 462 /* Optimize FDB RTC */ 463 rtc_attr->log_size = 0; 464 rtc_attr->log_depth = 0; 465 } 466} 467 468static int hws_matcher_create_rtc(struct mlx5hws_matcher *matcher) 469{ 470 struct mlx5hws_matcher_attr *attr = &matcher->attr; 471 struct mlx5hws_cmd_rtc_create_attr rtc_attr = {0}; 472 struct mlx5hws_match_template *mt = matcher->mt; 473 struct mlx5hws_context *ctx = matcher->tbl->ctx; 474 union mlx5hws_matcher_size *size_rx, *size_tx; 475 struct mlx5hws_table *tbl = matcher->tbl; 476 u32 obj_id; 477 int ret; 478 479 size_rx = &attr->size[MLX5HWS_MATCHER_SIZE_TYPE_RX]; 480 size_tx = &attr->size[MLX5HWS_MATCHER_SIZE_TYPE_TX]; 481 482 rtc_attr.log_size = size_rx->table.sz_row_log; 483 rtc_attr.log_depth = size_rx->table.sz_col_log; 484 rtc_attr.is_frst_jumbo = mlx5hws_matcher_mt_is_jumbo(mt); 485 rtc_attr.is_scnd_range = 0; 486 rtc_attr.miss_ft_id = matcher->end_ft_id; 487 488 if (attr->insert_mode == MLX5HWS_MATCHER_INSERT_BY_HASH) { 489 /* The usual Hash Table */ 490 rtc_attr.update_index_mode = 491 MLX5_IFC_RTC_STE_UPDATE_MODE_BY_HASH; 492 493 /* The first mt is used since all share the same definer */ 494 rtc_attr.match_definer_0 = mlx5hws_definer_get_id(mt->definer); 495 } else if (attr->insert_mode == MLX5HWS_MATCHER_INSERT_BY_INDEX) { 496 rtc_attr.update_index_mode = 497 MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET; 498 rtc_attr.num_hash_definer = 1; 499 500 if (attr->distribute_mode == 501 MLX5HWS_MATCHER_DISTRIBUTE_BY_HASH) { 502 /* Hash Split Table */ 503 rtc_attr.access_index_mode = 504 MLX5_IFC_RTC_STE_ACCESS_MODE_BY_HASH; 505 rtc_attr.match_definer_0 = 506 mlx5hws_definer_get_id(mt->definer); 507 } else if (attr->distribute_mode == 508 MLX5HWS_MATCHER_DISTRIBUTE_BY_LINEAR) { 509 /* Linear Lookup Table */ 510 rtc_attr.access_index_mode = 511 MLX5_IFC_RTC_STE_ACCESS_MODE_LINEAR; 512 rtc_attr.match_definer_0 = 513 ctx->caps->linear_match_definer; 514 } 515 } 516 517 rtc_attr.pd = ctx->pd_num; 518 rtc_attr.ste_base = matcher->match_ste.ste_0_base; 519 rtc_attr.reparse_mode = mlx5hws_context_get_reparse_mode(ctx); 520 rtc_attr.table_type = mlx5hws_table_get_res_fw_ft_type(tbl->type, false); 521 hws_matcher_set_rtc_attr_sz(matcher, &rtc_attr, false); 522 523 /* STC is a single resource (obj_id), use any STC for the ID */ 524 obj_id = mlx5hws_pool_get_base_id(ctx->stc_pool); 525 rtc_attr.stc_base = obj_id; 526 527 ret = mlx5hws_cmd_rtc_create(ctx->mdev, &rtc_attr, 528 &matcher->match_ste.rtc_0_id); 529 if (ret) { 530 mlx5hws_err(ctx, "Failed to create matcher RTC\n"); 531 return ret; 532 } 533 534 if (tbl->type == MLX5HWS_TABLE_TYPE_FDB) { 535 rtc_attr.log_size = size_tx->table.sz_row_log; 536 rtc_attr.log_depth = size_tx->table.sz_col_log; 537 rtc_attr.ste_base = matcher->match_ste.ste_1_base; 538 rtc_attr.table_type = mlx5hws_table_get_res_fw_ft_type(tbl->type, true); 539 540 obj_id = mlx5hws_pool_get_base_mirror_id(ctx->stc_pool); 541 rtc_attr.stc_base = obj_id; 542 hws_matcher_set_rtc_attr_sz(matcher, &rtc_attr, true); 543 544 ret = mlx5hws_cmd_rtc_create(ctx->mdev, &rtc_attr, 545 &matcher->match_ste.rtc_1_id); 546 if (ret) { 547 mlx5hws_err(ctx, "Failed to create mirror matcher RTC\n"); 548 goto destroy_rtc_0; 549 } 550 } 551 552 return 0; 553 554destroy_rtc_0: 555 mlx5hws_cmd_rtc_destroy(ctx->mdev, matcher->match_ste.rtc_0_id); 556 return ret; 557} 558 559static void hws_matcher_destroy_rtc(struct mlx5hws_matcher *matcher) 560{ 561 struct mlx5_core_dev *mdev = matcher->tbl->ctx->mdev; 562 563 if (matcher->tbl->type == MLX5HWS_TABLE_TYPE_FDB) 564 mlx5hws_cmd_rtc_destroy(mdev, matcher->match_ste.rtc_1_id); 565 566 mlx5hws_cmd_rtc_destroy(mdev, matcher->match_ste.rtc_0_id); 567} 568 569static int 570hws_matcher_check_attr_sz(struct mlx5hws_cmd_query_caps *caps, 571 struct mlx5hws_matcher *matcher) 572{ 573 struct mlx5hws_matcher_attr *attr = &matcher->attr; 574 struct mlx5hws_context *ctx = matcher->tbl->ctx; 575 union mlx5hws_matcher_size *size; 576 int i; 577 578 for (i = 0; i < 2; i++) { 579 size = &attr->size[i]; 580 581 if (size->table.sz_col_log > caps->rtc_log_depth_max) { 582 mlx5hws_err(ctx, "Matcher depth exceeds limit %d\n", 583 caps->rtc_log_depth_max); 584 return -EOPNOTSUPP; 585 } 586 587 if (size->table.sz_col_log + size->table.sz_row_log > 588 caps->ste_alloc_log_max) { 589 mlx5hws_err(ctx, 590 "Total matcher size exceeds limit %d\n", 591 caps->ste_alloc_log_max); 592 return -EOPNOTSUPP; 593 } 594 595 if (size->table.sz_col_log + size->table.sz_row_log < 596 caps->ste_alloc_log_gran) { 597 mlx5hws_err(ctx, "Total matcher size below limit %d\n", 598 caps->ste_alloc_log_gran); 599 return -EOPNOTSUPP; 600 } 601 } 602 603 return 0; 604} 605 606static int hws_matcher_check_and_process_at(struct mlx5hws_matcher *matcher, 607 struct mlx5hws_action_template *at) 608{ 609 struct mlx5hws_context *ctx = matcher->tbl->ctx; 610 bool valid; 611 int ret; 612 613 valid = mlx5hws_action_check_combo(ctx, at->action_type_arr, matcher->tbl->type); 614 if (!valid) { 615 mlx5hws_err(ctx, "Invalid combination in action template\n"); 616 return -EINVAL; 617 } 618 619 /* Process action template to setters */ 620 ret = mlx5hws_action_template_process(at); 621 if (ret) { 622 mlx5hws_err(ctx, "Failed to process action template\n"); 623 return ret; 624 } 625 626 return 0; 627} 628 629static int hws_matcher_bind_at(struct mlx5hws_matcher *matcher) 630{ 631 bool is_jumbo = mlx5hws_matcher_mt_is_jumbo(matcher->mt); 632 struct mlx5hws_context *ctx = matcher->tbl->ctx; 633 u8 required_stes, max_stes; 634 int i, ret; 635 636 if (matcher->flags & MLX5HWS_MATCHER_FLAGS_COLLISION) 637 return 0; 638 639 max_stes = 0; 640 for (i = 0; i < matcher->num_of_at; i++) { 641 struct mlx5hws_action_template *at = &matcher->at[i]; 642 643 ret = hws_matcher_check_and_process_at(matcher, at); 644 if (ret) { 645 mlx5hws_err(ctx, "Invalid at %d", i); 646 return ret; 647 } 648 649 required_stes = at->num_of_action_stes - (!is_jumbo || at->only_term); 650 max_stes = max(max_stes, required_stes); 651 652 /* Future: Optimize reparse */ 653 } 654 655 matcher->num_of_action_stes = max_stes; 656 657 return 0; 658} 659 660static void hws_matcher_set_ip_version_match(struct mlx5hws_matcher *matcher) 661{ 662 int i; 663 664 for (i = 0; i < matcher->mt->fc_sz; i++) { 665 switch (matcher->mt->fc[i].fname) { 666 case MLX5HWS_DEFINER_FNAME_ETH_TYPE_O: 667 matcher->matches_outer_ethertype = 1; 668 break; 669 case MLX5HWS_DEFINER_FNAME_ETH_L3_TYPE_O: 670 matcher->matches_outer_ip_version = 1; 671 break; 672 case MLX5HWS_DEFINER_FNAME_ETH_TYPE_I: 673 matcher->matches_inner_ethertype = 1; 674 break; 675 case MLX5HWS_DEFINER_FNAME_ETH_L3_TYPE_I: 676 matcher->matches_inner_ip_version = 1; 677 break; 678 default: 679 break; 680 } 681 } 682} 683 684static int hws_matcher_bind_mt(struct mlx5hws_matcher *matcher) 685{ 686 struct mlx5hws_cmd_ste_create_attr ste_attr = {}; 687 struct mlx5hws_context *ctx = matcher->tbl->ctx; 688 union mlx5hws_matcher_size *size; 689 int ret; 690 691 /* Calculate match, range and hash definers */ 692 if (!(matcher->flags & MLX5HWS_MATCHER_FLAGS_COLLISION)) { 693 ret = mlx5hws_definer_mt_init(ctx, matcher->mt); 694 if (ret) { 695 if (ret == -E2BIG) 696 mlx5hws_err(ctx, "Failed to set matcher templates with match definers\n"); 697 return ret; 698 } 699 } 700 701 hws_matcher_set_ip_version_match(matcher); 702 703 /* Create an STE range each for RX and TX. */ 704 ste_attr.table_type = FS_FT_FDB_RX; 705 size = &matcher->attr.size[MLX5HWS_MATCHER_SIZE_TYPE_RX]; 706 ste_attr.log_obj_range = 707 matcher->attr.optimize_flow_src == 708 MLX5HWS_MATCHER_FLOW_SRC_VPORT ? 709 0 : size->table.sz_col_log + size->table.sz_row_log; 710 711 ret = mlx5hws_cmd_ste_create(ctx->mdev, &ste_attr, 712 &matcher->match_ste.ste_0_base); 713 if (ret) { 714 mlx5hws_err(ctx, "Failed to allocate RX STE range (%d)\n", ret); 715 goto uninit_match_definer; 716 } 717 718 ste_attr.table_type = FS_FT_FDB_TX; 719 size = &matcher->attr.size[MLX5HWS_MATCHER_SIZE_TYPE_TX]; 720 ste_attr.log_obj_range = 721 matcher->attr.optimize_flow_src == 722 MLX5HWS_MATCHER_FLOW_SRC_WIRE ? 723 0 : size->table.sz_col_log + size->table.sz_row_log; 724 725 ret = mlx5hws_cmd_ste_create(ctx->mdev, &ste_attr, 726 &matcher->match_ste.ste_1_base); 727 if (ret) { 728 mlx5hws_err(ctx, "Failed to allocate TX STE range (%d)\n", ret); 729 goto destroy_rx_ste_range; 730 } 731 732 return 0; 733 734destroy_rx_ste_range: 735 mlx5hws_cmd_ste_destroy(ctx->mdev, matcher->match_ste.ste_0_base); 736uninit_match_definer: 737 if (!(matcher->flags & MLX5HWS_MATCHER_FLAGS_COLLISION)) 738 mlx5hws_definer_mt_uninit(ctx, matcher->mt); 739 return ret; 740} 741 742static void hws_matcher_unbind_mt(struct mlx5hws_matcher *matcher) 743{ 744 struct mlx5hws_context *ctx = matcher->tbl->ctx; 745 746 mlx5hws_cmd_ste_destroy(ctx->mdev, matcher->match_ste.ste_1_base); 747 mlx5hws_cmd_ste_destroy(ctx->mdev, matcher->match_ste.ste_0_base); 748 if (!(matcher->flags & MLX5HWS_MATCHER_FLAGS_COLLISION)) 749 mlx5hws_definer_mt_uninit(ctx, matcher->mt); 750} 751 752static int 753hws_matcher_validate_insert_mode(struct mlx5hws_cmd_query_caps *caps, 754 struct mlx5hws_matcher *matcher) 755{ 756 struct mlx5hws_matcher_attr *attr = &matcher->attr; 757 struct mlx5hws_context *ctx = matcher->tbl->ctx; 758 union mlx5hws_matcher_size *size_rx, *size_tx; 759 760 size_rx = &matcher->attr.size[MLX5HWS_MATCHER_SIZE_TYPE_RX]; 761 size_tx = &matcher->attr.size[MLX5HWS_MATCHER_SIZE_TYPE_TX]; 762 763 switch (attr->insert_mode) { 764 case MLX5HWS_MATCHER_INSERT_BY_HASH: 765 if (matcher->attr.distribute_mode != MLX5HWS_MATCHER_DISTRIBUTE_BY_HASH) { 766 mlx5hws_err(ctx, "Invalid matcher distribute mode\n"); 767 return -EOPNOTSUPP; 768 } 769 break; 770 771 case MLX5HWS_MATCHER_INSERT_BY_INDEX: 772 if (size_rx->table.sz_col_log || size_tx->table.sz_col_log) { 773 mlx5hws_err(ctx, "Matcher with INSERT_BY_INDEX supports only Nx1 table size\n"); 774 return -EOPNOTSUPP; 775 } 776 777 if (attr->distribute_mode == MLX5HWS_MATCHER_DISTRIBUTE_BY_HASH) { 778 /* Hash Split Table */ 779 if (!caps->rtc_hash_split_table) { 780 mlx5hws_err(ctx, "FW doesn't support insert by index and hash distribute\n"); 781 return -EOPNOTSUPP; 782 } 783 } else if (attr->distribute_mode == MLX5HWS_MATCHER_DISTRIBUTE_BY_LINEAR) { 784 /* Linear Lookup Table */ 785 if (!caps->rtc_linear_lookup_table || 786 !IS_BIT_SET(caps->access_index_mode, 787 MLX5_IFC_RTC_STE_ACCESS_MODE_LINEAR)) { 788 mlx5hws_err(ctx, "FW doesn't support insert by index and linear distribute\n"); 789 return -EOPNOTSUPP; 790 } 791 792 if (size_rx->table.sz_row_log > 793 MLX5_IFC_RTC_LINEAR_LOOKUP_TBL_LOG_MAX || 794 size_tx->table.sz_row_log > 795 MLX5_IFC_RTC_LINEAR_LOOKUP_TBL_LOG_MAX) { 796 mlx5hws_err(ctx, "Matcher with linear distribute: rows exceed limit %d", 797 MLX5_IFC_RTC_LINEAR_LOOKUP_TBL_LOG_MAX); 798 return -EOPNOTSUPP; 799 } 800 } else { 801 mlx5hws_err(ctx, "Matcher has unsupported distribute mode\n"); 802 return -EOPNOTSUPP; 803 } 804 break; 805 806 default: 807 mlx5hws_err(ctx, "Matcher has unsupported insert mode\n"); 808 return -EOPNOTSUPP; 809 } 810 811 return 0; 812} 813 814static int 815hws_matcher_process_attr(struct mlx5hws_cmd_query_caps *caps, 816 struct mlx5hws_matcher *matcher) 817{ 818 struct mlx5hws_matcher_attr *attr = &matcher->attr; 819 union mlx5hws_matcher_size *size_rx, *size_tx; 820 821 size_rx = &attr->size[MLX5HWS_MATCHER_SIZE_TYPE_RX]; 822 size_tx = &attr->size[MLX5HWS_MATCHER_SIZE_TYPE_TX]; 823 824 if (hws_matcher_validate_insert_mode(caps, matcher)) 825 return -EOPNOTSUPP; 826 827 if (matcher->tbl->type != MLX5HWS_TABLE_TYPE_FDB && attr->optimize_flow_src) { 828 mlx5hws_err(matcher->tbl->ctx, "NIC domain doesn't support flow_src\n"); 829 return -EOPNOTSUPP; 830 } 831 832 /* Convert number of rules to the required depth */ 833 if (attr->mode == MLX5HWS_MATCHER_RESOURCE_MODE_RULE && 834 attr->insert_mode == MLX5HWS_MATCHER_INSERT_BY_HASH) { 835 size_rx->table.sz_col_log = 836 hws_matcher_rules_to_tbl_depth(size_rx->rule.num_log); 837 size_tx->table.sz_col_log = 838 hws_matcher_rules_to_tbl_depth(size_tx->rule.num_log); 839 } 840 841 matcher->flags |= attr->resizable ? MLX5HWS_MATCHER_FLAGS_RESIZABLE : 0; 842 matcher->flags |= attr->isolated_matcher_end_ft_id ? 843 MLX5HWS_MATCHER_FLAGS_ISOLATED : 0; 844 845 return hws_matcher_check_attr_sz(caps, matcher); 846} 847 848static int hws_matcher_create_and_connect(struct mlx5hws_matcher *matcher) 849{ 850 int ret; 851 852 /* Select and create the definers for current matcher */ 853 ret = hws_matcher_bind_mt(matcher); 854 if (ret) 855 return ret; 856 857 /* Calculate and verify action combination */ 858 ret = hws_matcher_bind_at(matcher); 859 if (ret) 860 goto unbind_mt; 861 862 /* Create matcher end flow table anchor */ 863 ret = hws_matcher_create_end_ft(matcher); 864 if (ret) 865 goto unbind_mt; 866 867 /* Allocate the RTC for the new matcher */ 868 ret = hws_matcher_create_rtc(matcher); 869 if (ret) 870 goto destroy_end_ft; 871 872 /* Connect the matcher to the matcher list */ 873 ret = hws_matcher_connect(matcher); 874 if (ret) 875 goto destroy_rtc; 876 877 return 0; 878 879destroy_rtc: 880 hws_matcher_destroy_rtc(matcher); 881destroy_end_ft: 882 hws_matcher_destroy_end_ft(matcher); 883unbind_mt: 884 hws_matcher_unbind_mt(matcher); 885 return ret; 886} 887 888static void hws_matcher_destroy_and_disconnect(struct mlx5hws_matcher *matcher) 889{ 890 hws_matcher_disconnect(matcher); 891 hws_matcher_destroy_rtc(matcher); 892 hws_matcher_destroy_end_ft(matcher); 893 hws_matcher_unbind_mt(matcher); 894} 895 896static int 897hws_matcher_create_col_matcher(struct mlx5hws_matcher *matcher) 898{ 899 struct mlx5hws_context *ctx = matcher->tbl->ctx; 900 union mlx5hws_matcher_size *size_rx, *size_tx; 901 struct mlx5hws_matcher *col_matcher; 902 int i, ret; 903 904 size_rx = &matcher->attr.size[MLX5HWS_MATCHER_SIZE_TYPE_RX]; 905 size_tx = &matcher->attr.size[MLX5HWS_MATCHER_SIZE_TYPE_TX]; 906 907 if (matcher->attr.mode != MLX5HWS_MATCHER_RESOURCE_MODE_RULE || 908 matcher->attr.insert_mode == MLX5HWS_MATCHER_INSERT_BY_INDEX) 909 return 0; 910 911 if (!hws_matcher_requires_col_tbl(size_rx->rule.num_log) && 912 !hws_matcher_requires_col_tbl(size_tx->rule.num_log)) 913 return 0; 914 915 col_matcher = kzalloc(sizeof(*matcher), GFP_KERNEL); 916 if (!col_matcher) 917 return -ENOMEM; 918 919 col_matcher->tbl = matcher->tbl; 920 col_matcher->mt = matcher->mt; 921 col_matcher->at = matcher->at; 922 col_matcher->num_of_at = matcher->num_of_at; 923 col_matcher->num_of_mt = matcher->num_of_mt; 924 col_matcher->attr.priority = matcher->attr.priority; 925 col_matcher->flags = matcher->flags; 926 col_matcher->flags |= MLX5HWS_MATCHER_FLAGS_COLLISION; 927 col_matcher->attr.mode = MLX5HWS_MATCHER_RESOURCE_MODE_HTABLE; 928 col_matcher->attr.optimize_flow_src = matcher->attr.optimize_flow_src; 929 for (i = 0; i < 2; i++) { 930 union mlx5hws_matcher_size *dst = &col_matcher->attr.size[i]; 931 union mlx5hws_matcher_size *src = &matcher->attr.size[i]; 932 933 dst->table.sz_row_log = src->rule.num_log; 934 dst->table.sz_col_log = MLX5HWS_MATCHER_ASSURED_COL_TBL_DEPTH; 935 if (dst->table.sz_row_log > MLX5HWS_MATCHER_ASSURED_ROW_RATIO) 936 dst->table.sz_row_log -= 937 MLX5HWS_MATCHER_ASSURED_ROW_RATIO; 938 } 939 940 col_matcher->attr.max_num_of_at_attach = matcher->attr.max_num_of_at_attach; 941 col_matcher->attr.isolated_matcher_end_ft_id = 942 matcher->attr.isolated_matcher_end_ft_id; 943 944 ret = hws_matcher_process_attr(ctx->caps, col_matcher); 945 if (ret) 946 goto free_col_matcher; 947 948 ret = hws_matcher_create_and_connect(col_matcher); 949 if (ret) 950 goto free_col_matcher; 951 952 matcher->col_matcher = col_matcher; 953 954 return 0; 955 956free_col_matcher: 957 kfree(col_matcher); 958 mlx5hws_err(ctx, "Failed to create assured collision matcher\n"); 959 return ret; 960} 961 962static void 963hws_matcher_destroy_col_matcher(struct mlx5hws_matcher *matcher) 964{ 965 if (matcher->attr.mode != MLX5HWS_MATCHER_RESOURCE_MODE_RULE || 966 matcher->attr.insert_mode == MLX5HWS_MATCHER_INSERT_BY_INDEX) 967 return; 968 969 if (matcher->col_matcher) { 970 hws_matcher_destroy_and_disconnect(matcher->col_matcher); 971 kfree(matcher->col_matcher); 972 } 973} 974 975static int hws_matcher_init(struct mlx5hws_matcher *matcher) 976{ 977 struct mlx5hws_context *ctx = matcher->tbl->ctx; 978 int ret; 979 980 mutex_lock(&ctx->ctrl_lock); 981 982 /* Allocate matcher resource and connect to the packet pipe */ 983 ret = hws_matcher_create_and_connect(matcher); 984 if (ret) 985 goto unlock_err; 986 987 /* Create additional matcher for collision handling */ 988 ret = hws_matcher_create_col_matcher(matcher); 989 if (ret) 990 goto destory_and_disconnect; 991 mutex_unlock(&ctx->ctrl_lock); 992 993 return 0; 994 995destory_and_disconnect: 996 hws_matcher_destroy_and_disconnect(matcher); 997unlock_err: 998 mutex_unlock(&ctx->ctrl_lock); 999 return ret; 1000} 1001 1002static int hws_matcher_uninit(struct mlx5hws_matcher *matcher) 1003{ 1004 struct mlx5hws_context *ctx = matcher->tbl->ctx; 1005 1006 mutex_lock(&ctx->ctrl_lock); 1007 hws_matcher_destroy_col_matcher(matcher); 1008 hws_matcher_destroy_and_disconnect(matcher); 1009 mutex_unlock(&ctx->ctrl_lock); 1010 1011 return 0; 1012} 1013 1014static int hws_matcher_grow_at_array(struct mlx5hws_matcher *matcher) 1015{ 1016 void *p; 1017 1018 if (matcher->size_of_at_array >= MLX5HWS_MATCHER_MAX_AT) 1019 return -ENOMEM; 1020 1021 matcher->size_of_at_array *= 2; 1022 p = krealloc(matcher->at, 1023 matcher->size_of_at_array * sizeof(*matcher->at), 1024 __GFP_ZERO | GFP_KERNEL); 1025 if (!p) { 1026 matcher->size_of_at_array /= 2; 1027 return -ENOMEM; 1028 } 1029 1030 matcher->at = p; 1031 1032 return 0; 1033} 1034 1035int mlx5hws_matcher_attach_at(struct mlx5hws_matcher *matcher, 1036 struct mlx5hws_action_template *at) 1037{ 1038 bool is_jumbo = mlx5hws_matcher_mt_is_jumbo(matcher->mt); 1039 u32 required_stes; 1040 int ret; 1041 1042 if (unlikely(matcher->num_of_at >= matcher->size_of_at_array)) { 1043 ret = hws_matcher_grow_at_array(matcher); 1044 if (ret) 1045 return ret; 1046 1047 if (matcher->col_matcher) { 1048 ret = hws_matcher_grow_at_array(matcher->col_matcher); 1049 if (ret) 1050 return ret; 1051 } 1052 } 1053 1054 ret = hws_matcher_check_and_process_at(matcher, at); 1055 if (ret) 1056 return ret; 1057 1058 required_stes = at->num_of_action_stes - (!is_jumbo || at->only_term); 1059 if (matcher->num_of_action_stes < required_stes) 1060 matcher->num_of_action_stes = required_stes; 1061 1062 matcher->at[matcher->num_of_at] = *at; 1063 matcher->num_of_at += 1; 1064 1065 if (matcher->col_matcher) 1066 matcher->col_matcher->num_of_at = matcher->num_of_at; 1067 1068 return 0; 1069} 1070 1071static int 1072hws_matcher_set_templates(struct mlx5hws_matcher *matcher, 1073 struct mlx5hws_match_template *mt[], 1074 u8 num_of_mt, 1075 struct mlx5hws_action_template *at[], 1076 u8 num_of_at) 1077{ 1078 struct mlx5hws_context *ctx = matcher->tbl->ctx; 1079 int ret = 0; 1080 int i; 1081 1082 if (!num_of_mt || !num_of_at) { 1083 mlx5hws_err(ctx, "Number of action/match template cannot be zero\n"); 1084 return -EOPNOTSUPP; 1085 } 1086 1087 matcher->mt = kcalloc(num_of_mt, sizeof(*matcher->mt), GFP_KERNEL); 1088 if (!matcher->mt) 1089 return -ENOMEM; 1090 1091 matcher->size_of_at_array = 1092 num_of_at + matcher->attr.max_num_of_at_attach; 1093 matcher->at = kvcalloc(matcher->size_of_at_array, sizeof(*matcher->at), 1094 GFP_KERNEL); 1095 if (!matcher->at) { 1096 mlx5hws_err(ctx, "Failed to allocate action template array\n"); 1097 ret = -ENOMEM; 1098 goto free_mt; 1099 } 1100 1101 for (i = 0; i < num_of_mt; i++) 1102 matcher->mt[i] = *mt[i]; 1103 1104 for (i = 0; i < num_of_at; i++) 1105 matcher->at[i] = *at[i]; 1106 1107 matcher->num_of_mt = num_of_mt; 1108 matcher->num_of_at = num_of_at; 1109 1110 return 0; 1111 1112free_mt: 1113 kfree(matcher->mt); 1114 return ret; 1115} 1116 1117static void 1118hws_matcher_unset_templates(struct mlx5hws_matcher *matcher) 1119{ 1120 kvfree(matcher->at); 1121 kfree(matcher->mt); 1122} 1123 1124struct mlx5hws_matcher * 1125mlx5hws_matcher_create(struct mlx5hws_table *tbl, 1126 struct mlx5hws_match_template *mt[], 1127 u8 num_of_mt, 1128 struct mlx5hws_action_template *at[], 1129 u8 num_of_at, 1130 struct mlx5hws_matcher_attr *attr) 1131{ 1132 struct mlx5hws_context *ctx = tbl->ctx; 1133 struct mlx5hws_matcher *matcher; 1134 int ret; 1135 1136 matcher = kzalloc(sizeof(*matcher), GFP_KERNEL); 1137 if (!matcher) 1138 return NULL; 1139 1140 matcher->tbl = tbl; 1141 matcher->attr = *attr; 1142 1143 ret = hws_matcher_process_attr(tbl->ctx->caps, matcher); 1144 if (ret) 1145 goto free_matcher; 1146 1147 ret = hws_matcher_set_templates(matcher, mt, num_of_mt, at, num_of_at); 1148 if (ret) 1149 goto free_matcher; 1150 1151 ret = hws_matcher_init(matcher); 1152 if (ret) { 1153 mlx5hws_err(ctx, "Failed to initialise matcher: %d\n", ret); 1154 goto unset_templates; 1155 } 1156 1157 return matcher; 1158 1159unset_templates: 1160 hws_matcher_unset_templates(matcher); 1161free_matcher: 1162 kfree(matcher); 1163 return NULL; 1164} 1165 1166int mlx5hws_matcher_destroy(struct mlx5hws_matcher *matcher) 1167{ 1168 hws_matcher_uninit(matcher); 1169 hws_matcher_unset_templates(matcher); 1170 kfree(matcher); 1171 return 0; 1172} 1173 1174struct mlx5hws_match_template * 1175mlx5hws_match_template_create(struct mlx5hws_context *ctx, 1176 u32 *match_param, 1177 u32 match_param_sz, 1178 u8 match_criteria_enable) 1179{ 1180 struct mlx5hws_match_template *mt; 1181 1182 mt = kzalloc(sizeof(*mt), GFP_KERNEL); 1183 if (!mt) 1184 return NULL; 1185 1186 mt->match_param = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL); 1187 if (!mt->match_param) 1188 goto free_template; 1189 1190 memcpy(mt->match_param, match_param, match_param_sz); 1191 mt->match_criteria_enable = match_criteria_enable; 1192 1193 return mt; 1194 1195free_template: 1196 kfree(mt); 1197 return NULL; 1198} 1199 1200int mlx5hws_match_template_destroy(struct mlx5hws_match_template *mt) 1201{ 1202 kfree(mt->match_param); 1203 kfree(mt); 1204 return 0; 1205} 1206 1207static int hws_matcher_resize_precheck(struct mlx5hws_matcher *src_matcher, 1208 struct mlx5hws_matcher *dst_matcher) 1209{ 1210 struct mlx5hws_context *ctx = src_matcher->tbl->ctx; 1211 int i; 1212 1213 if (src_matcher->tbl->type != dst_matcher->tbl->type) { 1214 mlx5hws_err(ctx, "Table type mismatch for src/dst matchers\n"); 1215 return -EINVAL; 1216 } 1217 1218 if (!mlx5hws_matcher_is_resizable(src_matcher) || 1219 !mlx5hws_matcher_is_resizable(dst_matcher)) { 1220 mlx5hws_err(ctx, "Src/dst matcher is not resizable\n"); 1221 return -EINVAL; 1222 } 1223 1224 if (mlx5hws_matcher_is_insert_by_idx(src_matcher) != 1225 mlx5hws_matcher_is_insert_by_idx(dst_matcher)) { 1226 mlx5hws_err(ctx, "Src/dst matchers insert mode mismatch\n"); 1227 return -EINVAL; 1228 } 1229 1230 if (mlx5hws_matcher_is_in_resize(src_matcher) || 1231 mlx5hws_matcher_is_in_resize(dst_matcher)) { 1232 mlx5hws_err(ctx, "Src/dst matcher is already in resize\n"); 1233 return -EINVAL; 1234 } 1235 1236 /* Compare match templates - make sure the definers are equivalent */ 1237 if (src_matcher->num_of_mt != dst_matcher->num_of_mt) { 1238 mlx5hws_err(ctx, "Src/dst matcher match templates mismatch\n"); 1239 return -EINVAL; 1240 } 1241 1242 if (src_matcher->num_of_action_stes > dst_matcher->num_of_action_stes) { 1243 mlx5hws_err(ctx, "Src/dst matcher max STEs mismatch\n"); 1244 return -EINVAL; 1245 } 1246 1247 for (i = 0; i < src_matcher->num_of_mt; i++) { 1248 if (mlx5hws_definer_compare(src_matcher->mt[i].definer, 1249 dst_matcher->mt[i].definer)) { 1250 mlx5hws_err(ctx, "Src/dst matcher definers mismatch\n"); 1251 return -EINVAL; 1252 } 1253 } 1254 1255 return 0; 1256} 1257 1258int mlx5hws_matcher_resize_set_target(struct mlx5hws_matcher *src_matcher, 1259 struct mlx5hws_matcher *dst_matcher) 1260{ 1261 int ret = 0; 1262 1263 mutex_lock(&src_matcher->tbl->ctx->ctrl_lock); 1264 1265 ret = hws_matcher_resize_precheck(src_matcher, dst_matcher); 1266 if (ret) 1267 goto out; 1268 1269 src_matcher->resize_dst = dst_matcher; 1270 1271out: 1272 mutex_unlock(&src_matcher->tbl->ctx->ctrl_lock); 1273 return ret; 1274} 1275 1276int mlx5hws_matcher_resize_rule_move(struct mlx5hws_matcher *src_matcher, 1277 struct mlx5hws_rule *rule, 1278 struct mlx5hws_rule_attr *attr) 1279{ 1280 struct mlx5hws_context *ctx = src_matcher->tbl->ctx; 1281 1282 if (unlikely(!mlx5hws_matcher_is_in_resize(src_matcher))) { 1283 mlx5hws_err(ctx, "Matcher is not resizable or not in resize\n"); 1284 return -EINVAL; 1285 } 1286 1287 if (unlikely(src_matcher != rule->matcher)) { 1288 mlx5hws_err(ctx, "Rule doesn't belong to src matcher\n"); 1289 return -EINVAL; 1290 } 1291 1292 return mlx5hws_rule_move_hws_add(rule, attr); 1293}
~/
Read-only file preview.