1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */
5 #include <linux/mlx5/transobj.h>
7 void mlx5e_rss_params_indir_init_uniform(struct mlx5e_rss_params_indir *indir,
8 unsigned int num_channels)
12 for (i = 0; i < indir->actual_table_size; i++)
13 indir->table[i] = i % num_channels;
16 static int mlx5e_rqt_init(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev,
17 u16 max_size, u32 *init_rqns, u16 init_size)
28 inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * init_size;
29 in = kvzalloc(inlen, GFP_KERNEL);
33 rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context);
35 MLX5_SET(rqtc, rqtc, rqt_max_size, rqt->size);
37 MLX5_SET(rqtc, rqtc, rqt_actual_size, init_size);
38 for (i = 0; i < init_size; i++)
39 MLX5_SET(rqtc, rqtc, rq_num[i], init_rqns[i]);
41 err = mlx5_core_create_rqt(rqt->mdev, in, inlen, &rqt->rqtn);
47 int mlx5e_rqt_init_direct(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev,
48 bool indir_enabled, u32 init_rqn, u32 indir_table_size)
50 u16 max_size = indir_enabled ? indir_table_size : 1;
52 return mlx5e_rqt_init(rqt, mdev, max_size, &init_rqn, 1);
55 static int mlx5e_bits_invert(unsigned long a, int size)
60 for (i = 0; i < size; i++)
61 inv |= (test_bit(size - i - 1, &a) ? 1 : 0) << i;
66 static int mlx5e_calc_indir_rqns(u32 *rss_rqns, u32 *rqns, unsigned int num_rqns,
67 u8 hfunc, struct mlx5e_rss_params_indir *indir)
71 for (i = 0; i < indir->actual_table_size; i++) {
74 if (hfunc == ETH_RSS_HASH_XOR)
75 ix = mlx5e_bits_invert(ix, ilog2(indir->actual_table_size));
77 ix = indir->table[ix];
79 if (WARN_ON(ix >= num_rqns))
80 /* Could be a bug in the driver or in the kernel part of
81 * ethtool: indir table refers to non-existent RQs.
84 rss_rqns[i] = rqns[ix];
90 int mlx5e_rqt_init_indir(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev,
91 u32 *rqns, unsigned int num_rqns,
92 u8 hfunc, struct mlx5e_rss_params_indir *indir)
97 rss_rqns = kvmalloc_array(indir->actual_table_size, sizeof(*rss_rqns), GFP_KERNEL);
101 err = mlx5e_calc_indir_rqns(rss_rqns, rqns, num_rqns, hfunc, indir);
105 err = mlx5e_rqt_init(rqt, mdev, indir->max_table_size, rss_rqns,
106 indir->actual_table_size);
113 #define MLX5E_UNIFORM_SPREAD_RQT_FACTOR 2
115 u32 mlx5e_rqt_size(struct mlx5_core_dev *mdev, unsigned int num_channels)
117 u32 rqt_size = max_t(u32, MLX5E_INDIR_MIN_RQT_SIZE,
118 roundup_pow_of_two(num_channels * MLX5E_UNIFORM_SPREAD_RQT_FACTOR));
119 u32 max_cap_rqt_size = 1 << MLX5_CAP_GEN(mdev, log_max_rqt_size);
121 return min_t(u32, rqt_size, max_cap_rqt_size);
124 void mlx5e_rqt_destroy(struct mlx5e_rqt *rqt)
126 mlx5_core_destroy_rqt(rqt->mdev, rqt->rqtn);
129 static int mlx5e_rqt_redirect(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int size)
137 inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + sizeof(u32) * size;
138 in = kvzalloc(inlen, GFP_KERNEL);
142 rqtc = MLX5_ADDR_OF(modify_rqt_in, in, ctx);
144 MLX5_SET(modify_rqt_in, in, bitmask.rqn_list, 1);
145 MLX5_SET(rqtc, rqtc, rqt_actual_size, size);
146 for (i = 0; i < size; i++)
147 MLX5_SET(rqtc, rqtc, rq_num[i], rqns[i]);
149 err = mlx5_core_modify_rqt(rqt->mdev, rqt->rqtn, in, inlen);
155 int mlx5e_rqt_redirect_direct(struct mlx5e_rqt *rqt, u32 rqn)
157 return mlx5e_rqt_redirect(rqt, &rqn, 1);
160 int mlx5e_rqt_redirect_indir(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int num_rqns,
161 u8 hfunc, struct mlx5e_rss_params_indir *indir)
166 if (WARN_ON(rqt->size != indir->max_table_size))
169 rss_rqns = kvmalloc_array(indir->actual_table_size, sizeof(*rss_rqns), GFP_KERNEL);
173 err = mlx5e_calc_indir_rqns(rss_rqns, rqns, num_rqns, hfunc, indir);
177 err = mlx5e_rqt_redirect(rqt, rss_rqns, indir->actual_table_size);