xref: /dpdk/drivers/net/mlx5/mlx5_rss.c (revision 5feecc57d90b97c579b16d1083ea167f7564530b)
18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
22f97422eSNelio Laranjeiro  * Copyright 2015 6WIND S.A.
3*5feecc57SShahaf 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 {
442f97422eSNelio Laranjeiro 	struct 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) {
53a1572312SShahaf Shuler 		if (rss_conf->rss_key_len != rss_hash_default_key_len) {
54a1572312SShahaf Shuler 			DRV_LOG(ERR,
55a1572312SShahaf Shuler 				"port %u RSS key len must be %zu Bytes long",
56a1572312SShahaf Shuler 				dev->data->port_id, rss_hash_default_key_len);
57a1572312SShahaf Shuler 			rte_errno = EINVAL;
58a1572312SShahaf Shuler 			return -rte_errno;
59a1572312SShahaf Shuler 		}
6029c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key,
6129c1d8bbSNélio Laranjeiro 						     rss_conf->rss_key_len, 0);
6229c1d8bbSNélio Laranjeiro 		if (!priv->rss_conf.rss_key) {
63a6d83b6aSNélio Laranjeiro 			rte_errno = ENOMEM;
64a6d83b6aSNélio Laranjeiro 			return -rte_errno;
6529c1d8bbSNélio Laranjeiro 		}
66920b4e54SNélio Laranjeiro 		memcpy(priv->rss_conf.rss_key, rss_conf->rss_key,
6729c1d8bbSNélio Laranjeiro 		       rss_conf->rss_key_len);
6829c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key_len = rss_conf->rss_key_len;
6929c1d8bbSNélio Laranjeiro 	}
7029c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = rss_conf->rss_hf;
7166669155SDahir Osman 	/* Enable the RSS hash in all Rx queues. */
7266669155SDahir Osman 	for (i = 0, idx = 0; idx != priv->rxqs_n; ++i) {
7366669155SDahir Osman 		if (!(*priv->rxqs)[i])
7466669155SDahir Osman 			continue;
7566669155SDahir Osman 		(*priv->rxqs)[i]->rss_hash = !!rss_conf->rss_hf &&
7666669155SDahir Osman 			!!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS);
7766669155SDahir Osman 		++idx;
7866669155SDahir Osman 	}
79a6d83b6aSNélio Laranjeiro 	return 0;
802f97422eSNelio Laranjeiro }
812f97422eSNelio Laranjeiro 
822f97422eSNelio Laranjeiro /**
832f97422eSNelio Laranjeiro  * DPDK callback to get the RSS hash configuration.
842f97422eSNelio Laranjeiro  *
852f97422eSNelio Laranjeiro  * @param dev
862f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
872f97422eSNelio Laranjeiro  * @param[in, out] rss_conf
882f97422eSNelio Laranjeiro  *   RSS configuration data.
892f97422eSNelio Laranjeiro  *
902f97422eSNelio Laranjeiro  * @return
91a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
922f97422eSNelio Laranjeiro  */
932f97422eSNelio Laranjeiro int
942f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev,
952f97422eSNelio Laranjeiro 		       struct rte_eth_rss_conf *rss_conf)
962f97422eSNelio Laranjeiro {
972f97422eSNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
982f97422eSNelio Laranjeiro 
99a6d83b6aSNélio Laranjeiro 	if (!rss_conf) {
100a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
101a6d83b6aSNélio Laranjeiro 		return -rte_errno;
102a6d83b6aSNélio Laranjeiro 	}
103920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key &&
104920b4e54SNélio Laranjeiro 	    (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) {
10529c1d8bbSNélio Laranjeiro 		memcpy(rss_conf->rss_key, priv->rss_conf.rss_key,
10629c1d8bbSNélio Laranjeiro 		       priv->rss_conf.rss_key_len);
107920b4e54SNélio Laranjeiro 	}
108920b4e54SNélio Laranjeiro 	rss_conf->rss_key_len = priv->rss_conf.rss_key_len;
109920b4e54SNélio Laranjeiro 	rss_conf->rss_hf = priv->rss_conf.rss_hf;
110920b4e54SNélio Laranjeiro 	return 0;
1112f97422eSNelio Laranjeiro }
112634efbc2SNelio Laranjeiro 
113634efbc2SNelio Laranjeiro /**
114634efbc2SNelio Laranjeiro  * Allocate/reallocate RETA index table.
115634efbc2SNelio Laranjeiro  *
116af4f09f2SNélio Laranjeiro  * @param dev
117af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
118634efbc2SNelio Laranjeiro  * @praram reta_size
119634efbc2SNelio Laranjeiro  *   The size of the array to allocate.
120634efbc2SNelio Laranjeiro  *
121634efbc2SNelio Laranjeiro  * @return
122a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
123634efbc2SNelio Laranjeiro  */
124634efbc2SNelio Laranjeiro int
125af4f09f2SNélio Laranjeiro mlx5_rss_reta_index_resize(struct rte_eth_dev *dev, unsigned int reta_size)
126634efbc2SNelio Laranjeiro {
127af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
128634efbc2SNelio Laranjeiro 	void *mem;
129634efbc2SNelio Laranjeiro 	unsigned int old_size = priv->reta_idx_n;
130634efbc2SNelio Laranjeiro 
131634efbc2SNelio Laranjeiro 	if (priv->reta_idx_n == reta_size)
132634efbc2SNelio Laranjeiro 		return 0;
133634efbc2SNelio Laranjeiro 
134634efbc2SNelio Laranjeiro 	mem = rte_realloc(priv->reta_idx,
135634efbc2SNelio Laranjeiro 			  reta_size * sizeof((*priv->reta_idx)[0]), 0);
136a6d83b6aSNélio Laranjeiro 	if (!mem) {
137a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
138a6d83b6aSNélio Laranjeiro 		return -rte_errno;
139a6d83b6aSNélio Laranjeiro 	}
140634efbc2SNelio Laranjeiro 	priv->reta_idx = mem;
141634efbc2SNelio Laranjeiro 	priv->reta_idx_n = reta_size;
142634efbc2SNelio Laranjeiro 	if (old_size < reta_size)
143634efbc2SNelio Laranjeiro 		memset(&(*priv->reta_idx)[old_size], 0,
144634efbc2SNelio Laranjeiro 		       (reta_size - old_size) *
145634efbc2SNelio Laranjeiro 		       sizeof((*priv->reta_idx)[0]));
146634efbc2SNelio Laranjeiro 	return 0;
147634efbc2SNelio Laranjeiro }
148634efbc2SNelio Laranjeiro 
149634efbc2SNelio Laranjeiro /**
150634efbc2SNelio Laranjeiro  * DPDK callback to get the RETA indirection table.
151634efbc2SNelio Laranjeiro  *
152634efbc2SNelio Laranjeiro  * @param dev
153634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
154634efbc2SNelio Laranjeiro  * @param reta_conf
155634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
156634efbc2SNelio Laranjeiro  * @param reta_size
157634efbc2SNelio Laranjeiro  *   Size of the RETA table.
158634efbc2SNelio Laranjeiro  *
159634efbc2SNelio Laranjeiro  * @return
160a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
161634efbc2SNelio Laranjeiro  */
162634efbc2SNelio Laranjeiro int
163634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev,
164634efbc2SNelio Laranjeiro 			struct rte_eth_rss_reta_entry64 *reta_conf,
165634efbc2SNelio Laranjeiro 			uint16_t reta_size)
166634efbc2SNelio Laranjeiro {
167634efbc2SNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
168af4f09f2SNélio Laranjeiro 	unsigned int idx;
169af4f09f2SNélio Laranjeiro 	unsigned int i;
170634efbc2SNelio Laranjeiro 
171a6d83b6aSNélio Laranjeiro 	if (!reta_size || reta_size > priv->reta_idx_n) {
172a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
173a6d83b6aSNélio Laranjeiro 		return -rte_errno;
174a6d83b6aSNélio Laranjeiro 	}
175af4f09f2SNélio Laranjeiro 	/* Fill each entry of the table even if its bit is not set. */
176af4f09f2SNélio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
177af4f09f2SNélio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
178af4f09f2SNélio Laranjeiro 		reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] =
179af4f09f2SNélio Laranjeiro 			(*priv->reta_idx)[i];
180af4f09f2SNélio Laranjeiro 	}
181af4f09f2SNélio Laranjeiro 	return 0;
182634efbc2SNelio Laranjeiro }
183634efbc2SNelio Laranjeiro 
184634efbc2SNelio Laranjeiro /**
185634efbc2SNelio Laranjeiro  * DPDK callback to update the RETA indirection table.
186634efbc2SNelio Laranjeiro  *
187634efbc2SNelio Laranjeiro  * @param dev
188634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
189634efbc2SNelio Laranjeiro  * @param reta_conf
190634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
191634efbc2SNelio Laranjeiro  * @param reta_size
192634efbc2SNelio Laranjeiro  *   Size of the RETA table.
193634efbc2SNelio Laranjeiro  *
194634efbc2SNelio Laranjeiro  * @return
195a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
196634efbc2SNelio Laranjeiro  */
197634efbc2SNelio Laranjeiro int
198634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,
199634efbc2SNelio Laranjeiro 			 struct rte_eth_rss_reta_entry64 *reta_conf,
200634efbc2SNelio Laranjeiro 			 uint16_t reta_size)
201634efbc2SNelio Laranjeiro {
202634efbc2SNelio Laranjeiro 	int ret;
203634efbc2SNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
204af4f09f2SNélio Laranjeiro 	unsigned int idx;
205af4f09f2SNélio Laranjeiro 	unsigned int i;
206af4f09f2SNélio Laranjeiro 	unsigned int pos;
207634efbc2SNelio Laranjeiro 
208a6d83b6aSNélio Laranjeiro 	if (!reta_size) {
209a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
210a6d83b6aSNélio Laranjeiro 		return -rte_errno;
211a6d83b6aSNélio Laranjeiro 	}
212af4f09f2SNélio Laranjeiro 	ret = mlx5_rss_reta_index_resize(dev, reta_size);
213af4f09f2SNélio Laranjeiro 	if (ret)
214af4f09f2SNélio Laranjeiro 		return ret;
215af4f09f2SNélio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
216af4f09f2SNélio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
217af4f09f2SNélio Laranjeiro 		pos = i % RTE_RETA_GROUP_SIZE;
218af4f09f2SNélio Laranjeiro 		if (((reta_conf[idx].mask >> i) & 0x1) == 0)
219af4f09f2SNélio Laranjeiro 			continue;
220af4f09f2SNélio Laranjeiro 		assert(reta_conf[idx].reta[pos] < priv->rxqs_n);
221af4f09f2SNélio Laranjeiro 		(*priv->reta_idx)[i] = reta_conf[idx].reta[pos];
222af4f09f2SNélio Laranjeiro 	}
2233f2fe392SNélio Laranjeiro 	if (dev->data->dev_started) {
2243f2fe392SNélio Laranjeiro 		mlx5_dev_stop(dev);
225a6d83b6aSNélio Laranjeiro 		return mlx5_dev_start(dev);
2263f2fe392SNélio Laranjeiro 	}
227a6d83b6aSNélio Laranjeiro 	return 0;
228634efbc2SNelio Laranjeiro }
229