xref: /dpdk/drivers/net/mlx5/mlx5_rss.c (revision 8fd92a66c60a7310cf5ab91996b9b09447512a61)
1*8fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
22f97422eSNelio Laranjeiro  * Copyright 2015 6WIND S.A.
32f97422eSNelio Laranjeiro  * Copyright 2015 Mellanox.
42f97422eSNelio Laranjeiro  */
52f97422eSNelio Laranjeiro 
62f97422eSNelio Laranjeiro #include <stddef.h>
72f97422eSNelio Laranjeiro #include <stdint.h>
82f97422eSNelio Laranjeiro #include <errno.h>
92f97422eSNelio Laranjeiro #include <string.h>
102f97422eSNelio Laranjeiro #include <assert.h>
112f97422eSNelio Laranjeiro 
122f97422eSNelio Laranjeiro /* Verbs header. */
132f97422eSNelio Laranjeiro /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
142f97422eSNelio Laranjeiro #ifdef PEDANTIC
15fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic"
162f97422eSNelio Laranjeiro #endif
172f97422eSNelio Laranjeiro #include <infiniband/verbs.h>
182f97422eSNelio Laranjeiro #ifdef PEDANTIC
19fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic"
202f97422eSNelio Laranjeiro #endif
212f97422eSNelio Laranjeiro 
222f97422eSNelio Laranjeiro #include <rte_malloc.h>
23ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h>
242f97422eSNelio Laranjeiro 
252f97422eSNelio Laranjeiro #include "mlx5.h"
26b365799bSNélio Laranjeiro #include "mlx5_defs.h"
272f97422eSNelio Laranjeiro #include "mlx5_rxtx.h"
282f97422eSNelio Laranjeiro 
292f97422eSNelio Laranjeiro /**
302f97422eSNelio Laranjeiro  * DPDK callback to update the RSS hash configuration.
312f97422eSNelio Laranjeiro  *
322f97422eSNelio Laranjeiro  * @param dev
332f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
342f97422eSNelio Laranjeiro  * @param[in] rss_conf
352f97422eSNelio Laranjeiro  *   RSS configuration data.
362f97422eSNelio Laranjeiro  *
372f97422eSNelio Laranjeiro  * @return
382f97422eSNelio Laranjeiro  *   0 on success, negative errno value on failure.
392f97422eSNelio Laranjeiro  */
402f97422eSNelio Laranjeiro int
412f97422eSNelio Laranjeiro mlx5_rss_hash_update(struct rte_eth_dev *dev,
422f97422eSNelio Laranjeiro 		     struct rte_eth_rss_conf *rss_conf)
432f97422eSNelio Laranjeiro {
442f97422eSNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
4529c1d8bbSNélio Laranjeiro 	int ret = 0;
462f97422eSNelio Laranjeiro 
472f97422eSNelio Laranjeiro 	priv_lock(priv);
48b365799bSNélio Laranjeiro 	if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) {
49b365799bSNélio Laranjeiro 		ret = -EINVAL;
50b365799bSNélio Laranjeiro 		goto out;
51b365799bSNélio Laranjeiro 	}
52920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key && rss_conf->rss_key_len) {
5329c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key,
5429c1d8bbSNélio Laranjeiro 						     rss_conf->rss_key_len, 0);
5529c1d8bbSNélio Laranjeiro 		if (!priv->rss_conf.rss_key) {
5629c1d8bbSNélio Laranjeiro 			ret = -ENOMEM;
5729c1d8bbSNélio Laranjeiro 			goto out;
5829c1d8bbSNélio Laranjeiro 		}
59920b4e54SNélio Laranjeiro 		memcpy(priv->rss_conf.rss_key, rss_conf->rss_key,
6029c1d8bbSNélio Laranjeiro 		       rss_conf->rss_key_len);
6129c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key_len = rss_conf->rss_key_len;
6229c1d8bbSNélio Laranjeiro 	}
6329c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = rss_conf->rss_hf;
6429c1d8bbSNélio Laranjeiro out:
652f97422eSNelio Laranjeiro 	priv_unlock(priv);
6629c1d8bbSNélio Laranjeiro 	return ret;
672f97422eSNelio Laranjeiro }
682f97422eSNelio Laranjeiro 
692f97422eSNelio Laranjeiro /**
702f97422eSNelio Laranjeiro  * DPDK callback to get the RSS hash configuration.
712f97422eSNelio Laranjeiro  *
722f97422eSNelio Laranjeiro  * @param dev
732f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
742f97422eSNelio Laranjeiro  * @param[in, out] rss_conf
752f97422eSNelio Laranjeiro  *   RSS configuration data.
762f97422eSNelio Laranjeiro  *
772f97422eSNelio Laranjeiro  * @return
782f97422eSNelio Laranjeiro  *   0 on success, negative errno value on failure.
792f97422eSNelio Laranjeiro  */
802f97422eSNelio Laranjeiro int
812f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev,
822f97422eSNelio Laranjeiro 		       struct rte_eth_rss_conf *rss_conf)
832f97422eSNelio Laranjeiro {
842f97422eSNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
852f97422eSNelio Laranjeiro 
86920b4e54SNélio Laranjeiro 	if (!rss_conf)
87920b4e54SNélio Laranjeiro 		return -EINVAL;
882f97422eSNelio Laranjeiro 	priv_lock(priv);
89920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key &&
90920b4e54SNélio Laranjeiro 	    (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) {
9129c1d8bbSNélio Laranjeiro 		memcpy(rss_conf->rss_key, priv->rss_conf.rss_key,
9229c1d8bbSNélio Laranjeiro 		       priv->rss_conf.rss_key_len);
93920b4e54SNélio Laranjeiro 	}
94920b4e54SNélio Laranjeiro 	rss_conf->rss_key_len = priv->rss_conf.rss_key_len;
95920b4e54SNélio Laranjeiro 	rss_conf->rss_hf = priv->rss_conf.rss_hf;
962f97422eSNelio Laranjeiro 	priv_unlock(priv);
97920b4e54SNélio Laranjeiro 	return 0;
982f97422eSNelio Laranjeiro }
99634efbc2SNelio Laranjeiro 
100634efbc2SNelio Laranjeiro /**
101634efbc2SNelio Laranjeiro  * Allocate/reallocate RETA index table.
102634efbc2SNelio Laranjeiro  *
103634efbc2SNelio Laranjeiro  * @param priv
104634efbc2SNelio Laranjeiro  *   Pointer to private structure.
105634efbc2SNelio Laranjeiro  * @praram reta_size
106634efbc2SNelio Laranjeiro  *   The size of the array to allocate.
107634efbc2SNelio Laranjeiro  *
108634efbc2SNelio Laranjeiro  * @return
109634efbc2SNelio Laranjeiro  *   0 on success, errno value on failure.
110634efbc2SNelio Laranjeiro  */
111634efbc2SNelio Laranjeiro int
112634efbc2SNelio Laranjeiro priv_rss_reta_index_resize(struct priv *priv, unsigned int reta_size)
113634efbc2SNelio Laranjeiro {
114634efbc2SNelio Laranjeiro 	void *mem;
115634efbc2SNelio Laranjeiro 	unsigned int old_size = priv->reta_idx_n;
116634efbc2SNelio Laranjeiro 
117634efbc2SNelio Laranjeiro 	if (priv->reta_idx_n == reta_size)
118634efbc2SNelio Laranjeiro 		return 0;
119634efbc2SNelio Laranjeiro 
120634efbc2SNelio Laranjeiro 	mem = rte_realloc(priv->reta_idx,
121634efbc2SNelio Laranjeiro 			  reta_size * sizeof((*priv->reta_idx)[0]), 0);
122634efbc2SNelio Laranjeiro 	if (!mem)
123634efbc2SNelio Laranjeiro 		return ENOMEM;
124634efbc2SNelio Laranjeiro 	priv->reta_idx = mem;
125634efbc2SNelio Laranjeiro 	priv->reta_idx_n = reta_size;
126634efbc2SNelio Laranjeiro 
127634efbc2SNelio Laranjeiro 	if (old_size < reta_size)
128634efbc2SNelio Laranjeiro 		memset(&(*priv->reta_idx)[old_size], 0,
129634efbc2SNelio Laranjeiro 		       (reta_size - old_size) *
130634efbc2SNelio Laranjeiro 		       sizeof((*priv->reta_idx)[0]));
131634efbc2SNelio Laranjeiro 	return 0;
132634efbc2SNelio Laranjeiro }
133634efbc2SNelio Laranjeiro 
134634efbc2SNelio Laranjeiro /**
135634efbc2SNelio Laranjeiro  * Query RETA table.
136634efbc2SNelio Laranjeiro  *
137634efbc2SNelio Laranjeiro  * @param priv
138634efbc2SNelio Laranjeiro  *   Pointer to private structure.
139634efbc2SNelio Laranjeiro  * @param[in, out] reta_conf
140634efbc2SNelio Laranjeiro  *   Pointer to the first RETA configuration structure.
141634efbc2SNelio Laranjeiro  * @param reta_size
142634efbc2SNelio Laranjeiro  *   Number of entries.
143634efbc2SNelio Laranjeiro  *
144634efbc2SNelio Laranjeiro  * @return
145634efbc2SNelio Laranjeiro  *   0 on success, errno value on failure.
146634efbc2SNelio Laranjeiro  */
147634efbc2SNelio Laranjeiro static int
148634efbc2SNelio Laranjeiro priv_dev_rss_reta_query(struct priv *priv,
149634efbc2SNelio Laranjeiro 			struct rte_eth_rss_reta_entry64 *reta_conf,
150634efbc2SNelio Laranjeiro 			unsigned int reta_size)
151634efbc2SNelio Laranjeiro {
152634efbc2SNelio Laranjeiro 	unsigned int idx;
153634efbc2SNelio Laranjeiro 	unsigned int i;
154634efbc2SNelio Laranjeiro 
155d365210eSYongseok Koh 	if (!reta_size || reta_size > priv->reta_idx_n)
156d365210eSYongseok Koh 		return EINVAL;
157634efbc2SNelio Laranjeiro 	/* Fill each entry of the table even if its bit is not set. */
158634efbc2SNelio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
159634efbc2SNelio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
160634efbc2SNelio Laranjeiro 		reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] =
161634efbc2SNelio Laranjeiro 			(*priv->reta_idx)[i];
162634efbc2SNelio Laranjeiro 	}
163634efbc2SNelio Laranjeiro 	return 0;
164634efbc2SNelio Laranjeiro }
165634efbc2SNelio Laranjeiro 
166634efbc2SNelio Laranjeiro /**
167634efbc2SNelio Laranjeiro  * Update RETA table.
168634efbc2SNelio Laranjeiro  *
169634efbc2SNelio Laranjeiro  * @param priv
170634efbc2SNelio Laranjeiro  *   Pointer to private structure.
171634efbc2SNelio Laranjeiro  * @param[in] reta_conf
172634efbc2SNelio Laranjeiro  *   Pointer to the first RETA configuration structure.
173634efbc2SNelio Laranjeiro  * @param reta_size
174634efbc2SNelio Laranjeiro  *   Number of entries.
175634efbc2SNelio Laranjeiro  *
176634efbc2SNelio Laranjeiro  * @return
177634efbc2SNelio Laranjeiro  *   0 on success, errno value on failure.
178634efbc2SNelio Laranjeiro  */
179634efbc2SNelio Laranjeiro static int
180634efbc2SNelio Laranjeiro priv_dev_rss_reta_update(struct priv *priv,
181634efbc2SNelio Laranjeiro 			 struct rte_eth_rss_reta_entry64 *reta_conf,
182634efbc2SNelio Laranjeiro 			 unsigned int reta_size)
183634efbc2SNelio Laranjeiro {
184634efbc2SNelio Laranjeiro 	unsigned int idx;
185634efbc2SNelio Laranjeiro 	unsigned int i;
186634efbc2SNelio Laranjeiro 	unsigned int pos;
187634efbc2SNelio Laranjeiro 	int ret;
188634efbc2SNelio Laranjeiro 
189d365210eSYongseok Koh 	if (!reta_size)
190d365210eSYongseok Koh 		return EINVAL;
191d365210eSYongseok Koh 	ret = priv_rss_reta_index_resize(priv, reta_size);
192634efbc2SNelio Laranjeiro 	if (ret)
193634efbc2SNelio Laranjeiro 		return ret;
194634efbc2SNelio Laranjeiro 
195634efbc2SNelio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
196634efbc2SNelio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
197634efbc2SNelio Laranjeiro 		pos = i % RTE_RETA_GROUP_SIZE;
198634efbc2SNelio Laranjeiro 		if (((reta_conf[idx].mask >> i) & 0x1) == 0)
199634efbc2SNelio Laranjeiro 			continue;
200634efbc2SNelio Laranjeiro 		assert(reta_conf[idx].reta[pos] < priv->rxqs_n);
201634efbc2SNelio Laranjeiro 		(*priv->reta_idx)[i] = reta_conf[idx].reta[pos];
202634efbc2SNelio Laranjeiro 	}
203634efbc2SNelio Laranjeiro 	return 0;
204634efbc2SNelio Laranjeiro }
205634efbc2SNelio Laranjeiro 
206634efbc2SNelio Laranjeiro /**
207634efbc2SNelio Laranjeiro  * DPDK callback to get the RETA indirection table.
208634efbc2SNelio Laranjeiro  *
209634efbc2SNelio Laranjeiro  * @param dev
210634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
211634efbc2SNelio Laranjeiro  * @param reta_conf
212634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
213634efbc2SNelio Laranjeiro  * @param reta_size
214634efbc2SNelio Laranjeiro  *   Size of the RETA table.
215634efbc2SNelio Laranjeiro  *
216634efbc2SNelio Laranjeiro  * @return
217634efbc2SNelio Laranjeiro  *   0 on success, negative errno value on failure.
218634efbc2SNelio Laranjeiro  */
219634efbc2SNelio Laranjeiro int
220634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev,
221634efbc2SNelio Laranjeiro 			struct rte_eth_rss_reta_entry64 *reta_conf,
222634efbc2SNelio Laranjeiro 			uint16_t reta_size)
223634efbc2SNelio Laranjeiro {
224634efbc2SNelio Laranjeiro 	int ret;
225634efbc2SNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
226634efbc2SNelio Laranjeiro 
227634efbc2SNelio Laranjeiro 	priv_lock(priv);
228634efbc2SNelio Laranjeiro 	ret = priv_dev_rss_reta_query(priv, reta_conf, reta_size);
229634efbc2SNelio Laranjeiro 	priv_unlock(priv);
230634efbc2SNelio Laranjeiro 	return -ret;
231634efbc2SNelio Laranjeiro }
232634efbc2SNelio Laranjeiro 
233634efbc2SNelio Laranjeiro /**
234634efbc2SNelio Laranjeiro  * DPDK callback to update the RETA indirection table.
235634efbc2SNelio Laranjeiro  *
236634efbc2SNelio Laranjeiro  * @param dev
237634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
238634efbc2SNelio Laranjeiro  * @param reta_conf
239634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
240634efbc2SNelio Laranjeiro  * @param reta_size
241634efbc2SNelio Laranjeiro  *   Size of the RETA table.
242634efbc2SNelio Laranjeiro  *
243634efbc2SNelio Laranjeiro  * @return
244634efbc2SNelio Laranjeiro  *   0 on success, negative errno value on failure.
245634efbc2SNelio Laranjeiro  */
246634efbc2SNelio Laranjeiro int
247634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,
248634efbc2SNelio Laranjeiro 			 struct rte_eth_rss_reta_entry64 *reta_conf,
249634efbc2SNelio Laranjeiro 			 uint16_t reta_size)
250634efbc2SNelio Laranjeiro {
251634efbc2SNelio Laranjeiro 	int ret;
252634efbc2SNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
253634efbc2SNelio Laranjeiro 
254634efbc2SNelio Laranjeiro 	priv_lock(priv);
255634efbc2SNelio Laranjeiro 	ret = priv_dev_rss_reta_update(priv, reta_conf, reta_size);
256634efbc2SNelio Laranjeiro 	priv_unlock(priv);
2573f2fe392SNélio Laranjeiro 	if (dev->data->dev_started) {
2583f2fe392SNélio Laranjeiro 		mlx5_dev_stop(dev);
2593f2fe392SNélio Laranjeiro 		mlx5_dev_start(dev);
2603f2fe392SNélio Laranjeiro 	}
261634efbc2SNelio Laranjeiro 	return -ret;
262634efbc2SNelio Laranjeiro }
263