0001
0002
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
0081
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 }