xref: /dpdk/drivers/net/mlx5/mlx5_rss.c (revision dbeba4cf18a5e1d9f7aaa284457bf15c351eb965)
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 #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
38a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
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 {
44*dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
4566669155SDahir Osman 	unsigned int i;
4666669155SDahir Osman 	unsigned int idx;
472f97422eSNelio Laranjeiro 
48b365799bSNélio Laranjeiro 	if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) {
49a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
50a6d83b6aSNélio Laranjeiro 		return -rte_errno;
51b365799bSNélio Laranjeiro 	}
52920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key && rss_conf->rss_key_len) {
53c388a2f6SNelio Laranjeiro 		if (rss_conf->rss_key_len != MLX5_RSS_HASH_KEY_LEN) {
54a1572312SShahaf Shuler 			DRV_LOG(ERR,
55c388a2f6SNelio Laranjeiro 				"port %u RSS key len must be %s Bytes long",
56c388a2f6SNelio Laranjeiro 				dev->data->port_id,
57c388a2f6SNelio Laranjeiro 				RTE_STR(MLX5_RSS_HASH_KEY_LEN));
58a1572312SShahaf Shuler 			rte_errno = EINVAL;
59a1572312SShahaf Shuler 			return -rte_errno;
60a1572312SShahaf Shuler 		}
6129c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key,
6229c1d8bbSNélio Laranjeiro 						     rss_conf->rss_key_len, 0);
6329c1d8bbSNélio Laranjeiro 		if (!priv->rss_conf.rss_key) {
64a6d83b6aSNélio Laranjeiro 			rte_errno = ENOMEM;
65a6d83b6aSNélio Laranjeiro 			return -rte_errno;
6629c1d8bbSNélio Laranjeiro 		}
67920b4e54SNélio Laranjeiro 		memcpy(priv->rss_conf.rss_key, rss_conf->rss_key,
6829c1d8bbSNélio Laranjeiro 		       rss_conf->rss_key_len);
6929c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key_len = rss_conf->rss_key_len;
7029c1d8bbSNélio Laranjeiro 	}
7129c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = rss_conf->rss_hf;
7266669155SDahir Osman 	/* Enable the RSS hash in all Rx queues. */
7366669155SDahir Osman 	for (i = 0, idx = 0; idx != priv->rxqs_n; ++i) {
7466669155SDahir Osman 		if (!(*priv->rxqs)[i])
7566669155SDahir Osman 			continue;
7666669155SDahir Osman 		(*priv->rxqs)[i]->rss_hash = !!rss_conf->rss_hf &&
7766669155SDahir Osman 			!!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS);
7866669155SDahir Osman 		++idx;
7966669155SDahir Osman 	}
80a6d83b6aSNélio Laranjeiro 	return 0;
812f97422eSNelio Laranjeiro }
822f97422eSNelio Laranjeiro 
832f97422eSNelio Laranjeiro /**
842f97422eSNelio Laranjeiro  * DPDK callback to get the RSS hash configuration.
852f97422eSNelio Laranjeiro  *
862f97422eSNelio Laranjeiro  * @param dev
872f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
882f97422eSNelio Laranjeiro  * @param[in, out] rss_conf
892f97422eSNelio Laranjeiro  *   RSS configuration data.
902f97422eSNelio Laranjeiro  *
912f97422eSNelio Laranjeiro  * @return
92a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
932f97422eSNelio Laranjeiro  */
942f97422eSNelio Laranjeiro int
952f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev,
962f97422eSNelio Laranjeiro 		       struct rte_eth_rss_conf *rss_conf)
972f97422eSNelio Laranjeiro {
98*dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
992f97422eSNelio Laranjeiro 
100a6d83b6aSNélio Laranjeiro 	if (!rss_conf) {
101a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
102a6d83b6aSNélio Laranjeiro 		return -rte_errno;
103a6d83b6aSNélio Laranjeiro 	}
104920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key &&
105920b4e54SNélio Laranjeiro 	    (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) {
10629c1d8bbSNélio Laranjeiro 		memcpy(rss_conf->rss_key, priv->rss_conf.rss_key,
10729c1d8bbSNélio Laranjeiro 		       priv->rss_conf.rss_key_len);
108920b4e54SNélio Laranjeiro 	}
109920b4e54SNélio Laranjeiro 	rss_conf->rss_key_len = priv->rss_conf.rss_key_len;
110920b4e54SNélio Laranjeiro 	rss_conf->rss_hf = priv->rss_conf.rss_hf;
111920b4e54SNélio Laranjeiro 	return 0;
1122f97422eSNelio Laranjeiro }
113634efbc2SNelio Laranjeiro 
114634efbc2SNelio Laranjeiro /**
115634efbc2SNelio Laranjeiro  * Allocate/reallocate RETA index table.
116634efbc2SNelio Laranjeiro  *
117af4f09f2SNélio Laranjeiro  * @param dev
118af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
119634efbc2SNelio Laranjeiro  * @praram reta_size
120634efbc2SNelio Laranjeiro  *   The size of the array to allocate.
121634efbc2SNelio Laranjeiro  *
122634efbc2SNelio Laranjeiro  * @return
123a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
124634efbc2SNelio Laranjeiro  */
125634efbc2SNelio Laranjeiro int
126af4f09f2SNélio Laranjeiro mlx5_rss_reta_index_resize(struct rte_eth_dev *dev, unsigned int reta_size)
127634efbc2SNelio Laranjeiro {
128*dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
129634efbc2SNelio Laranjeiro 	void *mem;
130634efbc2SNelio Laranjeiro 	unsigned int old_size = priv->reta_idx_n;
131634efbc2SNelio Laranjeiro 
132634efbc2SNelio Laranjeiro 	if (priv->reta_idx_n == reta_size)
133634efbc2SNelio Laranjeiro 		return 0;
134634efbc2SNelio Laranjeiro 
135634efbc2SNelio Laranjeiro 	mem = rte_realloc(priv->reta_idx,
136634efbc2SNelio Laranjeiro 			  reta_size * sizeof((*priv->reta_idx)[0]), 0);
137a6d83b6aSNélio Laranjeiro 	if (!mem) {
138a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
139a6d83b6aSNélio Laranjeiro 		return -rte_errno;
140a6d83b6aSNélio Laranjeiro 	}
141634efbc2SNelio Laranjeiro 	priv->reta_idx = mem;
142634efbc2SNelio Laranjeiro 	priv->reta_idx_n = reta_size;
143634efbc2SNelio Laranjeiro 	if (old_size < reta_size)
144634efbc2SNelio Laranjeiro 		memset(&(*priv->reta_idx)[old_size], 0,
145634efbc2SNelio Laranjeiro 		       (reta_size - old_size) *
146634efbc2SNelio Laranjeiro 		       sizeof((*priv->reta_idx)[0]));
147634efbc2SNelio Laranjeiro 	return 0;
148634efbc2SNelio Laranjeiro }
149634efbc2SNelio Laranjeiro 
150634efbc2SNelio Laranjeiro /**
151634efbc2SNelio Laranjeiro  * DPDK callback to get the RETA indirection table.
152634efbc2SNelio Laranjeiro  *
153634efbc2SNelio Laranjeiro  * @param dev
154634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
155634efbc2SNelio Laranjeiro  * @param reta_conf
156634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
157634efbc2SNelio Laranjeiro  * @param reta_size
158634efbc2SNelio Laranjeiro  *   Size of the RETA table.
159634efbc2SNelio Laranjeiro  *
160634efbc2SNelio Laranjeiro  * @return
161a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
162634efbc2SNelio Laranjeiro  */
163634efbc2SNelio Laranjeiro int
164634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev,
165634efbc2SNelio Laranjeiro 			struct rte_eth_rss_reta_entry64 *reta_conf,
166634efbc2SNelio Laranjeiro 			uint16_t reta_size)
167634efbc2SNelio Laranjeiro {
168*dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
169af4f09f2SNélio Laranjeiro 	unsigned int idx;
170af4f09f2SNélio Laranjeiro 	unsigned int i;
171634efbc2SNelio Laranjeiro 
172a6d83b6aSNélio Laranjeiro 	if (!reta_size || reta_size > priv->reta_idx_n) {
173a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
174a6d83b6aSNélio Laranjeiro 		return -rte_errno;
175a6d83b6aSNélio Laranjeiro 	}
176af4f09f2SNélio Laranjeiro 	/* Fill each entry of the table even if its bit is not set. */
177af4f09f2SNélio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
178af4f09f2SNélio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
179af4f09f2SNélio Laranjeiro 		reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] =
180af4f09f2SNélio Laranjeiro 			(*priv->reta_idx)[i];
181af4f09f2SNélio Laranjeiro 	}
182af4f09f2SNélio Laranjeiro 	return 0;
183634efbc2SNelio Laranjeiro }
184634efbc2SNelio Laranjeiro 
185634efbc2SNelio Laranjeiro /**
186634efbc2SNelio Laranjeiro  * DPDK callback to update the RETA indirection table.
187634efbc2SNelio Laranjeiro  *
188634efbc2SNelio Laranjeiro  * @param dev
189634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
190634efbc2SNelio Laranjeiro  * @param reta_conf
191634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
192634efbc2SNelio Laranjeiro  * @param reta_size
193634efbc2SNelio Laranjeiro  *   Size of the RETA table.
194634efbc2SNelio Laranjeiro  *
195634efbc2SNelio Laranjeiro  * @return
196a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
197634efbc2SNelio Laranjeiro  */
198634efbc2SNelio Laranjeiro int
199634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,
200634efbc2SNelio Laranjeiro 			 struct rte_eth_rss_reta_entry64 *reta_conf,
201634efbc2SNelio Laranjeiro 			 uint16_t reta_size)
202634efbc2SNelio Laranjeiro {
203634efbc2SNelio Laranjeiro 	int ret;
204*dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
205af4f09f2SNélio Laranjeiro 	unsigned int idx;
206af4f09f2SNélio Laranjeiro 	unsigned int i;
207af4f09f2SNélio Laranjeiro 	unsigned int pos;
208634efbc2SNelio Laranjeiro 
209a6d83b6aSNélio Laranjeiro 	if (!reta_size) {
210a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
211a6d83b6aSNélio Laranjeiro 		return -rte_errno;
212a6d83b6aSNélio Laranjeiro 	}
213af4f09f2SNélio Laranjeiro 	ret = mlx5_rss_reta_index_resize(dev, reta_size);
214af4f09f2SNélio Laranjeiro 	if (ret)
215af4f09f2SNélio Laranjeiro 		return ret;
216af4f09f2SNélio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
217af4f09f2SNélio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
218af4f09f2SNélio Laranjeiro 		pos = i % RTE_RETA_GROUP_SIZE;
219af4f09f2SNélio Laranjeiro 		if (((reta_conf[idx].mask >> i) & 0x1) == 0)
220af4f09f2SNélio Laranjeiro 			continue;
221af4f09f2SNélio Laranjeiro 		assert(reta_conf[idx].reta[pos] < priv->rxqs_n);
222af4f09f2SNélio Laranjeiro 		(*priv->reta_idx)[i] = reta_conf[idx].reta[pos];
223af4f09f2SNélio Laranjeiro 	}
2243f2fe392SNélio Laranjeiro 	if (dev->data->dev_started) {
2253f2fe392SNélio Laranjeiro 		mlx5_dev_stop(dev);
226a6d83b6aSNélio Laranjeiro 		return mlx5_dev_start(dev);
2273f2fe392SNélio Laranjeiro 	}
228a6d83b6aSNélio Laranjeiro 	return 0;
229634efbc2SNelio Laranjeiro }
230