xref: /dpdk/drivers/net/mlx5/mlx5_rss.c (revision 920b4e545efe05f33ca30ad3816220ad393de4c6)
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"
542f97422eSNelio Laranjeiro #include "mlx5_rxtx.h"
552f97422eSNelio Laranjeiro 
562f97422eSNelio Laranjeiro /**
572f97422eSNelio Laranjeiro  * DPDK callback to update the RSS hash configuration.
582f97422eSNelio Laranjeiro  *
592f97422eSNelio Laranjeiro  * @param dev
602f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
612f97422eSNelio Laranjeiro  * @param[in] rss_conf
622f97422eSNelio Laranjeiro  *   RSS configuration data.
632f97422eSNelio Laranjeiro  *
642f97422eSNelio Laranjeiro  * @return
652f97422eSNelio Laranjeiro  *   0 on success, negative errno value on failure.
662f97422eSNelio Laranjeiro  */
672f97422eSNelio Laranjeiro int
682f97422eSNelio Laranjeiro mlx5_rss_hash_update(struct rte_eth_dev *dev,
692f97422eSNelio Laranjeiro 		     struct rte_eth_rss_conf *rss_conf)
702f97422eSNelio Laranjeiro {
712f97422eSNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
7229c1d8bbSNélio Laranjeiro 	int ret = 0;
732f97422eSNelio Laranjeiro 
742f97422eSNelio Laranjeiro 	priv_lock(priv);
75*920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key && rss_conf->rss_key_len) {
7629c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key,
7729c1d8bbSNélio Laranjeiro 						     rss_conf->rss_key_len, 0);
7829c1d8bbSNélio Laranjeiro 		if (!priv->rss_conf.rss_key) {
7929c1d8bbSNélio Laranjeiro 			ret = -ENOMEM;
8029c1d8bbSNélio Laranjeiro 			goto out;
8129c1d8bbSNélio Laranjeiro 		}
82*920b4e54SNélio Laranjeiro 		memcpy(priv->rss_conf.rss_key, rss_conf->rss_key,
8329c1d8bbSNélio Laranjeiro 		       rss_conf->rss_key_len);
8429c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key_len = rss_conf->rss_key_len;
8529c1d8bbSNélio Laranjeiro 	}
8629c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = rss_conf->rss_hf;
8729c1d8bbSNélio Laranjeiro out:
882f97422eSNelio Laranjeiro 	priv_unlock(priv);
8929c1d8bbSNélio Laranjeiro 	return ret;
902f97422eSNelio Laranjeiro }
912f97422eSNelio Laranjeiro 
922f97422eSNelio Laranjeiro /**
932f97422eSNelio Laranjeiro  * DPDK callback to get the RSS hash configuration.
942f97422eSNelio Laranjeiro  *
952f97422eSNelio Laranjeiro  * @param dev
962f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
972f97422eSNelio Laranjeiro  * @param[in, out] rss_conf
982f97422eSNelio Laranjeiro  *   RSS configuration data.
992f97422eSNelio Laranjeiro  *
1002f97422eSNelio Laranjeiro  * @return
1012f97422eSNelio Laranjeiro  *   0 on success, negative errno value on failure.
1022f97422eSNelio Laranjeiro  */
1032f97422eSNelio Laranjeiro int
1042f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev,
1052f97422eSNelio Laranjeiro 		       struct rte_eth_rss_conf *rss_conf)
1062f97422eSNelio Laranjeiro {
1072f97422eSNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
1082f97422eSNelio Laranjeiro 
109*920b4e54SNélio Laranjeiro 	if (!rss_conf)
110*920b4e54SNélio Laranjeiro 		return -EINVAL;
1112f97422eSNelio Laranjeiro 	priv_lock(priv);
112*920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key &&
113*920b4e54SNélio Laranjeiro 	    (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) {
11429c1d8bbSNélio Laranjeiro 		memcpy(rss_conf->rss_key, priv->rss_conf.rss_key,
11529c1d8bbSNélio Laranjeiro 		       priv->rss_conf.rss_key_len);
116*920b4e54SNélio Laranjeiro 	}
117*920b4e54SNélio Laranjeiro 	rss_conf->rss_key_len = priv->rss_conf.rss_key_len;
118*920b4e54SNélio Laranjeiro 	rss_conf->rss_hf = priv->rss_conf.rss_hf;
1192f97422eSNelio Laranjeiro 	priv_unlock(priv);
120*920b4e54SNélio Laranjeiro 	return 0;
1212f97422eSNelio Laranjeiro }
122634efbc2SNelio Laranjeiro 
123634efbc2SNelio Laranjeiro /**
124634efbc2SNelio Laranjeiro  * Allocate/reallocate RETA index table.
125634efbc2SNelio Laranjeiro  *
126634efbc2SNelio Laranjeiro  * @param priv
127634efbc2SNelio Laranjeiro  *   Pointer to private structure.
128634efbc2SNelio Laranjeiro  * @praram reta_size
129634efbc2SNelio Laranjeiro  *   The size of the array to allocate.
130634efbc2SNelio Laranjeiro  *
131634efbc2SNelio Laranjeiro  * @return
132634efbc2SNelio Laranjeiro  *   0 on success, errno value on failure.
133634efbc2SNelio Laranjeiro  */
134634efbc2SNelio Laranjeiro int
135634efbc2SNelio Laranjeiro priv_rss_reta_index_resize(struct priv *priv, unsigned int reta_size)
136634efbc2SNelio Laranjeiro {
137634efbc2SNelio Laranjeiro 	void *mem;
138634efbc2SNelio Laranjeiro 	unsigned int old_size = priv->reta_idx_n;
139634efbc2SNelio Laranjeiro 
140634efbc2SNelio Laranjeiro 	if (priv->reta_idx_n == reta_size)
141634efbc2SNelio Laranjeiro 		return 0;
142634efbc2SNelio Laranjeiro 
143634efbc2SNelio Laranjeiro 	mem = rte_realloc(priv->reta_idx,
144634efbc2SNelio Laranjeiro 			  reta_size * sizeof((*priv->reta_idx)[0]), 0);
145634efbc2SNelio Laranjeiro 	if (!mem)
146634efbc2SNelio Laranjeiro 		return ENOMEM;
147634efbc2SNelio Laranjeiro 	priv->reta_idx = mem;
148634efbc2SNelio Laranjeiro 	priv->reta_idx_n = reta_size;
149634efbc2SNelio Laranjeiro 
150634efbc2SNelio Laranjeiro 	if (old_size < reta_size)
151634efbc2SNelio Laranjeiro 		memset(&(*priv->reta_idx)[old_size], 0,
152634efbc2SNelio Laranjeiro 		       (reta_size - old_size) *
153634efbc2SNelio Laranjeiro 		       sizeof((*priv->reta_idx)[0]));
154634efbc2SNelio Laranjeiro 	return 0;
155634efbc2SNelio Laranjeiro }
156634efbc2SNelio Laranjeiro 
157634efbc2SNelio Laranjeiro /**
158634efbc2SNelio Laranjeiro  * Query RETA table.
159634efbc2SNelio Laranjeiro  *
160634efbc2SNelio Laranjeiro  * @param priv
161634efbc2SNelio Laranjeiro  *   Pointer to private structure.
162634efbc2SNelio Laranjeiro  * @param[in, out] reta_conf
163634efbc2SNelio Laranjeiro  *   Pointer to the first RETA configuration structure.
164634efbc2SNelio Laranjeiro  * @param reta_size
165634efbc2SNelio Laranjeiro  *   Number of entries.
166634efbc2SNelio Laranjeiro  *
167634efbc2SNelio Laranjeiro  * @return
168634efbc2SNelio Laranjeiro  *   0 on success, errno value on failure.
169634efbc2SNelio Laranjeiro  */
170634efbc2SNelio Laranjeiro static int
171634efbc2SNelio Laranjeiro priv_dev_rss_reta_query(struct priv *priv,
172634efbc2SNelio Laranjeiro 			struct rte_eth_rss_reta_entry64 *reta_conf,
173634efbc2SNelio Laranjeiro 			unsigned int reta_size)
174634efbc2SNelio Laranjeiro {
175634efbc2SNelio Laranjeiro 	unsigned int idx;
176634efbc2SNelio Laranjeiro 	unsigned int i;
177634efbc2SNelio Laranjeiro 
178d365210eSYongseok Koh 	if (!reta_size || reta_size > priv->reta_idx_n)
179d365210eSYongseok Koh 		return EINVAL;
180634efbc2SNelio Laranjeiro 	/* Fill each entry of the table even if its bit is not set. */
181634efbc2SNelio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
182634efbc2SNelio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
183634efbc2SNelio Laranjeiro 		reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] =
184634efbc2SNelio Laranjeiro 			(*priv->reta_idx)[i];
185634efbc2SNelio Laranjeiro 	}
186634efbc2SNelio Laranjeiro 	return 0;
187634efbc2SNelio Laranjeiro }
188634efbc2SNelio Laranjeiro 
189634efbc2SNelio Laranjeiro /**
190634efbc2SNelio Laranjeiro  * Update RETA table.
191634efbc2SNelio Laranjeiro  *
192634efbc2SNelio Laranjeiro  * @param priv
193634efbc2SNelio Laranjeiro  *   Pointer to private structure.
194634efbc2SNelio Laranjeiro  * @param[in] reta_conf
195634efbc2SNelio Laranjeiro  *   Pointer to the first RETA configuration structure.
196634efbc2SNelio Laranjeiro  * @param reta_size
197634efbc2SNelio Laranjeiro  *   Number of entries.
198634efbc2SNelio Laranjeiro  *
199634efbc2SNelio Laranjeiro  * @return
200634efbc2SNelio Laranjeiro  *   0 on success, errno value on failure.
201634efbc2SNelio Laranjeiro  */
202634efbc2SNelio Laranjeiro static int
203634efbc2SNelio Laranjeiro priv_dev_rss_reta_update(struct priv *priv,
204634efbc2SNelio Laranjeiro 			 struct rte_eth_rss_reta_entry64 *reta_conf,
205634efbc2SNelio Laranjeiro 			 unsigned int reta_size)
206634efbc2SNelio Laranjeiro {
207634efbc2SNelio Laranjeiro 	unsigned int idx;
208634efbc2SNelio Laranjeiro 	unsigned int i;
209634efbc2SNelio Laranjeiro 	unsigned int pos;
210634efbc2SNelio Laranjeiro 	int ret;
211634efbc2SNelio Laranjeiro 
212d365210eSYongseok Koh 	if (!reta_size)
213d365210eSYongseok Koh 		return EINVAL;
214d365210eSYongseok Koh 	ret = priv_rss_reta_index_resize(priv, reta_size);
215634efbc2SNelio Laranjeiro 	if (ret)
216634efbc2SNelio Laranjeiro 		return ret;
217634efbc2SNelio Laranjeiro 
218634efbc2SNelio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
219634efbc2SNelio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
220634efbc2SNelio Laranjeiro 		pos = i % RTE_RETA_GROUP_SIZE;
221634efbc2SNelio Laranjeiro 		if (((reta_conf[idx].mask >> i) & 0x1) == 0)
222634efbc2SNelio Laranjeiro 			continue;
223634efbc2SNelio Laranjeiro 		assert(reta_conf[idx].reta[pos] < priv->rxqs_n);
224634efbc2SNelio Laranjeiro 		(*priv->reta_idx)[i] = reta_conf[idx].reta[pos];
225634efbc2SNelio Laranjeiro 	}
226634efbc2SNelio Laranjeiro 	return 0;
227634efbc2SNelio Laranjeiro }
228634efbc2SNelio Laranjeiro 
229634efbc2SNelio Laranjeiro /**
230634efbc2SNelio Laranjeiro  * DPDK callback to get the RETA indirection table.
231634efbc2SNelio Laranjeiro  *
232634efbc2SNelio Laranjeiro  * @param dev
233634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
234634efbc2SNelio Laranjeiro  * @param reta_conf
235634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
236634efbc2SNelio Laranjeiro  * @param reta_size
237634efbc2SNelio Laranjeiro  *   Size of the RETA table.
238634efbc2SNelio Laranjeiro  *
239634efbc2SNelio Laranjeiro  * @return
240634efbc2SNelio Laranjeiro  *   0 on success, negative errno value on failure.
241634efbc2SNelio Laranjeiro  */
242634efbc2SNelio Laranjeiro int
243634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev,
244634efbc2SNelio Laranjeiro 			struct rte_eth_rss_reta_entry64 *reta_conf,
245634efbc2SNelio Laranjeiro 			uint16_t reta_size)
246634efbc2SNelio Laranjeiro {
247634efbc2SNelio Laranjeiro 	int ret;
248634efbc2SNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
249634efbc2SNelio Laranjeiro 
250634efbc2SNelio Laranjeiro 	priv_lock(priv);
251634efbc2SNelio Laranjeiro 	ret = priv_dev_rss_reta_query(priv, reta_conf, reta_size);
252634efbc2SNelio Laranjeiro 	priv_unlock(priv);
253634efbc2SNelio Laranjeiro 	return -ret;
254634efbc2SNelio Laranjeiro }
255634efbc2SNelio Laranjeiro 
256634efbc2SNelio Laranjeiro /**
257634efbc2SNelio Laranjeiro  * DPDK callback to update the RETA indirection table.
258634efbc2SNelio Laranjeiro  *
259634efbc2SNelio Laranjeiro  * @param dev
260634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
261634efbc2SNelio Laranjeiro  * @param reta_conf
262634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
263634efbc2SNelio Laranjeiro  * @param reta_size
264634efbc2SNelio Laranjeiro  *   Size of the RETA table.
265634efbc2SNelio Laranjeiro  *
266634efbc2SNelio Laranjeiro  * @return
267634efbc2SNelio Laranjeiro  *   0 on success, negative errno value on failure.
268634efbc2SNelio Laranjeiro  */
269634efbc2SNelio Laranjeiro int
270634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,
271634efbc2SNelio Laranjeiro 			 struct rte_eth_rss_reta_entry64 *reta_conf,
272634efbc2SNelio Laranjeiro 			 uint16_t reta_size)
273634efbc2SNelio Laranjeiro {
274634efbc2SNelio Laranjeiro 	int ret;
275634efbc2SNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
276634efbc2SNelio Laranjeiro 
277aee1b165SXueming Li 	assert(!mlx5_is_secondary());
278634efbc2SNelio Laranjeiro 	priv_lock(priv);
279634efbc2SNelio Laranjeiro 	ret = priv_dev_rss_reta_update(priv, reta_conf, reta_size);
280634efbc2SNelio Laranjeiro 	priv_unlock(priv);
2813f2fe392SNélio Laranjeiro 	if (dev->data->dev_started) {
2823f2fe392SNélio Laranjeiro 		mlx5_dev_stop(dev);
2833f2fe392SNélio Laranjeiro 		mlx5_dev_start(dev);
2843f2fe392SNélio Laranjeiro 	}
285634efbc2SNelio Laranjeiro 	return -ret;
286634efbc2SNelio Laranjeiro }
287