Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
0002 /* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */
0003 
0004 #include "rqt.h"
0005 #include <linux/mlx5/transobj.h>
0006 
0007 void mlx5e_rss_params_indir_init_uniform(struct mlx5e_rss_params_indir *indir,
0008                      unsigned int num_channels)
0009 {
0010     unsigned int i;
0011 
0012     for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
0013         indir->table[i] = i % num_channels;
0014 }
0015 
0016 static int mlx5e_rqt_init(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev,
0017               u16 max_size, u32 *init_rqns, u16 init_size)
0018 {
0019     void *rqtc;
0020     int inlen;
0021     int err;
0022     u32 *in;
0023     int i;
0024 
0025     rqt->mdev = mdev;
0026     rqt->size = max_size;
0027 
0028     inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * init_size;
0029     in = kvzalloc(inlen, GFP_KERNEL);
0030     if (!in)
0031         return -ENOMEM;
0032 
0033     rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context);
0034 
0035     MLX5_SET(rqtc, rqtc, rqt_max_size, rqt->size);
0036 
0037     MLX5_SET(rqtc, rqtc, rqt_actual_size, init_size);
0038     for (i = 0; i < init_size; i++)
0039         MLX5_SET(rqtc, rqtc, rq_num[i], init_rqns[i]);
0040 
0041     err = mlx5_core_create_rqt(rqt->mdev, in, inlen, &rqt->rqtn);
0042 
0043     kvfree(in);
0044     return err;
0045 }
0046 
0047 int mlx5e_rqt_init_direct(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev,
0048               bool indir_enabled, u32 init_rqn)
0049 {
0050     u16 max_size = indir_enabled ? MLX5E_INDIR_RQT_SIZE : 1;
0051 
0052     return mlx5e_rqt_init(rqt, mdev, max_size, &init_rqn, 1);
0053 }
0054 
0055 static int mlx5e_bits_invert(unsigned long a, int size)
0056 {
0057     int inv = 0;
0058     int i;
0059 
0060     for (i = 0; i < size; i++)
0061         inv |= (test_bit(size - i - 1, &a) ? 1 : 0) << i;
0062 
0063     return inv;
0064 }
0065 
0066 static int mlx5e_calc_indir_rqns(u32 *rss_rqns, u32 *rqns, unsigned int num_rqns,
0067                  u8 hfunc, struct mlx5e_rss_params_indir *indir)
0068 {
0069     unsigned int i;
0070 
0071     for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++) {
0072         unsigned int ix = i;
0073 
0074         if (hfunc == ETH_RSS_HASH_XOR)
0075             ix = mlx5e_bits_invert(ix, ilog2(MLX5E_INDIR_RQT_SIZE));
0076 
0077         ix = indir->table[ix];
0078 
0079         if (WARN_ON(ix >= num_rqns))
0080             /* Could be a bug in the driver or in the kernel part of
0081              * ethtool: indir table refers to non-existent RQs.
0082              */
0083             return -EINVAL;
0084         rss_rqns[i] = rqns[ix];
0085     }
0086 
0087     return 0;
0088 }
0089 
0090 int mlx5e_rqt_init_indir(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev,
0091              u32 *rqns, unsigned int num_rqns,
0092              u8 hfunc, struct mlx5e_rss_params_indir *indir)
0093 {
0094     u32 *rss_rqns;
0095     int err;
0096 
0097     rss_rqns = kvmalloc_array(MLX5E_INDIR_RQT_SIZE, sizeof(*rss_rqns), GFP_KERNEL);
0098     if (!rss_rqns)
0099         return -ENOMEM;
0100 
0101     err = mlx5e_calc_indir_rqns(rss_rqns, rqns, num_rqns, hfunc, indir);
0102     if (err)
0103         goto out;
0104 
0105     err = mlx5e_rqt_init(rqt, mdev, MLX5E_INDIR_RQT_SIZE, rss_rqns, MLX5E_INDIR_RQT_SIZE);
0106 
0107 out:
0108     kvfree(rss_rqns);
0109     return err;
0110 }
0111 
0112 void mlx5e_rqt_destroy(struct mlx5e_rqt *rqt)
0113 {
0114     mlx5_core_destroy_rqt(rqt->mdev, rqt->rqtn);
0115 }
0116 
0117 static int mlx5e_rqt_redirect(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int size)
0118 {
0119     unsigned int i;
0120     void *rqtc;
0121     int inlen;
0122     u32 *in;
0123     int err;
0124 
0125     inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + sizeof(u32) * size;
0126     in = kvzalloc(inlen, GFP_KERNEL);
0127     if (!in)
0128         return -ENOMEM;
0129 
0130     rqtc = MLX5_ADDR_OF(modify_rqt_in, in, ctx);
0131 
0132     MLX5_SET(modify_rqt_in, in, bitmask.rqn_list, 1);
0133     MLX5_SET(rqtc, rqtc, rqt_actual_size, size);
0134     for (i = 0; i < size; i++)
0135         MLX5_SET(rqtc, rqtc, rq_num[i], rqns[i]);
0136 
0137     err = mlx5_core_modify_rqt(rqt->mdev, rqt->rqtn, in, inlen);
0138 
0139     kvfree(in);
0140     return err;
0141 }
0142 
0143 int mlx5e_rqt_redirect_direct(struct mlx5e_rqt *rqt, u32 rqn)
0144 {
0145     return mlx5e_rqt_redirect(rqt, &rqn, 1);
0146 }
0147 
0148 int mlx5e_rqt_redirect_indir(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int num_rqns,
0149                  u8 hfunc, struct mlx5e_rss_params_indir *indir)
0150 {
0151     u32 *rss_rqns;
0152     int err;
0153 
0154     if (WARN_ON(rqt->size != MLX5E_INDIR_RQT_SIZE))
0155         return -EINVAL;
0156 
0157     rss_rqns = kvmalloc_array(MLX5E_INDIR_RQT_SIZE, sizeof(*rss_rqns), GFP_KERNEL);
0158     if (!rss_rqns)
0159         return -ENOMEM;
0160 
0161     err = mlx5e_calc_indir_rqns(rss_rqns, rqns, num_rqns, hfunc, indir);
0162     if (err)
0163         goto out;
0164 
0165     err = mlx5e_rqt_redirect(rqt, rss_rqns, MLX5E_INDIR_RQT_SIZE);
0166 
0167 out:
0168     kvfree(rss_rqns);
0169     return err;
0170 }