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