xref: /dpdk/drivers/net/mlx5/mlx5_rss.c (revision 5aeb7fab59fef7b9cb01ec58ef32d1068923b6d3)
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 #include <rte_malloc.h>
12df96fd0dSBruce Richardson #include <ethdev_driver.h>
132f97422eSNelio Laranjeiro 
1483c2047cSSuanming Mou #include <mlx5_malloc.h>
1583c2047cSSuanming Mou 
16b365799bSNélio Laranjeiro #include "mlx5_defs.h"
177b4f1e6bSMatan Azrad #include "mlx5.h"
182f97422eSNelio Laranjeiro #include "mlx5_rxtx.h"
19151cbe3aSMichael Baum #include "mlx5_rx.h"
202f97422eSNelio Laranjeiro 
212f97422eSNelio Laranjeiro /**
222f97422eSNelio Laranjeiro  * DPDK callback to update the RSS hash configuration.
232f97422eSNelio Laranjeiro  *
242f97422eSNelio Laranjeiro  * @param dev
252f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
262f97422eSNelio Laranjeiro  * @param[in] rss_conf
272f97422eSNelio Laranjeiro  *   RSS configuration data.
282f97422eSNelio Laranjeiro  *
292f97422eSNelio Laranjeiro  * @return
30a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
312f97422eSNelio Laranjeiro  */
322f97422eSNelio Laranjeiro int
332f97422eSNelio Laranjeiro mlx5_rss_hash_update(struct rte_eth_dev *dev,
342f97422eSNelio Laranjeiro 		     struct rte_eth_rss_conf *rss_conf)
352f97422eSNelio Laranjeiro {
36dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
3766669155SDahir Osman 	unsigned int i;
3866669155SDahir Osman 	unsigned int idx;
392f97422eSNelio Laranjeiro 
40b365799bSNélio Laranjeiro 	if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) {
41a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
42a6d83b6aSNélio Laranjeiro 		return -rte_errno;
43b365799bSNélio Laranjeiro 	}
44920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key && rss_conf->rss_key_len) {
45c388a2f6SNelio Laranjeiro 		if (rss_conf->rss_key_len != MLX5_RSS_HASH_KEY_LEN) {
46a1572312SShahaf Shuler 			DRV_LOG(ERR,
47c388a2f6SNelio Laranjeiro 				"port %u RSS key len must be %s Bytes long",
48c388a2f6SNelio Laranjeiro 				dev->data->port_id,
49c388a2f6SNelio Laranjeiro 				RTE_STR(MLX5_RSS_HASH_KEY_LEN));
50a1572312SShahaf Shuler 			rte_errno = EINVAL;
51a1572312SShahaf Shuler 			return -rte_errno;
52a1572312SShahaf Shuler 		}
5383c2047cSSuanming Mou 		priv->rss_conf.rss_key = mlx5_realloc(priv->rss_conf.rss_key,
5483c2047cSSuanming Mou 						      MLX5_MEM_RTE,
5583c2047cSSuanming Mou 						      rss_conf->rss_key_len,
5683c2047cSSuanming Mou 						      0, SOCKET_ID_ANY);
5729c1d8bbSNélio Laranjeiro 		if (!priv->rss_conf.rss_key) {
58a6d83b6aSNélio Laranjeiro 			rte_errno = ENOMEM;
59a6d83b6aSNélio Laranjeiro 			return -rte_errno;
6029c1d8bbSNélio Laranjeiro 		}
61920b4e54SNélio Laranjeiro 		memcpy(priv->rss_conf.rss_key, rss_conf->rss_key,
6229c1d8bbSNélio Laranjeiro 		       rss_conf->rss_key_len);
6329c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key_len = rss_conf->rss_key_len;
6429c1d8bbSNélio Laranjeiro 	}
6529c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = rss_conf->rss_hf;
6666669155SDahir Osman 	/* Enable the RSS hash in all Rx queues. */
6766669155SDahir Osman 	for (i = 0, idx = 0; idx != priv->rxqs_n; ++i) {
6866669155SDahir Osman 		if (!(*priv->rxqs)[i])
6966669155SDahir Osman 			continue;
7066669155SDahir Osman 		(*priv->rxqs)[i]->rss_hash = !!rss_conf->rss_hf &&
71295968d1SFerruh Yigit 			!!(dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS);
7266669155SDahir Osman 		++idx;
7366669155SDahir Osman 	}
74a6d83b6aSNélio Laranjeiro 	return 0;
752f97422eSNelio Laranjeiro }
762f97422eSNelio Laranjeiro 
772f97422eSNelio Laranjeiro /**
782f97422eSNelio Laranjeiro  * DPDK callback to get the RSS hash configuration.
792f97422eSNelio Laranjeiro  *
802f97422eSNelio Laranjeiro  * @param dev
812f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
822f97422eSNelio Laranjeiro  * @param[in, out] rss_conf
832f97422eSNelio Laranjeiro  *   RSS configuration data.
842f97422eSNelio Laranjeiro  *
852f97422eSNelio Laranjeiro  * @return
86a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
872f97422eSNelio Laranjeiro  */
882f97422eSNelio Laranjeiro int
892f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev,
902f97422eSNelio Laranjeiro 		       struct rte_eth_rss_conf *rss_conf)
912f97422eSNelio Laranjeiro {
92dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
932f97422eSNelio Laranjeiro 
94a6d83b6aSNélio Laranjeiro 	if (!rss_conf) {
95a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
96a6d83b6aSNélio Laranjeiro 		return -rte_errno;
97a6d83b6aSNélio Laranjeiro 	}
98920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key &&
99920b4e54SNélio Laranjeiro 	    (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) {
10029c1d8bbSNélio Laranjeiro 		memcpy(rss_conf->rss_key, priv->rss_conf.rss_key,
10129c1d8bbSNélio Laranjeiro 		       priv->rss_conf.rss_key_len);
102920b4e54SNélio Laranjeiro 	}
103920b4e54SNélio Laranjeiro 	rss_conf->rss_key_len = priv->rss_conf.rss_key_len;
104920b4e54SNélio Laranjeiro 	rss_conf->rss_hf = priv->rss_conf.rss_hf;
105920b4e54SNélio Laranjeiro 	return 0;
1062f97422eSNelio Laranjeiro }
107634efbc2SNelio Laranjeiro 
108634efbc2SNelio Laranjeiro /**
109634efbc2SNelio Laranjeiro  * Allocate/reallocate RETA index table.
110634efbc2SNelio Laranjeiro  *
111af4f09f2SNélio Laranjeiro  * @param dev
112af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
113634efbc2SNelio Laranjeiro  * @praram reta_size
114634efbc2SNelio Laranjeiro  *   The size of the array to allocate.
115634efbc2SNelio Laranjeiro  *
116634efbc2SNelio Laranjeiro  * @return
117a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
118634efbc2SNelio Laranjeiro  */
119634efbc2SNelio Laranjeiro int
120af4f09f2SNélio Laranjeiro mlx5_rss_reta_index_resize(struct rte_eth_dev *dev, unsigned int reta_size)
121634efbc2SNelio Laranjeiro {
122dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
123634efbc2SNelio Laranjeiro 	void *mem;
124634efbc2SNelio Laranjeiro 	unsigned int old_size = priv->reta_idx_n;
125634efbc2SNelio Laranjeiro 
126634efbc2SNelio Laranjeiro 	if (priv->reta_idx_n == reta_size)
127634efbc2SNelio Laranjeiro 		return 0;
128634efbc2SNelio Laranjeiro 
12983c2047cSSuanming Mou 	mem = mlx5_realloc(priv->reta_idx, MLX5_MEM_RTE,
13083c2047cSSuanming Mou 			   reta_size * sizeof((*priv->reta_idx)[0]), 0,
13183c2047cSSuanming Mou 			   SOCKET_ID_ANY);
132a6d83b6aSNélio Laranjeiro 	if (!mem) {
133a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
134a6d83b6aSNélio Laranjeiro 		return -rte_errno;
135a6d83b6aSNélio Laranjeiro 	}
136634efbc2SNelio Laranjeiro 	priv->reta_idx = mem;
137634efbc2SNelio Laranjeiro 	priv->reta_idx_n = reta_size;
138634efbc2SNelio Laranjeiro 	if (old_size < reta_size)
139634efbc2SNelio Laranjeiro 		memset(&(*priv->reta_idx)[old_size], 0,
140634efbc2SNelio Laranjeiro 		       (reta_size - old_size) *
141634efbc2SNelio Laranjeiro 		       sizeof((*priv->reta_idx)[0]));
142634efbc2SNelio Laranjeiro 	return 0;
143634efbc2SNelio Laranjeiro }
144634efbc2SNelio Laranjeiro 
145634efbc2SNelio Laranjeiro /**
146634efbc2SNelio Laranjeiro  * DPDK callback to get the RETA indirection table.
147634efbc2SNelio Laranjeiro  *
148634efbc2SNelio Laranjeiro  * @param dev
149634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
150634efbc2SNelio Laranjeiro  * @param reta_conf
151634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
152634efbc2SNelio Laranjeiro  * @param reta_size
153634efbc2SNelio Laranjeiro  *   Size of the RETA table.
154634efbc2SNelio Laranjeiro  *
155634efbc2SNelio Laranjeiro  * @return
156a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
157634efbc2SNelio Laranjeiro  */
158634efbc2SNelio Laranjeiro int
159634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev,
160634efbc2SNelio Laranjeiro 			struct rte_eth_rss_reta_entry64 *reta_conf,
161634efbc2SNelio Laranjeiro 			uint16_t reta_size)
162634efbc2SNelio Laranjeiro {
163dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
164af4f09f2SNélio Laranjeiro 	unsigned int idx;
165af4f09f2SNélio Laranjeiro 	unsigned int i;
166634efbc2SNelio Laranjeiro 
167a6d83b6aSNélio Laranjeiro 	if (!reta_size || reta_size > priv->reta_idx_n) {
168a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
169a6d83b6aSNélio Laranjeiro 		return -rte_errno;
170a6d83b6aSNélio Laranjeiro 	}
171af4f09f2SNélio Laranjeiro 	/* Fill each entry of the table even if its bit is not set. */
172af4f09f2SNélio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
173295968d1SFerruh Yigit 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
174295968d1SFerruh Yigit 		reta_conf[idx].reta[i % RTE_ETH_RETA_GROUP_SIZE] =
175af4f09f2SNélio Laranjeiro 			(*priv->reta_idx)[i];
176af4f09f2SNélio Laranjeiro 	}
177af4f09f2SNélio Laranjeiro 	return 0;
178634efbc2SNelio Laranjeiro }
179634efbc2SNelio Laranjeiro 
180634efbc2SNelio Laranjeiro /**
181634efbc2SNelio Laranjeiro  * DPDK callback to update the RETA indirection table.
182634efbc2SNelio Laranjeiro  *
183634efbc2SNelio Laranjeiro  * @param dev
184634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
185634efbc2SNelio Laranjeiro  * @param reta_conf
186634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
187634efbc2SNelio Laranjeiro  * @param reta_size
188634efbc2SNelio Laranjeiro  *   Size of the RETA table.
189634efbc2SNelio Laranjeiro  *
190634efbc2SNelio Laranjeiro  * @return
191a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
192634efbc2SNelio Laranjeiro  */
193634efbc2SNelio Laranjeiro int
194634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,
195634efbc2SNelio Laranjeiro 			 struct rte_eth_rss_reta_entry64 *reta_conf,
196634efbc2SNelio Laranjeiro 			 uint16_t reta_size)
197634efbc2SNelio Laranjeiro {
198634efbc2SNelio Laranjeiro 	int ret;
199dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
200af4f09f2SNélio Laranjeiro 	unsigned int idx;
201af4f09f2SNélio Laranjeiro 	unsigned int i;
202af4f09f2SNélio Laranjeiro 	unsigned int pos;
203634efbc2SNelio Laranjeiro 
204a6d83b6aSNélio Laranjeiro 	if (!reta_size) {
205a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
206a6d83b6aSNélio Laranjeiro 		return -rte_errno;
207a6d83b6aSNélio Laranjeiro 	}
208af4f09f2SNélio Laranjeiro 	ret = mlx5_rss_reta_index_resize(dev, reta_size);
209af4f09f2SNélio Laranjeiro 	if (ret)
210af4f09f2SNélio Laranjeiro 		return ret;
211af4f09f2SNélio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
212295968d1SFerruh Yigit 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
213295968d1SFerruh Yigit 		pos = i % RTE_ETH_RETA_GROUP_SIZE;
214*5aeb7fabSMaxime Coquelin 		if (((reta_conf[idx].mask >> pos) & 0x1) == 0)
215af4f09f2SNélio Laranjeiro 			continue;
2168e46d4e1SAlexander Kozyrev 		MLX5_ASSERT(reta_conf[idx].reta[pos] < priv->rxqs_n);
217af4f09f2SNélio Laranjeiro 		(*priv->reta_idx)[i] = reta_conf[idx].reta[pos];
218af4f09f2SNélio Laranjeiro 	}
219e0d44951SMaxime Leroy 
220e0d44951SMaxime Leroy 	priv->skip_default_rss_reta = 1;
221e0d44951SMaxime Leroy 
2223f2fe392SNélio Laranjeiro 	if (dev->data->dev_started) {
2233f2fe392SNélio Laranjeiro 		mlx5_dev_stop(dev);
224a6d83b6aSNélio Laranjeiro 		return mlx5_dev_start(dev);
2253f2fe392SNélio Laranjeiro 	}
226a6d83b6aSNélio Laranjeiro 	return 0;
227634efbc2SNelio Laranjeiro }
228