1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */ 3 4#include "rx_res.h" 5#include "channels.h" 6#include "params.h" 7 8#define MLX5E_MAX_NUM_RSS 16 9 10struct mlx5e_rx_res { 11 struct mlx5_core_dev *mdev; /* primary */ 12 enum mlx5e_rx_res_features features; 13 unsigned int max_nch; 14 u32 drop_rqn; 15 16 struct mlx5e_packet_merge_param pkt_merge_param; 17 struct rw_semaphore pkt_merge_param_sem; 18 19 struct mlx5e_rss *rss[MLX5E_MAX_NUM_RSS]; 20 bool rss_active; 21 u32 *rss_rqns; 22 u32 *rss_vhca_ids; 23 unsigned int rss_nch; 24 25 struct { 26 struct mlx5e_rqt direct_rqt; 27 struct mlx5e_tir direct_tir; 28 } *channels; 29 30 struct { 31 struct mlx5e_rqt rqt; 32 struct mlx5e_tir tir; 33 } ptp; 34}; 35 36/* API for rx_res_rss_* */ 37 38static u32 *get_vhca_ids(struct mlx5e_rx_res *res, int offset) 39{ 40 bool multi_vhca = res->features & MLX5E_RX_RES_FEATURE_MULTI_VHCA; 41 42 return multi_vhca ? res->rss_vhca_ids + offset : NULL; 43} 44 45void mlx5e_rx_res_rss_update_num_channels(struct mlx5e_rx_res *res, u32 nch) 46{ 47 int i; 48 49 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) { 50 if (res->rss[i]) 51 mlx5e_rss_params_indir_modify_actual_size(res->rss[i], nch); 52 } 53} 54 55static int mlx5e_rx_res_rss_init_def(struct mlx5e_rx_res *res, 56 unsigned int init_nch) 57{ 58 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; 59 struct mlx5e_rss *rss; 60 61 if (WARN_ON(res->rss[0])) 62 return -EINVAL; 63 64 rss = mlx5e_rss_init(res->mdev, inner_ft_support, res->drop_rqn, 65 &res->pkt_merge_param, MLX5E_RSS_INIT_TIRS, init_nch, res->max_nch); 66 if (IS_ERR(rss)) 67 return PTR_ERR(rss); 68 69 mlx5e_rss_set_indir_uniform(rss, init_nch); 70 71 res->rss[0] = rss; 72 73 return 0; 74} 75 76int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int init_nch) 77{ 78 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; 79 struct mlx5e_rss *rss; 80 int i; 81 82 for (i = 1; i < MLX5E_MAX_NUM_RSS; i++) 83 if (!res->rss[i]) 84 break; 85 86 if (i == MLX5E_MAX_NUM_RSS) 87 return -ENOSPC; 88 89 rss = mlx5e_rss_init(res->mdev, inner_ft_support, res->drop_rqn, 90 &res->pkt_merge_param, MLX5E_RSS_INIT_NO_TIRS, init_nch, 91 res->max_nch); 92 if (IS_ERR(rss)) 93 return PTR_ERR(rss); 94 95 mlx5e_rss_set_indir_uniform(rss, init_nch); 96 if (res->rss_active) { 97 u32 *vhca_ids = get_vhca_ids(res, 0); 98 99 mlx5e_rss_enable(rss, res->rss_rqns, vhca_ids, res->rss_nch); 100 } 101 102 res->rss[i] = rss; 103 *rss_idx = i; 104 105 return 0; 106} 107 108static int __mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx) 109{ 110 struct mlx5e_rss *rss = res->rss[rss_idx]; 111 int err; 112 113 err = mlx5e_rss_cleanup(rss); 114 if (err) 115 return err; 116 117 res->rss[rss_idx] = NULL; 118 119 return 0; 120} 121 122int mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx) 123{ 124 struct mlx5e_rss *rss; 125 126 if (rss_idx >= MLX5E_MAX_NUM_RSS) 127 return -EINVAL; 128 129 rss = res->rss[rss_idx]; 130 if (!rss) 131 return -EINVAL; 132 133 return __mlx5e_rx_res_rss_destroy(res, rss_idx); 134} 135 136static void mlx5e_rx_res_rss_destroy_all(struct mlx5e_rx_res *res) 137{ 138 int i; 139 140 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) { 141 struct mlx5e_rss *rss = res->rss[i]; 142 int err; 143 144 if (!rss) 145 continue; 146 147 err = __mlx5e_rx_res_rss_destroy(res, i); 148 if (err) { 149 unsigned int refcount; 150 151 refcount = mlx5e_rss_refcnt_read(rss); 152 mlx5_core_warn(res->mdev, 153 "Failed to destroy RSS context %d, refcount = %u, err = %d\n", 154 i, refcount, err); 155 } 156 } 157} 158 159static void mlx5e_rx_res_rss_enable(struct mlx5e_rx_res *res) 160{ 161 int i; 162 163 res->rss_active = true; 164 165 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) { 166 struct mlx5e_rss *rss = res->rss[i]; 167 u32 *vhca_ids; 168 169 if (!rss) 170 continue; 171 vhca_ids = get_vhca_ids(res, 0); 172 mlx5e_rss_enable(rss, res->rss_rqns, vhca_ids, res->rss_nch); 173 } 174} 175 176static void mlx5e_rx_res_rss_disable(struct mlx5e_rx_res *res) 177{ 178 int i; 179 180 res->rss_active = false; 181 182 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) { 183 struct mlx5e_rss *rss = res->rss[i]; 184 185 if (!rss) 186 continue; 187 mlx5e_rss_disable(rss); 188 } 189} 190 191/* Updates the indirection table SW shadow, does not update the HW resources yet */ 192void mlx5e_rx_res_rss_set_indir_uniform(struct mlx5e_rx_res *res, unsigned int nch) 193{ 194 WARN_ON_ONCE(res->rss_active); 195 mlx5e_rss_set_indir_uniform(res->rss[0], nch); 196} 197 198int mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx, 199 u32 *indir, u8 *key, u8 *hfunc) 200{ 201 struct mlx5e_rss *rss; 202 203 if (rss_idx >= MLX5E_MAX_NUM_RSS) 204 return -EINVAL; 205 206 rss = res->rss[rss_idx]; 207 if (!rss) 208 return -ENOENT; 209 210 return mlx5e_rss_get_rxfh(rss, indir, key, hfunc); 211} 212 213int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx, 214 const u32 *indir, const u8 *key, const u8 *hfunc) 215{ 216 u32 *vhca_ids = get_vhca_ids(res, 0); 217 struct mlx5e_rss *rss; 218 219 if (rss_idx >= MLX5E_MAX_NUM_RSS) 220 return -EINVAL; 221 222 rss = res->rss[rss_idx]; 223 if (!rss) 224 return -ENOENT; 225 226 return mlx5e_rss_set_rxfh(rss, indir, key, hfunc, res->rss_rqns, vhca_ids, 227 res->rss_nch); 228} 229 230int mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx, 231 enum mlx5_traffic_types tt) 232{ 233 struct mlx5e_rss *rss; 234 235 if (rss_idx >= MLX5E_MAX_NUM_RSS) 236 return -EINVAL; 237 238 rss = res->rss[rss_idx]; 239 if (!rss) 240 return -ENOENT; 241 242 return mlx5e_rss_get_hash_fields(rss, tt); 243} 244 245int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx, 246 enum mlx5_traffic_types tt, u8 rx_hash_fields) 247{ 248 struct mlx5e_rss *rss; 249 250 if (rss_idx >= MLX5E_MAX_NUM_RSS) 251 return -EINVAL; 252 253 rss = res->rss[rss_idx]; 254 if (!rss) 255 return -ENOENT; 256 257 return mlx5e_rss_set_hash_fields(rss, tt, rx_hash_fields); 258} 259 260int mlx5e_rx_res_rss_cnt(struct mlx5e_rx_res *res) 261{ 262 int i, cnt; 263 264 cnt = 0; 265 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) 266 if (res->rss[i]) 267 cnt++; 268 269 return cnt; 270} 271 272int mlx5e_rx_res_rss_index(struct mlx5e_rx_res *res, struct mlx5e_rss *rss) 273{ 274 int i; 275 276 if (!rss) 277 return -EINVAL; 278 279 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) 280 if (rss == res->rss[i]) 281 return i; 282 283 return -ENOENT; 284} 285 286struct mlx5e_rss *mlx5e_rx_res_rss_get(struct mlx5e_rx_res *res, u32 rss_idx) 287{ 288 if (rss_idx >= MLX5E_MAX_NUM_RSS) 289 return NULL; 290 291 return res->rss[rss_idx]; 292} 293 294/* End of API rx_res_rss_* */ 295 296static void mlx5e_rx_res_free(struct mlx5e_rx_res *res) 297{ 298 kvfree(res->rss_vhca_ids); 299 kvfree(res->rss_rqns); 300 kvfree(res); 301} 302 303static struct mlx5e_rx_res *mlx5e_rx_res_alloc(struct mlx5_core_dev *mdev, unsigned int max_nch, 304 bool multi_vhca) 305{ 306 struct mlx5e_rx_res *rx_res; 307 308 rx_res = kvzalloc(sizeof(*rx_res), GFP_KERNEL); 309 if (!rx_res) 310 return NULL; 311 312 rx_res->rss_rqns = kvcalloc(max_nch, sizeof(*rx_res->rss_rqns), GFP_KERNEL); 313 if (!rx_res->rss_rqns) { 314 kvfree(rx_res); 315 return NULL; 316 } 317 318 if (multi_vhca) { 319 rx_res->rss_vhca_ids = kvcalloc(max_nch, sizeof(*rx_res->rss_vhca_ids), GFP_KERNEL); 320 if (!rx_res->rss_vhca_ids) { 321 kvfree(rx_res->rss_rqns); 322 kvfree(rx_res); 323 return NULL; 324 } 325 } 326 327 return rx_res; 328} 329 330static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res) 331{ 332 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; 333 struct mlx5e_tir_builder *builder; 334 int err = 0; 335 int ix; 336 337 builder = mlx5e_tir_builder_alloc(false); 338 if (!builder) 339 return -ENOMEM; 340 341 res->channels = kvcalloc(res->max_nch, sizeof(*res->channels), GFP_KERNEL); 342 if (!res->channels) { 343 err = -ENOMEM; 344 goto out; 345 } 346 347 for (ix = 0; ix < res->max_nch; ix++) { 348 err = mlx5e_rqt_init_direct(&res->channels[ix].direct_rqt, 349 res->mdev, false, res->drop_rqn, 350 mlx5e_rqt_size(res->mdev, res->max_nch)); 351 if (err) { 352 mlx5_core_warn(res->mdev, "Failed to create a direct RQT: err = %d, ix = %u\n", 353 err, ix); 354 goto err_destroy_direct_rqts; 355 } 356 } 357 358 for (ix = 0; ix < res->max_nch; ix++) { 359 mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, 360 mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt), 361 inner_ft_support); 362 mlx5e_tir_builder_build_packet_merge(builder, &res->pkt_merge_param); 363 mlx5e_tir_builder_build_direct(builder); 364 365 err = mlx5e_tir_init(&res->channels[ix].direct_tir, builder, res->mdev, true); 366 if (err) { 367 mlx5_core_warn(res->mdev, "Failed to create a direct TIR: err = %d, ix = %u\n", 368 err, ix); 369 goto err_destroy_direct_tirs; 370 } 371 372 mlx5e_tir_builder_clear(builder); 373 } 374 375 goto out; 376 377err_destroy_direct_tirs: 378 while (--ix >= 0) 379 mlx5e_tir_destroy(&res->channels[ix].direct_tir); 380 381 ix = res->max_nch; 382err_destroy_direct_rqts: 383 while (--ix >= 0) 384 mlx5e_rqt_destroy(&res->channels[ix].direct_rqt); 385 386 kvfree(res->channels); 387 388out: 389 mlx5e_tir_builder_free(builder); 390 391 return err; 392} 393 394static int mlx5e_rx_res_ptp_init(struct mlx5e_rx_res *res) 395{ 396 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; 397 struct mlx5e_tir_builder *builder; 398 int err; 399 400 builder = mlx5e_tir_builder_alloc(false); 401 if (!builder) 402 return -ENOMEM; 403 404 err = mlx5e_rqt_init_direct(&res->ptp.rqt, res->mdev, false, res->drop_rqn, 405 mlx5e_rqt_size(res->mdev, res->max_nch)); 406 if (err) 407 goto out; 408 409 /* Separated from the channels RQs, does not share pkt_merge state with them */ 410 mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, 411 mlx5e_rqt_get_rqtn(&res->ptp.rqt), 412 inner_ft_support); 413 mlx5e_tir_builder_build_direct(builder); 414 415 err = mlx5e_tir_init(&res->ptp.tir, builder, res->mdev, true); 416 if (err) 417 goto err_destroy_ptp_rqt; 418 419 goto out; 420 421err_destroy_ptp_rqt: 422 mlx5e_rqt_destroy(&res->ptp.rqt); 423 424out: 425 mlx5e_tir_builder_free(builder); 426 return err; 427} 428 429static void mlx5e_rx_res_channels_destroy(struct mlx5e_rx_res *res) 430{ 431 unsigned int ix; 432 433 for (ix = 0; ix < res->max_nch; ix++) { 434 mlx5e_tir_destroy(&res->channels[ix].direct_tir); 435 mlx5e_rqt_destroy(&res->channels[ix].direct_rqt); 436 } 437 438 kvfree(res->channels); 439} 440 441static void mlx5e_rx_res_ptp_destroy(struct mlx5e_rx_res *res) 442{ 443 mlx5e_tir_destroy(&res->ptp.tir); 444 mlx5e_rqt_destroy(&res->ptp.rqt); 445} 446 447struct mlx5e_rx_res * 448mlx5e_rx_res_create(struct mlx5_core_dev *mdev, enum mlx5e_rx_res_features features, 449 unsigned int max_nch, u32 drop_rqn, 450 const struct mlx5e_packet_merge_param *init_pkt_merge_param, 451 unsigned int init_nch) 452{ 453 bool multi_vhca = features & MLX5E_RX_RES_FEATURE_MULTI_VHCA; 454 struct mlx5e_rx_res *res; 455 int err; 456 457 res = mlx5e_rx_res_alloc(mdev, max_nch, multi_vhca); 458 if (!res) 459 return ERR_PTR(-ENOMEM); 460 461 res->mdev = mdev; 462 res->features = features; 463 res->max_nch = max_nch; 464 res->drop_rqn = drop_rqn; 465 466 res->pkt_merge_param = *init_pkt_merge_param; 467 init_rwsem(&res->pkt_merge_param_sem); 468 469 err = mlx5e_rx_res_rss_init_def(res, init_nch); 470 if (err) 471 goto err_rx_res_free; 472 473 err = mlx5e_rx_res_channels_init(res); 474 if (err) 475 goto err_rss_destroy; 476 477 err = mlx5e_rx_res_ptp_init(res); 478 if (err) 479 goto err_channels_destroy; 480 481 return res; 482 483err_channels_destroy: 484 mlx5e_rx_res_channels_destroy(res); 485err_rss_destroy: 486 __mlx5e_rx_res_rss_destroy(res, 0); 487err_rx_res_free: 488 mlx5e_rx_res_free(res); 489 return ERR_PTR(err); 490} 491 492void mlx5e_rx_res_destroy(struct mlx5e_rx_res *res) 493{ 494 mlx5e_rx_res_ptp_destroy(res); 495 mlx5e_rx_res_channels_destroy(res); 496 mlx5e_rx_res_rss_destroy_all(res); 497 mlx5e_rx_res_free(res); 498} 499 500u32 mlx5e_rx_res_get_tirn_direct(struct mlx5e_rx_res *res, unsigned int ix) 501{ 502 return mlx5e_tir_get_tirn(&res->channels[ix].direct_tir); 503} 504 505u32 mlx5e_rx_res_get_tirn_rss(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt) 506{ 507 struct mlx5e_rss *rss = res->rss[0]; 508 509 return mlx5e_rss_get_tirn(rss, tt, false); 510} 511 512u32 mlx5e_rx_res_get_tirn_rss_inner(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt) 513{ 514 struct mlx5e_rss *rss = res->rss[0]; 515 516 return mlx5e_rss_get_tirn(rss, tt, true); 517} 518 519u32 mlx5e_rx_res_get_tirn_ptp(struct mlx5e_rx_res *res) 520{ 521 WARN_ON(!(res->features & MLX5E_RX_RES_FEATURE_PTP)); 522 return mlx5e_tir_get_tirn(&res->ptp.tir); 523} 524 525static u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix) 526{ 527 return mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt); 528} 529 530static void mlx5e_rx_res_channel_activate_direct(struct mlx5e_rx_res *res, 531 struct mlx5e_channels *chs, 532 unsigned int ix) 533{ 534 u32 *vhca_id = get_vhca_ids(res, ix); 535 u32 rqn = res->rss_rqns[ix]; 536 int err; 537 538 err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, rqn, vhca_id); 539 if (err) 540 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to RQ %#x (channel %u): err = %d\n", 541 mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt), 542 rqn, ix, err); 543} 544 545static void mlx5e_rx_res_channel_deactivate_direct(struct mlx5e_rx_res *res, 546 unsigned int ix) 547{ 548 int err; 549 550 err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, res->drop_rqn, NULL); 551 if (err) 552 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (channel %u): err = %d\n", 553 mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt), 554 res->drop_rqn, ix, err); 555} 556 557void mlx5e_rx_res_channels_activate(struct mlx5e_rx_res *res, struct mlx5e_channels *chs) 558{ 559 unsigned int nch, ix; 560 int err; 561 562 nch = mlx5e_channels_get_num(chs); 563 564 for (ix = 0; ix < chs->num; ix++) { 565 u32 *vhca_id = get_vhca_ids(res, ix); 566 567 if (mlx5e_channels_is_xsk(chs, ix)) 568 mlx5e_channels_get_xsk_rqn(chs, ix, &res->rss_rqns[ix], vhca_id); 569 else 570 mlx5e_channels_get_regular_rqn(chs, ix, &res->rss_rqns[ix], vhca_id); 571 } 572 res->rss_nch = chs->num; 573 574 mlx5e_rx_res_rss_enable(res); 575 576 for (ix = 0; ix < nch; ix++) 577 mlx5e_rx_res_channel_activate_direct(res, chs, ix); 578 for (ix = nch; ix < res->max_nch; ix++) 579 mlx5e_rx_res_channel_deactivate_direct(res, ix); 580 581 if (res->features & MLX5E_RX_RES_FEATURE_PTP) { 582 u32 rqn; 583 584 if (!mlx5e_channels_get_ptp_rqn(chs, &rqn)) 585 rqn = res->drop_rqn; 586 587 err = mlx5e_rqt_redirect_direct(&res->ptp.rqt, rqn, NULL); 588 if (err) 589 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to RQ %#x (PTP): err = %d\n", 590 mlx5e_rqt_get_rqtn(&res->ptp.rqt), 591 rqn, err); 592 } 593} 594 595void mlx5e_rx_res_channels_deactivate(struct mlx5e_rx_res *res) 596{ 597 unsigned int ix; 598 int err; 599 600 mlx5e_rx_res_rss_disable(res); 601 602 for (ix = 0; ix < res->max_nch; ix++) 603 mlx5e_rx_res_channel_deactivate_direct(res, ix); 604 605 if (res->features & MLX5E_RX_RES_FEATURE_PTP) { 606 err = mlx5e_rqt_redirect_direct(&res->ptp.rqt, res->drop_rqn, NULL); 607 if (err) 608 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (PTP): err = %d\n", 609 mlx5e_rqt_get_rqtn(&res->ptp.rqt), 610 res->drop_rqn, err); 611 } 612} 613 614void mlx5e_rx_res_xsk_update(struct mlx5e_rx_res *res, struct mlx5e_channels *chs, 615 unsigned int ix, bool xsk) 616{ 617 u32 *vhca_id = get_vhca_ids(res, ix); 618 619 if (xsk) 620 mlx5e_channels_get_xsk_rqn(chs, ix, &res->rss_rqns[ix], vhca_id); 621 else 622 mlx5e_channels_get_regular_rqn(chs, ix, &res->rss_rqns[ix], vhca_id); 623 624 mlx5e_rx_res_rss_enable(res); 625 626 mlx5e_rx_res_channel_activate_direct(res, chs, ix); 627} 628 629int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res, 630 struct mlx5e_packet_merge_param *pkt_merge_param) 631{ 632 struct mlx5e_tir_builder *builder; 633 int err, final_err; 634 unsigned int ix; 635 636 builder = mlx5e_tir_builder_alloc(true); 637 if (!builder) 638 return -ENOMEM; 639 640 down_write(&res->pkt_merge_param_sem); 641 res->pkt_merge_param = *pkt_merge_param; 642 643 mlx5e_tir_builder_build_packet_merge(builder, pkt_merge_param); 644 645 final_err = 0; 646 647 for (ix = 0; ix < MLX5E_MAX_NUM_RSS; ix++) { 648 struct mlx5e_rss *rss = res->rss[ix]; 649 650 if (!rss) 651 continue; 652 653 err = mlx5e_rss_packet_merge_set_param(rss, pkt_merge_param); 654 if (err) 655 final_err = final_err ? : err; 656 } 657 658 for (ix = 0; ix < res->max_nch; ix++) { 659 err = mlx5e_tir_modify(&res->channels[ix].direct_tir, builder); 660 if (err) { 661 mlx5_core_warn(res->mdev, "Failed to update packet merge state of direct TIR %#x for channel %u: err = %d\n", 662 mlx5e_tir_get_tirn(&res->channels[ix].direct_tir), ix, err); 663 if (!final_err) 664 final_err = err; 665 } 666 } 667 668 up_write(&res->pkt_merge_param_sem); 669 mlx5e_tir_builder_free(builder); 670 return final_err; 671} 672 673struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res *res) 674{ 675 return mlx5e_rss_get_hash(res->rss[0]); 676} 677 678int mlx5e_rx_res_tls_tir_create(struct mlx5e_rx_res *res, unsigned int rxq, 679 struct mlx5e_tir *tir) 680{ 681 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; 682 struct mlx5e_tir_builder *builder; 683 u32 rqtn; 684 int err; 685 686 builder = mlx5e_tir_builder_alloc(false); 687 if (!builder) 688 return -ENOMEM; 689 690 rqtn = mlx5e_rx_res_get_rqtn_direct(res, rxq); 691 692 mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, rqtn, 693 inner_ft_support); 694 mlx5e_tir_builder_build_direct(builder); 695 mlx5e_tir_builder_build_tls(builder); 696 down_read(&res->pkt_merge_param_sem); 697 mlx5e_tir_builder_build_packet_merge(builder, &res->pkt_merge_param); 698 err = mlx5e_tir_init(tir, builder, res->mdev, false); 699 up_read(&res->pkt_merge_param_sem); 700 701 mlx5e_tir_builder_free(builder); 702 703 return err; 704} 705