xref: /dpdk/drivers/net/mlx5/mlx5_rss.c (revision b365799b3cd440437367b4539f1792eb65c86cc7)
12f97422eSNelio Laranjeiro /*-
22f97422eSNelio Laranjeiro  *   BSD LICENSE
32f97422eSNelio Laranjeiro  *
42f97422eSNelio Laranjeiro  *   Copyright 2015 6WIND S.A.
52f97422eSNelio Laranjeiro  *   Copyright 2015 Mellanox.
62f97422eSNelio Laranjeiro  *
72f97422eSNelio Laranjeiro  *   Redistribution and use in source and binary forms, with or without
82f97422eSNelio Laranjeiro  *   modification, are permitted provided that the following conditions
92f97422eSNelio Laranjeiro  *   are met:
102f97422eSNelio Laranjeiro  *
112f97422eSNelio Laranjeiro  *     * Redistributions of source code must retain the above copyright
122f97422eSNelio Laranjeiro  *       notice, this list of conditions and the following disclaimer.
132f97422eSNelio Laranjeiro  *     * Redistributions in binary form must reproduce the above copyright
142f97422eSNelio Laranjeiro  *       notice, this list of conditions and the following disclaimer in
152f97422eSNelio Laranjeiro  *       the documentation and/or other materials provided with the
162f97422eSNelio Laranjeiro  *       distribution.
172f97422eSNelio Laranjeiro  *     * Neither the name of 6WIND S.A. nor the names of its
182f97422eSNelio Laranjeiro  *       contributors may be used to endorse or promote products derived
192f97422eSNelio Laranjeiro  *       from this software without specific prior written permission.
202f97422eSNelio Laranjeiro  *
212f97422eSNelio Laranjeiro  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
222f97422eSNelio Laranjeiro  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
232f97422eSNelio Laranjeiro  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
242f97422eSNelio Laranjeiro  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
252f97422eSNelio Laranjeiro  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
262f97422eSNelio Laranjeiro  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
272f97422eSNelio Laranjeiro  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
282f97422eSNelio Laranjeiro  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
292f97422eSNelio Laranjeiro  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
302f97422eSNelio Laranjeiro  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
312f97422eSNelio Laranjeiro  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
322f97422eSNelio Laranjeiro  */
332f97422eSNelio Laranjeiro 
342f97422eSNelio Laranjeiro #include <stddef.h>
352f97422eSNelio Laranjeiro #include <stdint.h>
362f97422eSNelio Laranjeiro #include <errno.h>
372f97422eSNelio Laranjeiro #include <string.h>
382f97422eSNelio Laranjeiro #include <assert.h>
392f97422eSNelio Laranjeiro 
402f97422eSNelio Laranjeiro /* Verbs header. */
412f97422eSNelio Laranjeiro /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
422f97422eSNelio Laranjeiro #ifdef PEDANTIC
43fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic"
442f97422eSNelio Laranjeiro #endif
452f97422eSNelio Laranjeiro #include <infiniband/verbs.h>
462f97422eSNelio Laranjeiro #ifdef PEDANTIC
47fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic"
482f97422eSNelio Laranjeiro #endif
492f97422eSNelio Laranjeiro 
502f97422eSNelio Laranjeiro #include <rte_malloc.h>
512f97422eSNelio Laranjeiro #include <rte_ethdev.h>
522f97422eSNelio Laranjeiro 
532f97422eSNelio Laranjeiro #include "mlx5.h"
54*b365799bSNélio Laranjeiro #include "mlx5_defs.h"
552f97422eSNelio Laranjeiro #include "mlx5_rxtx.h"
562f97422eSNelio Laranjeiro 
572f97422eSNelio Laranjeiro /**
582f97422eSNelio Laranjeiro  * DPDK callback to update the RSS hash configuration.
592f97422eSNelio Laranjeiro  *
602f97422eSNelio Laranjeiro  * @param dev
612f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
622f97422eSNelio Laranjeiro  * @param[in] rss_conf
632f97422eSNelio Laranjeiro  *   RSS configuration data.
642f97422eSNelio Laranjeiro  *
652f97422eSNelio Laranjeiro  * @return
662f97422eSNelio Laranjeiro  *   0 on success, negative errno value on failure.
672f97422eSNelio Laranjeiro  */
682f97422eSNelio Laranjeiro int
692f97422eSNelio Laranjeiro mlx5_rss_hash_update(struct rte_eth_dev *dev,
702f97422eSNelio Laranjeiro 		     struct rte_eth_rss_conf *rss_conf)
712f97422eSNelio Laranjeiro {
722f97422eSNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
7329c1d8bbSNélio Laranjeiro 	int ret = 0;
742f97422eSNelio Laranjeiro 
752f97422eSNelio Laranjeiro 	priv_lock(priv);
76*b365799bSNélio Laranjeiro 	if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) {
77*b365799bSNélio Laranjeiro 		ret = -EINVAL;
78*b365799bSNélio Laranjeiro 		goto out;
79*b365799bSNélio Laranjeiro 	}
80920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key && rss_conf->rss_key_len) {
8129c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key,
8229c1d8bbSNélio Laranjeiro 						     rss_conf->rss_key_len, 0);
8329c1d8bbSNélio Laranjeiro 		if (!priv->rss_conf.rss_key) {
8429c1d8bbSNélio Laranjeiro 			ret = -ENOMEM;
8529c1d8bbSNélio Laranjeiro 			goto out;
8629c1d8bbSNélio Laranjeiro 		}
87920b4e54SNélio Laranjeiro 		memcpy(priv->rss_conf.rss_key, rss_conf->rss_key,
8829c1d8bbSNélio Laranjeiro 		       rss_conf->rss_key_len);
8929c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key_len = rss_conf->rss_key_len;
9029c1d8bbSNélio Laranjeiro 	}
9129c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = rss_conf->rss_hf;
9229c1d8bbSNélio Laranjeiro out:
932f97422eSNelio Laranjeiro 	priv_unlock(priv);
9429c1d8bbSNélio Laranjeiro 	return ret;
952f97422eSNelio Laranjeiro }
962f97422eSNelio Laranjeiro 
972f97422eSNelio Laranjeiro /**
982f97422eSNelio Laranjeiro  * DPDK callback to get the RSS hash configuration.
992f97422eSNelio Laranjeiro  *
1002f97422eSNelio Laranjeiro  * @param dev
1012f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
1022f97422eSNelio Laranjeiro  * @param[in, out] rss_conf
1032f97422eSNelio Laranjeiro  *   RSS configuration data.
1042f97422eSNelio Laranjeiro  *
1052f97422eSNelio Laranjeiro  * @return
1062f97422eSNelio Laranjeiro  *   0 on success, negative errno value on failure.
1072f97422eSNelio Laranjeiro  */
1082f97422eSNelio Laranjeiro int
1092f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev,
1102f97422eSNelio Laranjeiro 		       struct rte_eth_rss_conf *rss_conf)
1112f97422eSNelio Laranjeiro {
1122f97422eSNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
1132f97422eSNelio Laranjeiro 
114920b4e54SNélio Laranjeiro 	if (!rss_conf)
115920b4e54SNélio Laranjeiro 		return -EINVAL;
1162f97422eSNelio Laranjeiro 	priv_lock(priv);
117920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key &&
118920b4e54SNélio Laranjeiro 	    (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) {
11929c1d8bbSNélio Laranjeiro 		memcpy(rss_conf->rss_key, priv->rss_conf.rss_key,
12029c1d8bbSNélio Laranjeiro 		       priv->rss_conf.rss_key_len);
121920b4e54SNélio Laranjeiro 	}
122920b4e54SNélio Laranjeiro 	rss_conf->rss_key_len = priv->rss_conf.rss_key_len;
123920b4e54SNélio Laranjeiro 	rss_conf->rss_hf = priv->rss_conf.rss_hf;
1242f97422eSNelio Laranjeiro 	priv_unlock(priv);
125920b4e54SNélio Laranjeiro 	return 0;
1262f97422eSNelio Laranjeiro }
127634efbc2SNelio Laranjeiro 
128634efbc2SNelio Laranjeiro /**
129634efbc2SNelio Laranjeiro  * Allocate/reallocate RETA index table.
130634efbc2SNelio Laranjeiro  *
131634efbc2SNelio Laranjeiro  * @param priv
132634efbc2SNelio Laranjeiro  *   Pointer to private structure.
133634efbc2SNelio Laranjeiro  * @praram reta_size
134634efbc2SNelio Laranjeiro  *   The size of the array to allocate.
135634efbc2SNelio Laranjeiro  *
136634efbc2SNelio Laranjeiro  * @return
137634efbc2SNelio Laranjeiro  *   0 on success, errno value on failure.
138634efbc2SNelio Laranjeiro  */
139634efbc2SNelio Laranjeiro int
140634efbc2SNelio Laranjeiro priv_rss_reta_index_resize(struct priv *priv, unsigned int reta_size)
141634efbc2SNelio Laranjeiro {
142634efbc2SNelio Laranjeiro 	void *mem;
143634efbc2SNelio Laranjeiro 	unsigned int old_size = priv->reta_idx_n;
144634efbc2SNelio Laranjeiro 
145634efbc2SNelio Laranjeiro 	if (priv->reta_idx_n == reta_size)
146634efbc2SNelio Laranjeiro 		return 0;
147634efbc2SNelio Laranjeiro 
148634efbc2SNelio Laranjeiro 	mem = rte_realloc(priv->reta_idx,
149634efbc2SNelio Laranjeiro 			  reta_size * sizeof((*priv->reta_idx)[0]), 0);
150634efbc2SNelio Laranjeiro 	if (!mem)
151634efbc2SNelio Laranjeiro 		return ENOMEM;
152634efbc2SNelio Laranjeiro 	priv->reta_idx = mem;
153634efbc2SNelio Laranjeiro 	priv->reta_idx_n = reta_size;
154634efbc2SNelio Laranjeiro 
155634efbc2SNelio Laranjeiro 	if (old_size < reta_size)
156634efbc2SNelio Laranjeiro 		memset(&(*priv->reta_idx)[old_size], 0,
157634efbc2SNelio Laranjeiro 		       (reta_size - old_size) *
158634efbc2SNelio Laranjeiro 		       sizeof((*priv->reta_idx)[0]));
159634efbc2SNelio Laranjeiro 	return 0;
160634efbc2SNelio Laranjeiro }
161634efbc2SNelio Laranjeiro 
162634efbc2SNelio Laranjeiro /**
163634efbc2SNelio Laranjeiro  * Query RETA table.
164634efbc2SNelio Laranjeiro  *
165634efbc2SNelio Laranjeiro  * @param priv
166634efbc2SNelio Laranjeiro  *   Pointer to private structure.
167634efbc2SNelio Laranjeiro  * @param[in, out] reta_conf
168634efbc2SNelio Laranjeiro  *   Pointer to the first RETA configuration structure.
169634efbc2SNelio Laranjeiro  * @param reta_size
170634efbc2SNelio Laranjeiro  *   Number of entries.
171634efbc2SNelio Laranjeiro  *
172634efbc2SNelio Laranjeiro  * @return
173634efbc2SNelio Laranjeiro  *   0 on success, errno value on failure.
174634efbc2SNelio Laranjeiro  */
175634efbc2SNelio Laranjeiro static int
176634efbc2SNelio Laranjeiro priv_dev_rss_reta_query(struct priv *priv,
177634efbc2SNelio Laranjeiro 			struct rte_eth_rss_reta_entry64 *reta_conf,
178634efbc2SNelio Laranjeiro 			unsigned int reta_size)
179634efbc2SNelio Laranjeiro {
180634efbc2SNelio Laranjeiro 	unsigned int idx;
181634efbc2SNelio Laranjeiro 	unsigned int i;
182634efbc2SNelio Laranjeiro 
183d365210eSYongseok Koh 	if (!reta_size || reta_size > priv->reta_idx_n)
184d365210eSYongseok Koh 		return EINVAL;
185634efbc2SNelio Laranjeiro 	/* Fill each entry of the table even if its bit is not set. */
186634efbc2SNelio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
187634efbc2SNelio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
188634efbc2SNelio Laranjeiro 		reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] =
189634efbc2SNelio Laranjeiro 			(*priv->reta_idx)[i];
190634efbc2SNelio Laranjeiro 	}
191634efbc2SNelio Laranjeiro 	return 0;
192634efbc2SNelio Laranjeiro }
193634efbc2SNelio Laranjeiro 
194634efbc2SNelio Laranjeiro /**
195634efbc2SNelio Laranjeiro  * Update RETA table.
196634efbc2SNelio Laranjeiro  *
197634efbc2SNelio Laranjeiro  * @param priv
198634efbc2SNelio Laranjeiro  *   Pointer to private structure.
199634efbc2SNelio Laranjeiro  * @param[in] reta_conf
200634efbc2SNelio Laranjeiro  *   Pointer to the first RETA configuration structure.
201634efbc2SNelio Laranjeiro  * @param reta_size
202634efbc2SNelio Laranjeiro  *   Number of entries.
203634efbc2SNelio Laranjeiro  *
204634efbc2SNelio Laranjeiro  * @return
205634efbc2SNelio Laranjeiro  *   0 on success, errno value on failure.
206634efbc2SNelio Laranjeiro  */
207634efbc2SNelio Laranjeiro static int
208634efbc2SNelio Laranjeiro priv_dev_rss_reta_update(struct priv *priv,
209634efbc2SNelio Laranjeiro 			 struct rte_eth_rss_reta_entry64 *reta_conf,
210634efbc2SNelio Laranjeiro 			 unsigned int reta_size)
211634efbc2SNelio Laranjeiro {
212634efbc2SNelio Laranjeiro 	unsigned int idx;
213634efbc2SNelio Laranjeiro 	unsigned int i;
214634efbc2SNelio Laranjeiro 	unsigned int pos;
215634efbc2SNelio Laranjeiro 	int ret;
216634efbc2SNelio Laranjeiro 
217d365210eSYongseok Koh 	if (!reta_size)
218d365210eSYongseok Koh 		return EINVAL;
219d365210eSYongseok Koh 	ret = priv_rss_reta_index_resize(priv, reta_size);
220634efbc2SNelio Laranjeiro 	if (ret)
221634efbc2SNelio Laranjeiro 		return ret;
222634efbc2SNelio Laranjeiro 
223634efbc2SNelio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
224634efbc2SNelio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
225634efbc2SNelio Laranjeiro 		pos = i % RTE_RETA_GROUP_SIZE;
226634efbc2SNelio Laranjeiro 		if (((reta_conf[idx].mask >> i) & 0x1) == 0)
227634efbc2SNelio Laranjeiro 			continue;
228634efbc2SNelio Laranjeiro 		assert(reta_conf[idx].reta[pos] < priv->rxqs_n);
229634efbc2SNelio Laranjeiro 		(*priv->reta_idx)[i] = reta_conf[idx].reta[pos];
230634efbc2SNelio Laranjeiro 	}
231634efbc2SNelio Laranjeiro 	return 0;
232634efbc2SNelio Laranjeiro }
233634efbc2SNelio Laranjeiro 
234634efbc2SNelio Laranjeiro /**
235634efbc2SNelio Laranjeiro  * DPDK callback to get the RETA indirection table.
236634efbc2SNelio Laranjeiro  *
237634efbc2SNelio Laranjeiro  * @param dev
238634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
239634efbc2SNelio Laranjeiro  * @param reta_conf
240634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
241634efbc2SNelio Laranjeiro  * @param reta_size
242634efbc2SNelio Laranjeiro  *   Size of the RETA table.
243634efbc2SNelio Laranjeiro  *
244634efbc2SNelio Laranjeiro  * @return
245634efbc2SNelio Laranjeiro  *   0 on success, negative errno value on failure.
246634efbc2SNelio Laranjeiro  */
247634efbc2SNelio Laranjeiro int
248634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev,
249634efbc2SNelio Laranjeiro 			struct rte_eth_rss_reta_entry64 *reta_conf,
250634efbc2SNelio Laranjeiro 			uint16_t reta_size)
251634efbc2SNelio Laranjeiro {
252634efbc2SNelio Laranjeiro 	int ret;
253634efbc2SNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
254634efbc2SNelio Laranjeiro 
255634efbc2SNelio Laranjeiro 	priv_lock(priv);
256634efbc2SNelio Laranjeiro 	ret = priv_dev_rss_reta_query(priv, reta_conf, reta_size);
257634efbc2SNelio Laranjeiro 	priv_unlock(priv);
258634efbc2SNelio Laranjeiro 	return -ret;
259634efbc2SNelio Laranjeiro }
260634efbc2SNelio Laranjeiro 
261634efbc2SNelio Laranjeiro /**
262634efbc2SNelio Laranjeiro  * DPDK callback to update the RETA indirection table.
263634efbc2SNelio Laranjeiro  *
264634efbc2SNelio Laranjeiro  * @param dev
265634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
266634efbc2SNelio Laranjeiro  * @param reta_conf
267634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
268634efbc2SNelio Laranjeiro  * @param reta_size
269634efbc2SNelio Laranjeiro  *   Size of the RETA table.
270634efbc2SNelio Laranjeiro  *
271634efbc2SNelio Laranjeiro  * @return
272634efbc2SNelio Laranjeiro  *   0 on success, negative errno value on failure.
273634efbc2SNelio Laranjeiro  */
274634efbc2SNelio Laranjeiro int
275634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,
276634efbc2SNelio Laranjeiro 			 struct rte_eth_rss_reta_entry64 *reta_conf,
277634efbc2SNelio Laranjeiro 			 uint16_t reta_size)
278634efbc2SNelio Laranjeiro {
279634efbc2SNelio Laranjeiro 	int ret;
280634efbc2SNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
281634efbc2SNelio Laranjeiro 
282634efbc2SNelio Laranjeiro 	priv_lock(priv);
283634efbc2SNelio Laranjeiro 	ret = priv_dev_rss_reta_update(priv, reta_conf, reta_size);
284634efbc2SNelio Laranjeiro 	priv_unlock(priv);
2853f2fe392SNélio Laranjeiro 	if (dev->data->dev_started) {
2863f2fe392SNélio Laranjeiro 		mlx5_dev_stop(dev);
2873f2fe392SNélio Laranjeiro 		mlx5_dev_start(dev);
2883f2fe392SNélio Laranjeiro 	}
289634efbc2SNelio Laranjeiro 	return -ret;
290634efbc2SNelio Laranjeiro }
291