xref: /dpdk/drivers/net/mlx5/mlx5_rss.c (revision 83c2047c5fe82fb25674c3053d4871838e7455cb)
18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
22f97422eSNelio Laranjeiro  * Copyright 2015 6WIND S.A.
35feecc57SShahaf Shuler  * Copyright 2015 Mellanox Technologies, Ltd
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 
112f97422eSNelio Laranjeiro /* Verbs header. */
122f97422eSNelio Laranjeiro /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
132f97422eSNelio Laranjeiro #ifdef PEDANTIC
14fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic"
152f97422eSNelio Laranjeiro #endif
162f97422eSNelio Laranjeiro #include <infiniband/verbs.h>
172f97422eSNelio Laranjeiro #ifdef PEDANTIC
18fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic"
192f97422eSNelio Laranjeiro #endif
202f97422eSNelio Laranjeiro 
212f97422eSNelio Laranjeiro #include <rte_malloc.h>
22ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h>
232f97422eSNelio Laranjeiro 
24*83c2047cSSuanming Mou #include <mlx5_malloc.h>
25*83c2047cSSuanming Mou 
26b365799bSNélio Laranjeiro #include "mlx5_defs.h"
277b4f1e6bSMatan Azrad #include "mlx5.h"
282f97422eSNelio Laranjeiro #include "mlx5_rxtx.h"
292f97422eSNelio Laranjeiro 
302f97422eSNelio Laranjeiro /**
312f97422eSNelio Laranjeiro  * DPDK callback to update the RSS hash configuration.
322f97422eSNelio Laranjeiro  *
332f97422eSNelio Laranjeiro  * @param dev
342f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
352f97422eSNelio Laranjeiro  * @param[in] rss_conf
362f97422eSNelio Laranjeiro  *   RSS configuration data.
372f97422eSNelio Laranjeiro  *
382f97422eSNelio Laranjeiro  * @return
39a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
402f97422eSNelio Laranjeiro  */
412f97422eSNelio Laranjeiro int
422f97422eSNelio Laranjeiro mlx5_rss_hash_update(struct rte_eth_dev *dev,
432f97422eSNelio Laranjeiro 		     struct rte_eth_rss_conf *rss_conf)
442f97422eSNelio Laranjeiro {
45dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
4666669155SDahir Osman 	unsigned int i;
4766669155SDahir Osman 	unsigned int idx;
482f97422eSNelio Laranjeiro 
49b365799bSNélio Laranjeiro 	if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) {
50a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
51a6d83b6aSNélio Laranjeiro 		return -rte_errno;
52b365799bSNélio Laranjeiro 	}
53920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key && rss_conf->rss_key_len) {
54c388a2f6SNelio Laranjeiro 		if (rss_conf->rss_key_len != MLX5_RSS_HASH_KEY_LEN) {
55a1572312SShahaf Shuler 			DRV_LOG(ERR,
56c388a2f6SNelio Laranjeiro 				"port %u RSS key len must be %s Bytes long",
57c388a2f6SNelio Laranjeiro 				dev->data->port_id,
58c388a2f6SNelio Laranjeiro 				RTE_STR(MLX5_RSS_HASH_KEY_LEN));
59a1572312SShahaf Shuler 			rte_errno = EINVAL;
60a1572312SShahaf Shuler 			return -rte_errno;
61a1572312SShahaf Shuler 		}
62*83c2047cSSuanming Mou 		priv->rss_conf.rss_key = mlx5_realloc(priv->rss_conf.rss_key,
63*83c2047cSSuanming Mou 						      MLX5_MEM_RTE,
64*83c2047cSSuanming Mou 						      rss_conf->rss_key_len,
65*83c2047cSSuanming Mou 						      0, SOCKET_ID_ANY);
6629c1d8bbSNélio Laranjeiro 		if (!priv->rss_conf.rss_key) {
67a6d83b6aSNélio Laranjeiro 			rte_errno = ENOMEM;
68a6d83b6aSNélio Laranjeiro 			return -rte_errno;
6929c1d8bbSNélio Laranjeiro 		}
70920b4e54SNélio Laranjeiro 		memcpy(priv->rss_conf.rss_key, rss_conf->rss_key,
7129c1d8bbSNélio Laranjeiro 		       rss_conf->rss_key_len);
7229c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key_len = rss_conf->rss_key_len;
7329c1d8bbSNélio Laranjeiro 	}
7429c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = rss_conf->rss_hf;
7566669155SDahir Osman 	/* Enable the RSS hash in all Rx queues. */
7666669155SDahir Osman 	for (i = 0, idx = 0; idx != priv->rxqs_n; ++i) {
7766669155SDahir Osman 		if (!(*priv->rxqs)[i])
7866669155SDahir Osman 			continue;
7966669155SDahir Osman 		(*priv->rxqs)[i]->rss_hash = !!rss_conf->rss_hf &&
8066669155SDahir Osman 			!!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS);
8166669155SDahir Osman 		++idx;
8266669155SDahir Osman 	}
83a6d83b6aSNélio Laranjeiro 	return 0;
842f97422eSNelio Laranjeiro }
852f97422eSNelio Laranjeiro 
862f97422eSNelio Laranjeiro /**
872f97422eSNelio Laranjeiro  * DPDK callback to get the RSS hash configuration.
882f97422eSNelio Laranjeiro  *
892f97422eSNelio Laranjeiro  * @param dev
902f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
912f97422eSNelio Laranjeiro  * @param[in, out] rss_conf
922f97422eSNelio Laranjeiro  *   RSS configuration data.
932f97422eSNelio Laranjeiro  *
942f97422eSNelio Laranjeiro  * @return
95a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
962f97422eSNelio Laranjeiro  */
972f97422eSNelio Laranjeiro int
982f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev,
992f97422eSNelio Laranjeiro 		       struct rte_eth_rss_conf *rss_conf)
1002f97422eSNelio Laranjeiro {
101dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
1022f97422eSNelio Laranjeiro 
103a6d83b6aSNélio Laranjeiro 	if (!rss_conf) {
104a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
105a6d83b6aSNélio Laranjeiro 		return -rte_errno;
106a6d83b6aSNélio Laranjeiro 	}
107920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key &&
108920b4e54SNélio Laranjeiro 	    (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) {
10929c1d8bbSNélio Laranjeiro 		memcpy(rss_conf->rss_key, priv->rss_conf.rss_key,
11029c1d8bbSNélio Laranjeiro 		       priv->rss_conf.rss_key_len);
111920b4e54SNélio Laranjeiro 	}
112920b4e54SNélio Laranjeiro 	rss_conf->rss_key_len = priv->rss_conf.rss_key_len;
113920b4e54SNélio Laranjeiro 	rss_conf->rss_hf = priv->rss_conf.rss_hf;
114920b4e54SNélio Laranjeiro 	return 0;
1152f97422eSNelio Laranjeiro }
116634efbc2SNelio Laranjeiro 
117634efbc2SNelio Laranjeiro /**
118634efbc2SNelio Laranjeiro  * Allocate/reallocate RETA index table.
119634efbc2SNelio Laranjeiro  *
120af4f09f2SNélio Laranjeiro  * @param dev
121af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
122634efbc2SNelio Laranjeiro  * @praram reta_size
123634efbc2SNelio Laranjeiro  *   The size of the array to allocate.
124634efbc2SNelio Laranjeiro  *
125634efbc2SNelio Laranjeiro  * @return
126a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
127634efbc2SNelio Laranjeiro  */
128634efbc2SNelio Laranjeiro int
129af4f09f2SNélio Laranjeiro mlx5_rss_reta_index_resize(struct rte_eth_dev *dev, unsigned int reta_size)
130634efbc2SNelio Laranjeiro {
131dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
132634efbc2SNelio Laranjeiro 	void *mem;
133634efbc2SNelio Laranjeiro 	unsigned int old_size = priv->reta_idx_n;
134634efbc2SNelio Laranjeiro 
135634efbc2SNelio Laranjeiro 	if (priv->reta_idx_n == reta_size)
136634efbc2SNelio Laranjeiro 		return 0;
137634efbc2SNelio Laranjeiro 
138*83c2047cSSuanming Mou 	mem = mlx5_realloc(priv->reta_idx, MLX5_MEM_RTE,
139*83c2047cSSuanming Mou 			   reta_size * sizeof((*priv->reta_idx)[0]), 0,
140*83c2047cSSuanming Mou 			   SOCKET_ID_ANY);
141a6d83b6aSNélio Laranjeiro 	if (!mem) {
142a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
143a6d83b6aSNélio Laranjeiro 		return -rte_errno;
144a6d83b6aSNélio Laranjeiro 	}
145634efbc2SNelio Laranjeiro 	priv->reta_idx = mem;
146634efbc2SNelio Laranjeiro 	priv->reta_idx_n = reta_size;
147634efbc2SNelio Laranjeiro 	if (old_size < reta_size)
148634efbc2SNelio Laranjeiro 		memset(&(*priv->reta_idx)[old_size], 0,
149634efbc2SNelio Laranjeiro 		       (reta_size - old_size) *
150634efbc2SNelio Laranjeiro 		       sizeof((*priv->reta_idx)[0]));
151634efbc2SNelio Laranjeiro 	return 0;
152634efbc2SNelio Laranjeiro }
153634efbc2SNelio Laranjeiro 
154634efbc2SNelio Laranjeiro /**
155634efbc2SNelio Laranjeiro  * DPDK callback to get the RETA indirection table.
156634efbc2SNelio Laranjeiro  *
157634efbc2SNelio Laranjeiro  * @param dev
158634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
159634efbc2SNelio Laranjeiro  * @param reta_conf
160634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
161634efbc2SNelio Laranjeiro  * @param reta_size
162634efbc2SNelio Laranjeiro  *   Size of the RETA table.
163634efbc2SNelio Laranjeiro  *
164634efbc2SNelio Laranjeiro  * @return
165a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
166634efbc2SNelio Laranjeiro  */
167634efbc2SNelio Laranjeiro int
168634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev,
169634efbc2SNelio Laranjeiro 			struct rte_eth_rss_reta_entry64 *reta_conf,
170634efbc2SNelio Laranjeiro 			uint16_t reta_size)
171634efbc2SNelio Laranjeiro {
172dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
173af4f09f2SNélio Laranjeiro 	unsigned int idx;
174af4f09f2SNélio Laranjeiro 	unsigned int i;
175634efbc2SNelio Laranjeiro 
176a6d83b6aSNélio Laranjeiro 	if (!reta_size || reta_size > priv->reta_idx_n) {
177a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
178a6d83b6aSNélio Laranjeiro 		return -rte_errno;
179a6d83b6aSNélio Laranjeiro 	}
180af4f09f2SNélio Laranjeiro 	/* Fill each entry of the table even if its bit is not set. */
181af4f09f2SNélio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
182af4f09f2SNélio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
183af4f09f2SNélio Laranjeiro 		reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] =
184af4f09f2SNélio Laranjeiro 			(*priv->reta_idx)[i];
185af4f09f2SNélio Laranjeiro 	}
186af4f09f2SNélio Laranjeiro 	return 0;
187634efbc2SNelio Laranjeiro }
188634efbc2SNelio Laranjeiro 
189634efbc2SNelio Laranjeiro /**
190634efbc2SNelio Laranjeiro  * DPDK callback to update the RETA indirection table.
191634efbc2SNelio Laranjeiro  *
192634efbc2SNelio Laranjeiro  * @param dev
193634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
194634efbc2SNelio Laranjeiro  * @param reta_conf
195634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
196634efbc2SNelio Laranjeiro  * @param reta_size
197634efbc2SNelio Laranjeiro  *   Size of the RETA table.
198634efbc2SNelio Laranjeiro  *
199634efbc2SNelio Laranjeiro  * @return
200a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
201634efbc2SNelio Laranjeiro  */
202634efbc2SNelio Laranjeiro int
203634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,
204634efbc2SNelio Laranjeiro 			 struct rte_eth_rss_reta_entry64 *reta_conf,
205634efbc2SNelio Laranjeiro 			 uint16_t reta_size)
206634efbc2SNelio Laranjeiro {
207634efbc2SNelio Laranjeiro 	int ret;
208dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
209af4f09f2SNélio Laranjeiro 	unsigned int idx;
210af4f09f2SNélio Laranjeiro 	unsigned int i;
211af4f09f2SNélio Laranjeiro 	unsigned int pos;
212634efbc2SNelio Laranjeiro 
213a6d83b6aSNélio Laranjeiro 	if (!reta_size) {
214a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
215a6d83b6aSNélio Laranjeiro 		return -rte_errno;
216a6d83b6aSNélio Laranjeiro 	}
217af4f09f2SNélio Laranjeiro 	ret = mlx5_rss_reta_index_resize(dev, reta_size);
218af4f09f2SNélio Laranjeiro 	if (ret)
219af4f09f2SNélio Laranjeiro 		return ret;
220af4f09f2SNélio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
221af4f09f2SNélio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
222af4f09f2SNélio Laranjeiro 		pos = i % RTE_RETA_GROUP_SIZE;
223af4f09f2SNélio Laranjeiro 		if (((reta_conf[idx].mask >> i) & 0x1) == 0)
224af4f09f2SNélio Laranjeiro 			continue;
2258e46d4e1SAlexander Kozyrev 		MLX5_ASSERT(reta_conf[idx].reta[pos] < priv->rxqs_n);
226af4f09f2SNélio Laranjeiro 		(*priv->reta_idx)[i] = reta_conf[idx].reta[pos];
227af4f09f2SNélio Laranjeiro 	}
2283f2fe392SNélio Laranjeiro 	if (dev->data->dev_started) {
2293f2fe392SNélio Laranjeiro 		mlx5_dev_stop(dev);
23063bd1629SOri Kam 		priv->skip_default_rss_reta = 1;
231a6d83b6aSNélio Laranjeiro 		return mlx5_dev_start(dev);
2323f2fe392SNélio Laranjeiro 	}
233a6d83b6aSNélio Laranjeiro 	return 0;
234634efbc2SNelio Laranjeiro }
235