rqt.c (3937B)
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */ 3 4#include "rqt.h" 5#include <linux/mlx5/transobj.h> 6 7void mlx5e_rss_params_indir_init_uniform(struct mlx5e_rss_params_indir *indir, 8 unsigned int num_channels) 9{ 10 unsigned int i; 11 12 for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++) 13 indir->table[i] = i % num_channels; 14} 15 16static int mlx5e_rqt_init(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev, 17 u16 max_size, u32 *init_rqns, u16 init_size) 18{ 19 void *rqtc; 20 int inlen; 21 int err; 22 u32 *in; 23 int i; 24 25 rqt->mdev = mdev; 26 rqt->size = max_size; 27 28 inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * init_size; 29 in = kvzalloc(inlen, GFP_KERNEL); 30 if (!in) 31 return -ENOMEM; 32 33 rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context); 34 35 MLX5_SET(rqtc, rqtc, rqt_max_size, rqt->size); 36 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]); 40 41 err = mlx5_core_create_rqt(rqt->mdev, in, inlen, &rqt->rqtn); 42 43 kvfree(in); 44 return err; 45} 46 47int mlx5e_rqt_init_direct(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev, 48 bool indir_enabled, u32 init_rqn) 49{ 50 u16 max_size = indir_enabled ? MLX5E_INDIR_RQT_SIZE : 1; 51 52 return mlx5e_rqt_init(rqt, mdev, max_size, &init_rqn, 1); 53} 54 55static int mlx5e_bits_invert(unsigned long a, int size) 56{ 57 int inv = 0; 58 int i; 59 60 for (i = 0; i < size; i++) 61 inv |= (test_bit(size - i - 1, &a) ? 1 : 0) << i; 62 63 return inv; 64} 65 66static int mlx5e_calc_indir_rqns(u32 *rss_rqns, u32 *rqns, unsigned int num_rqns, 67 u8 hfunc, struct mlx5e_rss_params_indir *indir) 68{ 69 unsigned int i; 70 71 for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++) { 72 unsigned int ix = i; 73 74 if (hfunc == ETH_RSS_HASH_XOR) 75 ix = mlx5e_bits_invert(ix, ilog2(MLX5E_INDIR_RQT_SIZE)); 76 77 ix = indir->table[ix]; 78 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. 82 */ 83 return -EINVAL; 84 rss_rqns[i] = rqns[ix]; 85 } 86 87 return 0; 88} 89 90int 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) 93{ 94 u32 *rss_rqns; 95 int err; 96 97 rss_rqns = kvmalloc_array(MLX5E_INDIR_RQT_SIZE, sizeof(*rss_rqns), GFP_KERNEL); 98 if (!rss_rqns) 99 return -ENOMEM; 100 101 err = mlx5e_calc_indir_rqns(rss_rqns, rqns, num_rqns, hfunc, indir); 102 if (err) 103 goto out; 104 105 err = mlx5e_rqt_init(rqt, mdev, MLX5E_INDIR_RQT_SIZE, rss_rqns, MLX5E_INDIR_RQT_SIZE); 106 107out: 108 kvfree(rss_rqns); 109 return err; 110} 111 112void mlx5e_rqt_destroy(struct mlx5e_rqt *rqt) 113{ 114 mlx5_core_destroy_rqt(rqt->mdev, rqt->rqtn); 115} 116 117static int mlx5e_rqt_redirect(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int size) 118{ 119 unsigned int i; 120 void *rqtc; 121 int inlen; 122 u32 *in; 123 int err; 124 125 inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + sizeof(u32) * size; 126 in = kvzalloc(inlen, GFP_KERNEL); 127 if (!in) 128 return -ENOMEM; 129 130 rqtc = MLX5_ADDR_OF(modify_rqt_in, in, ctx); 131 132 MLX5_SET(modify_rqt_in, in, bitmask.rqn_list, 1); 133 MLX5_SET(rqtc, rqtc, rqt_actual_size, size); 134 for (i = 0; i < size; i++) 135 MLX5_SET(rqtc, rqtc, rq_num[i], rqns[i]); 136 137 err = mlx5_core_modify_rqt(rqt->mdev, rqt->rqtn, in, inlen); 138 139 kvfree(in); 140 return err; 141} 142 143int mlx5e_rqt_redirect_direct(struct mlx5e_rqt *rqt, u32 rqn) 144{ 145 return mlx5e_rqt_redirect(rqt, &rqn, 1); 146} 147 148int mlx5e_rqt_redirect_indir(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int num_rqns, 149 u8 hfunc, struct mlx5e_rss_params_indir *indir) 150{ 151 u32 *rss_rqns; 152 int err; 153 154 if (WARN_ON(rqt->size != MLX5E_INDIR_RQT_SIZE)) 155 return -EINVAL; 156 157 rss_rqns = kvmalloc_array(MLX5E_INDIR_RQT_SIZE, sizeof(*rss_rqns), GFP_KERNEL); 158 if (!rss_rqns) 159 return -ENOMEM; 160 161 err = mlx5e_calc_indir_rqns(rss_rqns, rqns, num_rqns, hfunc, indir); 162 if (err) 163 goto out; 164 165 err = mlx5e_rqt_redirect(rqt, rss_rqns, MLX5E_INDIR_RQT_SIZE); 166 167out: 168 kvfree(rss_rqns); 169 return err; 170}