| @@ -16,6 +16,10 @@ · 15 unmodified lines |
| 16 | #define esw_chains_ht(esw) (esw_chains_priv(esw)->chains_ht) | 16 | #define esw_chains_ht(esw) (esw_chains_priv(esw)->chains_ht) |
| 17 | #define esw_prios_ht(esw) (esw_chains_priv(esw)->prios_ht) | 17 | #define esw_prios_ht(esw) (esw_chains_priv(esw)->prios_ht) |
| 18 | #define fdb_pool_left(esw) (esw_chains_priv(esw)->fdb_left) | 18 | #define fdb_pool_left(esw) (esw_chains_priv(esw)->fdb_left) |
| | 19 | #define tc_slow_fdb(esw) ((esw)->fdb_table.offloads.slow_fdb) |
| | 20 | #define tc_end_fdb(esw) (esw_chains_priv(esw)->tc_end_fdb) |
| | 21 | #define fdb_ignore_flow_level_supported(esw) \ |
| | 22 | (MLX5_CAP_ESW_FLOWTABLE_FDB((esw)->dev, ignore_flow_level)) |
| 19 | | 23 | |
| 20 | #define ESW_OFFLOADS_NUM_GROUPS 4 | 24 | #define ESW_OFFLOADS_NUM_GROUPS 4 |
| 21 | | 25 | |
| @@ -39,6 +43,8 @@ struct mlx5_esw_chains_priv { · 17 unmodified lines |
| 39 | /* Protects above chains_ht and prios_ht */ | 43 | /* Protects above chains_ht and prios_ht */ |
| 40 | struct mutex lock; | 44 | struct mutex lock; |
| 41 | | 45 | |
| | 46 | struct mlx5_flow_table *tc_end_fdb; |
| | 47 | |
| 42 | int fdb_left[ARRAY_SIZE(ESW_POOLS)]; | 48 | int fdb_left[ARRAY_SIZE(ESW_POOLS)]; |
| 43 | }; | 49 | }; |
| 44 | | 50 | |
| @@ -50,6 +56,7 @@ struct fdb_chain { · 5 unmodified lines |
| 50 | int ref; | 56 | int ref; |
| 51 | | 57 | |
| 52 | struct mlx5_eswitch *esw; | 58 | struct mlx5_eswitch *esw; |
| | 59 | struct list_head prios_list; |
| 53 | }; | 60 | }; |
| 54 | | 61 | |
| 55 | struct fdb_prio_key { | 62 | struct fdb_prio_key { |
| @@ -60,6 +67,7 @@ struct fdb_prio_key { · 4 unmodified lines |
| 60 | | 67 | |
| 61 | struct fdb_prio { | 68 | struct fdb_prio { |
| 62 | struct rhash_head node; | 69 | struct rhash_head node; |
| | 70 | struct list_head list; |
| 63 | | 71 | |
| 64 | struct fdb_prio_key key; | 72 | struct fdb_prio_key key; |
| 65 | | 73 | |
| @@ -67,6 +75,9 @@ struct fdb_prio { · 1 unmodified line |
| 67 | | 75 | |
| 68 | struct fdb_chain *fdb_chain; | 76 | struct fdb_chain *fdb_chain; |
| 69 | struct mlx5_flow_table *fdb; | 77 | struct mlx5_flow_table *fdb; |
| | 78 | struct mlx5_flow_table *next_fdb; |
| | 79 | struct mlx5_flow_group *miss_group; |
| | 80 | struct mlx5_flow_handle *miss_rule; |
| 70 | }; | 81 | }; |
| 71 | | 82 | |
| 72 | static const struct rhashtable_params chain_params = { | 83 | static const struct rhashtable_params chain_params = { |
| @@ -93,6 +104,9 @@ u32 mlx5_esw_chains_get_chain_range(struct mlx5_eswitch *esw) · 20 unmodified lines |
| 93 | if (!mlx5_esw_chains_prios_supported(esw)) | 104 | if (!mlx5_esw_chains_prios_supported(esw)) |
| 94 | return 1; | 105 | return 1; |
| 95 | | 106 | |
| | 107 | if (fdb_ignore_flow_level_supported(esw)) |
| | 108 | return UINT_MAX - 1; |
| | 109 | |
| 96 | return FDB_TC_MAX_CHAIN; | 110 | return FDB_TC_MAX_CHAIN; |
| 97 | } | 111 | } |
| 98 | | 112 | |
| @@ -106,11 +120,17 @@ u32 mlx5_esw_chains_get_prio_range(struct mlx5_eswitch *esw) · 7 unmodified lines |
| 106 | if (!mlx5_esw_chains_prios_supported(esw)) | 120 | if (!mlx5_esw_chains_prios_supported(esw)) |
| 107 | return 1; | 121 | return 1; |
| 108 | | 122 | |
| | 123 | if (fdb_ignore_flow_level_supported(esw)) |
| | 124 | return UINT_MAX; |
| | 125 | |
| 109 | return FDB_TC_MAX_PRIO; | 126 | return FDB_TC_MAX_PRIO; |
| 110 | } | 127 | } |
| 111 | | 128 | |
| 112 | static unsigned int mlx5_esw_chains_get_level_range(struct mlx5_eswitch *esw) | 129 | static unsigned int mlx5_esw_chains_get_level_range(struct mlx5_eswitch *esw) |
| 113 | { | 130 | { |
| | 131 | if (fdb_ignore_flow_level_supported(esw)) |
| | 132 | return UINT_MAX; |
| | 133 | |
| 114 | return FDB_TC_LEVELS_PER_PRIO; | 134 | return FDB_TC_LEVELS_PER_PRIO; |
| 115 | } | 135 | } |
| 116 | | 136 | |
| @@ -181,13 +201,40 @@ mlx5_esw_chains_create_fdb_table(struct mlx5_eswitch *esw, · 64 unmodified lines |
| 181 | sz = mlx5_esw_chains_get_avail_sz_from_pool(esw, POOL_NEXT_SIZE); | 201 | sz = mlx5_esw_chains_get_avail_sz_from_pool(esw, POOL_NEXT_SIZE); |
| 182 | if (!sz) | 202 | if (!sz) |
| 183 | return ERR_PTR(-ENOSPC); | 203 | return ERR_PTR(-ENOSPC); |
| 184 | | | |
| 185 | ft_attr.max_fte = sz; | 204 | ft_attr.max_fte = sz; |
| 186 | ft_attr.level = level; | | |
| 187 | ft_attr.prio = prio - 1; | | |
| 188 | ft_attr.autogroup.max_num_groups = ESW_OFFLOADS_NUM_GROUPS; | | |
| 189 | ns = mlx5_get_fdb_sub_ns(esw->dev, chain); | | |
| 190 | | 205 | |
| | 206 | /* We use tc_slow_fdb(esw) as the table's next_ft till |
| | 207 | * ignore_flow_level is allowed on FT creation and not just for FTEs. |
| | 208 | * Instead caller should add an explicit miss rule if needed. |
| | 209 | */ |
| | 210 | ft_attr.next_ft = tc_slow_fdb(esw); |
| | 211 | |
| | 212 | /* The root table(chain 0, prio 1, level 0) is required to be |
| | 213 | * connected to the previous prio (FDB_BYPASS_PATH if exists). |
| | 214 | * We always create it, as a managed table, in order to align with |
| | 215 | * fs_core logic. |
| | 216 | */ |
| | 217 | if (!fdb_ignore_flow_level_supported(esw) || |
| | 218 | (chain == 0 && prio == 1 && level == 0)) { |
| | 219 | ft_attr.level = level; |
| | 220 | ft_attr.prio = prio - 1; |
| | 221 | ns = mlx5_get_fdb_sub_ns(esw->dev, chain); |
| | 222 | } else { |
| | 223 | ft_attr.flags |= MLX5_FLOW_TABLE_UNMANAGED; |
| | 224 | ft_attr.prio = FDB_TC_OFFLOAD; |
| | 225 | /* Firmware doesn't allow us to create another level 0 table, |
| | 226 | * so we create all unmanaged tables as level 1. |
| | 227 | * |
| | 228 | * To connect them, we use explicit miss rules with |
| | 229 | * ignore_flow_level. Caller is responsible to create |
| | 230 | * these rules (if needed). |
| | 231 | */ |
| | 232 | ft_attr.level = 1; |
| | 233 | ns = mlx5_get_flow_namespace(esw->dev, MLX5_FLOW_NAMESPACE_FDB); |
| | 234 | } |
| | 235 | |
| | 236 | ft_attr.autogroup.num_reserved_entries = 2; |
| | 237 | ft_attr.autogroup.max_num_groups = ESW_OFFLOADS_NUM_GROUPS; |
| 191 | fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); | 238 | fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); |
| 192 | if (IS_ERR(fdb)) { | 239 | if (IS_ERR(fdb)) { |
| 193 | esw_warn(esw->dev, | 240 | esw_warn(esw->dev, |
| @@ -220,6 +267,7 @@ mlx5_esw_chains_create_fdb_chain(struct mlx5_eswitch *esw, u32 chain) · 26 unmodified lines |
| 220 | | 267 | |
| 221 | fdb_chain->esw = esw; | 268 | fdb_chain->esw = esw; |
| 222 | fdb_chain->chain = chain; | 269 | fdb_chain->chain = chain; |
| | 270 | INIT_LIST_HEAD(&fdb_chain->prios_list); |
| 223 | | 271 | |
| 224 | err = rhashtable_insert_fast(&esw_chains_ht(esw), &fdb_chain->node, | 272 | err = rhashtable_insert_fast(&esw_chains_ht(esw), &fdb_chain->node, |
| 225 | chain_params); | 273 | chain_params); |
| @@ -261,6 +309,79 @@ mlx5_esw_chains_get_fdb_chain(struct mlx5_eswitch *esw, u32 chain) · 35 unmodified lines |
| 261 | return fdb_chain; | 309 | return fdb_chain; |
| 262 | } | 310 | } |
| 263 | | 311 | |
| | 312 | static struct mlx5_flow_handle * |
| | 313 | mlx5_esw_chains_add_miss_rule(struct mlx5_flow_table *fdb, |
| | 314 | struct mlx5_flow_table *next_fdb) |
| | 315 | { |
| | 316 | static const struct mlx5_flow_spec spec = {}; |
| | 317 | struct mlx5_flow_destination dest = {}; |
| | 318 | struct mlx5_flow_act act = {}; |
| | 319 | |
| | 320 | act.flags = FLOW_ACT_IGNORE_FLOW_LEVEL | FLOW_ACT_NO_APPEND; |
| | 321 | act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; |
| | 322 | dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; |
| | 323 | dest.ft = next_fdb; |
| | 324 | |
| | 325 | return mlx5_add_flow_rules(fdb, &spec, &act, &dest, 1); |
| | 326 | } |
| | 327 | |
| | 328 | static int |
| | 329 | mlx5_esw_chains_update_prio_prevs(struct fdb_prio *fdb_prio, |
| | 330 | struct mlx5_flow_table *next_fdb) |
| | 331 | { |
| | 332 | struct mlx5_flow_handle *miss_rules[FDB_TC_LEVELS_PER_PRIO + 1] = {}; |
| | 333 | struct fdb_chain *fdb_chain = fdb_prio->fdb_chain; |
| | 334 | struct fdb_prio *pos; |
| | 335 | int n = 0, err; |
| | 336 | |
| | 337 | if (fdb_prio->key.level) |
| | 338 | return 0; |
| | 339 | |
| | 340 | /* Iterate in reverse order until reaching the level 0 rule of |
| | 341 | * the previous priority, adding all the miss rules first, so we can |
| | 342 | * revert them if any of them fails. |
| | 343 | */ |
| | 344 | pos = fdb_prio; |
| | 345 | list_for_each_entry_continue_reverse(pos, |
| | 346 | &fdb_chain->prios_list, |
| | 347 | list) { |
| | 348 | miss_rules[n] = mlx5_esw_chains_add_miss_rule(pos->fdb, |
| | 349 | next_fdb); |
| | 350 | if (IS_ERR(miss_rules[n])) { |
| | 351 | err = PTR_ERR(miss_rules[n]); |
| | 352 | goto err_prev_rule; |
| | 353 | } |
| | 354 | |
| | 355 | n++; |
| | 356 | if (!pos->key.level) |
| | 357 | break; |
| | 358 | } |
| | 359 | |
| | 360 | /* Success, delete old miss rules, and update the pointers. */ |
| | 361 | n = 0; |
| | 362 | pos = fdb_prio; |
| | 363 | list_for_each_entry_continue_reverse(pos, |
| | 364 | &fdb_chain->prios_list, |
| | 365 | list) { |
| | 366 | mlx5_del_flow_rules(pos->miss_rule); |
| | 367 | |
| | 368 | pos->miss_rule = miss_rules[n]; |
| | 369 | pos->next_fdb = next_fdb; |
| | 370 | |
| | 371 | n++; |
| | 372 | if (!pos->key.level) |
| | 373 | break; |
| | 374 | } |
| | 375 | |
| | 376 | return 0; |
| | 377 | |
| | 378 | err_prev_rule: |
| | 379 | while (--n >= 0) |
| | 380 | mlx5_del_flow_rules(miss_rules[n]); |
| | 381 | |
| | 382 | return err; |
| | 383 | } |
| | 384 | |
| 264 | static void | 385 | static void |
| 265 | mlx5_esw_chains_put_fdb_chain(struct fdb_chain *fdb_chain) | 386 | mlx5_esw_chains_put_fdb_chain(struct fdb_chain *fdb_chain) |
| 266 | { | 387 | { |
| @@ -272,9 +393,15 @@ static struct fdb_prio * · 5 unmodified lines |
| 272 | mlx5_esw_chains_create_fdb_prio(struct mlx5_eswitch *esw, | 393 | mlx5_esw_chains_create_fdb_prio(struct mlx5_eswitch *esw, |
| 273 | u32 chain, u32 prio, u32 level) | 394 | u32 chain, u32 prio, u32 level) |
| 274 | { | 395 | { |
| | 396 | int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); |
| | 397 | struct mlx5_flow_handle *miss_rule = NULL; |
| | 398 | struct mlx5_flow_group *miss_group; |
| 275 | struct fdb_prio *fdb_prio = NULL; | 399 | struct fdb_prio *fdb_prio = NULL; |
| | 400 | struct mlx5_flow_table *next_fdb; |
| 276 | struct fdb_chain *fdb_chain; | 401 | struct fdb_chain *fdb_chain; |
| 277 | struct mlx5_flow_table *fdb; | 402 | struct mlx5_flow_table *fdb; |
| | 403 | struct list_head *pos; |
| | 404 | u32 *flow_group_in; |
| 278 | int err; | 405 | int err; |
| 279 | | 406 | |
| 280 | fdb_chain = mlx5_esw_chains_get_fdb_chain(esw, chain); | 407 | fdb_chain = mlx5_esw_chains_get_fdb_chain(esw, chain); |
| @@ -282,18 +409,65 @@ mlx5_esw_chains_create_fdb_prio(struct mlx5_eswitch *esw, · 1 unmodified line |
| 282 | return ERR_CAST(fdb_chain); | 409 | return ERR_CAST(fdb_chain); |
| 283 | | 410 | |
| 284 | fdb_prio = kvzalloc(sizeof(*fdb_prio), GFP_KERNEL); | 411 | fdb_prio = kvzalloc(sizeof(*fdb_prio), GFP_KERNEL); |
| 285 | if (!fdb_prio) { | 412 | flow_group_in = kvzalloc(inlen, GFP_KERNEL); |
| | 413 | if (!fdb_prio || !flow_group_in) { |
| 286 | err = -ENOMEM; | 414 | err = -ENOMEM; |
| 287 | goto err_alloc; | 415 | goto err_alloc; |
| 288 | } | 416 | } |
| 289 | | 417 | |
| 290 | fdb = mlx5_esw_chains_create_fdb_table(esw, fdb_chain->chain, prio, | 418 | /* Chain's prio list is sorted by prio and level. |
| 291 | level); | 419 | * And all levels of some prio point to the next prio's level 0. |
| | 420 | * Example list (prio, level): |
| | 421 | * (3,0)->(3,1)->(5,0)->(5,1)->(6,1)->(7,0) |
| | 422 | * In hardware, we will we have the following pointers: |
| | 423 | * (3,0) -> (5,0) -> (7,0) -> Slow path |
| | 424 | * (3,1) -> (5,0) |
| | 425 | * (5,1) -> (7,0) |
| | 426 | * (6,1) -> (7,0) |
| | 427 | */ |
| | 428 | |
| | 429 | /* Default miss for each chain: */ |
| | 430 | next_fdb = (chain == mlx5_esw_chains_get_ft_chain(esw)) ? |
| | 431 | tc_slow_fdb(esw) : |
| | 432 | tc_end_fdb(esw); |
| | 433 | list_for_each(pos, &fdb_chain->prios_list) { |
| | 434 | struct fdb_prio *p = list_entry(pos, struct fdb_prio, list); |
| | 435 | |
| | 436 | /* exit on first pos that is larger */ |
| | 437 | if (prio < p->key.prio || (prio == p->key.prio && |
| | 438 | level < p->key.level)) { |
| | 439 | /* Get next level 0 table */ |
| | 440 | next_fdb = p->key.level == 0 ? p->fdb : p->next_fdb; |
| | 441 | break; |
| | 442 | } |
| | 443 | } |
| | 444 | |
| | 445 | fdb = mlx5_esw_chains_create_fdb_table(esw, chain, prio, level); |
| 292 | if (IS_ERR(fdb)) { | 446 | if (IS_ERR(fdb)) { |
| 293 | err = PTR_ERR(fdb); | 447 | err = PTR_ERR(fdb); |
| 294 | goto err_create; | 448 | goto err_create; |
| 295 | } | 449 | } |
| 296 | | 450 | |
| | 451 | MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, |
| | 452 | fdb->max_fte - 2); |
| | 453 | MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, |
| | 454 | fdb->max_fte - 1); |
| | 455 | miss_group = mlx5_create_flow_group(fdb, flow_group_in); |
| | 456 | if (IS_ERR(miss_group)) { |
| | 457 | err = PTR_ERR(miss_group); |
| | 458 | goto err_group; |
| | 459 | } |
| | 460 | |
| | 461 | /* Add miss rule to next_fdb */ |
| | 462 | miss_rule = mlx5_esw_chains_add_miss_rule(fdb, next_fdb); |
| | 463 | if (IS_ERR(miss_rule)) { |
| | 464 | err = PTR_ERR(miss_rule); |
| | 465 | goto err_miss_rule; |
| | 466 | } |
| | 467 | |
| | 468 | fdb_prio->miss_group = miss_group; |
| | 469 | fdb_prio->miss_rule = miss_rule; |
| | 470 | fdb_prio->next_fdb = next_fdb; |
| 297 | fdb_prio->fdb_chain = fdb_chain; | 471 | fdb_prio->fdb_chain = fdb_chain; |
| 298 | fdb_prio->key.chain = chain; | 472 | fdb_prio->key.chain = chain; |
| 299 | fdb_prio->key.prio = prio; | 473 | fdb_prio->key.prio = prio; |
| @@ -305,13 +479,30 @@ mlx5_esw_chains_create_fdb_prio(struct mlx5_eswitch *esw, · 5 unmodified lines |
| 305 | if (err) | 479 | if (err) |
| 306 | goto err_insert; | 480 | goto err_insert; |
| 307 | | 481 | |
| | 482 | list_add(&fdb_prio->list, pos->prev); |
| | 483 | |
| | 484 | /* Table is ready, connect it */ |
| | 485 | err = mlx5_esw_chains_update_prio_prevs(fdb_prio, fdb); |
| | 486 | if (err) |
| | 487 | goto err_update; |
| | 488 | |
| | 489 | kvfree(flow_group_in); |
| 308 | return fdb_prio; | 490 | return fdb_prio; |
| 309 | | 491 | |
| | 492 | err_update: |
| | 493 | list_del(&fdb_prio->list); |
| | 494 | rhashtable_remove_fast(&esw_prios_ht(esw), &fdb_prio->node, |
| | 495 | prio_params); |
| 310 | err_insert: | 496 | err_insert: |
| | 497 | mlx5_del_flow_rules(miss_rule); |
| | 498 | err_miss_rule: |
| | 499 | mlx5_destroy_flow_group(miss_group); |
| | 500 | err_group: |
| 311 | mlx5_esw_chains_destroy_fdb_table(esw, fdb); | 501 | mlx5_esw_chains_destroy_fdb_table(esw, fdb); |
| 312 | err_create: | 502 | err_create: |
| 313 | kvfree(fdb_prio); | | |
| 314 | err_alloc: | 503 | err_alloc: |
| | 504 | kvfree(fdb_prio); |
| | 505 | kvfree(flow_group_in); |
| 315 | mlx5_esw_chains_put_fdb_chain(fdb_chain); | 506 | mlx5_esw_chains_put_fdb_chain(fdb_chain); |
| 316 | return ERR_PTR(err); | 507 | return ERR_PTR(err); |
| 317 | } | 508 | } |
| @@ -322,8 +513,14 @@ mlx5_esw_chains_destroy_fdb_prio(struct mlx5_eswitch *esw, · 4 unmodified lines |
| 322 | { | 513 | { |
| 323 | struct fdb_chain *fdb_chain = fdb_prio->fdb_chain; | 514 | struct fdb_chain *fdb_chain = fdb_prio->fdb_chain; |
| 324 | | 515 | |
| | 516 | WARN_ON(mlx5_esw_chains_update_prio_prevs(fdb_prio, |
| | 517 | fdb_prio->next_fdb)); |
| | 518 | |
| | 519 | list_del(&fdb_prio->list); |
| 325 | rhashtable_remove_fast(&esw_prios_ht(esw), &fdb_prio->node, | 520 | rhashtable_remove_fast(&esw_prios_ht(esw), &fdb_prio->node, |
| 326 | prio_params); | 521 | prio_params); |
| | 522 | mlx5_del_flow_rules(fdb_prio->miss_rule); |
| | 523 | mlx5_destroy_flow_group(fdb_prio->miss_group); |
| 327 | mlx5_esw_chains_destroy_fdb_table(esw, fdb_prio->fdb); | 524 | mlx5_esw_chains_destroy_fdb_table(esw, fdb_prio->fdb); |
| 328 | mlx5_esw_chains_put_fdb_chain(fdb_chain); | 525 | mlx5_esw_chains_put_fdb_chain(fdb_chain); |
| 329 | kvfree(fdb_prio); | 526 | kvfree(fdb_prio); |
| @@ -415,6 +612,12 @@ err_get_prio: · 85 unmodified lines |
| 415 | chain, prio, level); | 612 | chain, prio, level); |
| 416 | } | 613 | } |
| 417 | | 614 | |
| | 615 | struct mlx5_flow_table * |
| | 616 | mlx5_esw_chains_get_tc_end_ft(struct mlx5_eswitch *esw) |
| | 617 | { |
| | 618 | return tc_end_fdb(esw); |
| | 619 | } |
| | 620 | |
| 418 | static int | 621 | static int |
| 419 | mlx5_esw_chains_init(struct mlx5_eswitch *esw) | 622 | mlx5_esw_chains_init(struct mlx5_eswitch *esw) |
| 420 | { | 623 | { |
| @@ -484,11 +687,21 @@ mlx5_esw_chains_open(struct mlx5_eswitch *esw) · 63 unmodified lines |
| 484 | struct mlx5_flow_table *ft; | 687 | struct mlx5_flow_table *ft; |
| 485 | int err; | 688 | int err; |
| 486 | | 689 | |
| 487 | /* Always open the root for fast path */ | 690 | /* Create tc_end_fdb(esw) which is the always created ft chain */ |
| 488 | ft = mlx5_esw_chains_get_table(esw, 0, 1, 0); | 691 | ft = mlx5_esw_chains_get_table(esw, mlx5_esw_chains_get_ft_chain(esw), |
| | 692 | 1, 0); |
| 489 | if (IS_ERR(ft)) | 693 | if (IS_ERR(ft)) |
| 490 | return PTR_ERR(ft); | 694 | return PTR_ERR(ft); |
| 491 | | 695 | |
| | 696 | tc_end_fdb(esw) = ft; |
| | 697 | |
| | 698 | /* Always open the root for fast path */ |
| | 699 | ft = mlx5_esw_chains_get_table(esw, 0, 1, 0); |
| | 700 | if (IS_ERR(ft)) { |
| | 701 | err = PTR_ERR(ft); |
| | 702 | goto level_0_err; |
| | 703 | } |
| | 704 | |
| 492 | /* Open level 1 for split rules now if prios isn't supported */ | 705 | /* Open level 1 for split rules now if prios isn't supported */ |
| 493 | if (!mlx5_esw_chains_prios_supported(esw)) { | 706 | if (!mlx5_esw_chains_prios_supported(esw)) { |
| 494 | ft = mlx5_esw_chains_get_table(esw, 0, 1, 1); | 707 | ft = mlx5_esw_chains_get_table(esw, 0, 1, 1); |
| @@ -503,6 +716,8 @@ mlx5_esw_chains_open(struct mlx5_eswitch *esw) · 8 unmodified lines |
| 503 | | 716 | |
| 504 | level_1_err: | 717 | level_1_err: |
| 505 | mlx5_esw_chains_put_table(esw, 0, 1, 0); | 718 | mlx5_esw_chains_put_table(esw, 0, 1, 0); |
| | 719 | level_0_err: |
| | 720 | mlx5_esw_chains_put_table(esw, mlx5_esw_chains_get_ft_chain(esw), 1, 0); |
| 506 | return err; | 721 | return err; |
| 507 | } | 722 | } |
| 508 | | 723 | |
| @@ -512,6 +727,7 @@ mlx5_esw_chains_close(struct mlx5_eswitch *esw) · 3 unmodified lines |
| 512 | if (!mlx5_esw_chains_prios_supported(esw)) | 727 | if (!mlx5_esw_chains_prios_supported(esw)) |
| 513 | mlx5_esw_chains_put_table(esw, 0, 1, 1); | 728 | mlx5_esw_chains_put_table(esw, 0, 1, 1); |
| 514 | mlx5_esw_chains_put_table(esw, 0, 1, 0); | 729 | mlx5_esw_chains_put_table(esw, 0, 1, 0); |
| | 730 | mlx5_esw_chains_put_table(esw, mlx5_esw_chains_get_ft_chain(esw), 1, 0); |
| 515 | } | 731 | } |
| 516 | | 732 | |
| 517 | int | 733 | int |