xref: /dpdk/drivers/net/mlx5/mlx5_rss.c (revision a6d83b6a9209a198fa5a7d2f9cbb37190e256f9c)
18fd92a66SOlivier 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
38*a6d83b6aSNé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;
452f97422eSNelio Laranjeiro 
46b365799bSNélio Laranjeiro 	if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) {
47*a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
48*a6d83b6aSNélio Laranjeiro 		return -rte_errno;
49b365799bSNélio Laranjeiro 	}
50920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key && rss_conf->rss_key_len) {
5129c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key,
5229c1d8bbSNélio Laranjeiro 						     rss_conf->rss_key_len, 0);
5329c1d8bbSNélio Laranjeiro 		if (!priv->rss_conf.rss_key) {
54*a6d83b6aSNélio Laranjeiro 			rte_errno = ENOMEM;
55*a6d83b6aSNélio Laranjeiro 			return -rte_errno;
5629c1d8bbSNélio Laranjeiro 		}
57920b4e54SNélio Laranjeiro 		memcpy(priv->rss_conf.rss_key, rss_conf->rss_key,
5829c1d8bbSNélio Laranjeiro 		       rss_conf->rss_key_len);
5929c1d8bbSNélio Laranjeiro 		priv->rss_conf.rss_key_len = rss_conf->rss_key_len;
6029c1d8bbSNélio Laranjeiro 	}
6129c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = rss_conf->rss_hf;
62*a6d83b6aSNélio Laranjeiro 	return 0;
632f97422eSNelio Laranjeiro }
642f97422eSNelio Laranjeiro 
652f97422eSNelio Laranjeiro /**
662f97422eSNelio Laranjeiro  * DPDK callback to get the RSS hash configuration.
672f97422eSNelio Laranjeiro  *
682f97422eSNelio Laranjeiro  * @param dev
692f97422eSNelio Laranjeiro  *   Pointer to Ethernet device structure.
702f97422eSNelio Laranjeiro  * @param[in, out] rss_conf
712f97422eSNelio Laranjeiro  *   RSS configuration data.
722f97422eSNelio Laranjeiro  *
732f97422eSNelio Laranjeiro  * @return
74*a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
752f97422eSNelio Laranjeiro  */
762f97422eSNelio Laranjeiro int
772f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev,
782f97422eSNelio Laranjeiro 		       struct rte_eth_rss_conf *rss_conf)
792f97422eSNelio Laranjeiro {
802f97422eSNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
812f97422eSNelio Laranjeiro 
82*a6d83b6aSNélio Laranjeiro 	if (!rss_conf) {
83*a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
84*a6d83b6aSNélio Laranjeiro 		return -rte_errno;
85*a6d83b6aSNélio Laranjeiro 	}
86920b4e54SNélio Laranjeiro 	if (rss_conf->rss_key &&
87920b4e54SNélio Laranjeiro 	    (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) {
8829c1d8bbSNélio Laranjeiro 		memcpy(rss_conf->rss_key, priv->rss_conf.rss_key,
8929c1d8bbSNélio Laranjeiro 		       priv->rss_conf.rss_key_len);
90920b4e54SNélio Laranjeiro 	}
91920b4e54SNélio Laranjeiro 	rss_conf->rss_key_len = priv->rss_conf.rss_key_len;
92920b4e54SNélio Laranjeiro 	rss_conf->rss_hf = priv->rss_conf.rss_hf;
93920b4e54SNélio Laranjeiro 	return 0;
942f97422eSNelio Laranjeiro }
95634efbc2SNelio Laranjeiro 
96634efbc2SNelio Laranjeiro /**
97634efbc2SNelio Laranjeiro  * Allocate/reallocate RETA index table.
98634efbc2SNelio Laranjeiro  *
99af4f09f2SNélio Laranjeiro  * @param dev
100af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
101634efbc2SNelio Laranjeiro  * @praram reta_size
102634efbc2SNelio Laranjeiro  *   The size of the array to allocate.
103634efbc2SNelio Laranjeiro  *
104634efbc2SNelio Laranjeiro  * @return
105*a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
106634efbc2SNelio Laranjeiro  */
107634efbc2SNelio Laranjeiro int
108af4f09f2SNélio Laranjeiro mlx5_rss_reta_index_resize(struct rte_eth_dev *dev, unsigned int reta_size)
109634efbc2SNelio Laranjeiro {
110af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
111634efbc2SNelio Laranjeiro 	void *mem;
112634efbc2SNelio Laranjeiro 	unsigned int old_size = priv->reta_idx_n;
113634efbc2SNelio Laranjeiro 
114634efbc2SNelio Laranjeiro 	if (priv->reta_idx_n == reta_size)
115634efbc2SNelio Laranjeiro 		return 0;
116634efbc2SNelio Laranjeiro 
117634efbc2SNelio Laranjeiro 	mem = rte_realloc(priv->reta_idx,
118634efbc2SNelio Laranjeiro 			  reta_size * sizeof((*priv->reta_idx)[0]), 0);
119*a6d83b6aSNélio Laranjeiro 	if (!mem) {
120*a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
121*a6d83b6aSNélio Laranjeiro 		return -rte_errno;
122*a6d83b6aSNélio Laranjeiro 	}
123634efbc2SNelio Laranjeiro 	priv->reta_idx = mem;
124634efbc2SNelio Laranjeiro 	priv->reta_idx_n = reta_size;
125634efbc2SNelio Laranjeiro 	if (old_size < reta_size)
126634efbc2SNelio Laranjeiro 		memset(&(*priv->reta_idx)[old_size], 0,
127634efbc2SNelio Laranjeiro 		       (reta_size - old_size) *
128634efbc2SNelio Laranjeiro 		       sizeof((*priv->reta_idx)[0]));
129634efbc2SNelio Laranjeiro 	return 0;
130634efbc2SNelio Laranjeiro }
131634efbc2SNelio Laranjeiro 
132634efbc2SNelio Laranjeiro /**
133634efbc2SNelio Laranjeiro  * DPDK callback to get the RETA indirection table.
134634efbc2SNelio Laranjeiro  *
135634efbc2SNelio Laranjeiro  * @param dev
136634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
137634efbc2SNelio Laranjeiro  * @param reta_conf
138634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
139634efbc2SNelio Laranjeiro  * @param reta_size
140634efbc2SNelio Laranjeiro  *   Size of the RETA table.
141634efbc2SNelio Laranjeiro  *
142634efbc2SNelio Laranjeiro  * @return
143*a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
144634efbc2SNelio Laranjeiro  */
145634efbc2SNelio Laranjeiro int
146634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev,
147634efbc2SNelio Laranjeiro 			struct rte_eth_rss_reta_entry64 *reta_conf,
148634efbc2SNelio Laranjeiro 			uint16_t reta_size)
149634efbc2SNelio Laranjeiro {
150634efbc2SNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
151af4f09f2SNélio Laranjeiro 	unsigned int idx;
152af4f09f2SNélio Laranjeiro 	unsigned int i;
153634efbc2SNelio Laranjeiro 
154*a6d83b6aSNélio Laranjeiro 	if (!reta_size || reta_size > priv->reta_idx_n) {
155*a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
156*a6d83b6aSNélio Laranjeiro 		return -rte_errno;
157*a6d83b6aSNélio Laranjeiro 	}
158af4f09f2SNélio Laranjeiro 	/* Fill each entry of the table even if its bit is not set. */
159af4f09f2SNélio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
160af4f09f2SNélio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
161af4f09f2SNélio Laranjeiro 		reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] =
162af4f09f2SNélio Laranjeiro 			(*priv->reta_idx)[i];
163af4f09f2SNélio Laranjeiro 	}
164af4f09f2SNélio Laranjeiro 	return 0;
165634efbc2SNelio Laranjeiro }
166634efbc2SNelio Laranjeiro 
167634efbc2SNelio Laranjeiro /**
168634efbc2SNelio Laranjeiro  * DPDK callback to update the RETA indirection table.
169634efbc2SNelio Laranjeiro  *
170634efbc2SNelio Laranjeiro  * @param dev
171634efbc2SNelio Laranjeiro  *   Pointer to Ethernet device structure.
172634efbc2SNelio Laranjeiro  * @param reta_conf
173634efbc2SNelio Laranjeiro  *   Pointer to RETA configuration structure array.
174634efbc2SNelio Laranjeiro  * @param reta_size
175634efbc2SNelio Laranjeiro  *   Size of the RETA table.
176634efbc2SNelio Laranjeiro  *
177634efbc2SNelio Laranjeiro  * @return
178*a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
179634efbc2SNelio Laranjeiro  */
180634efbc2SNelio Laranjeiro int
181634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,
182634efbc2SNelio Laranjeiro 			 struct rte_eth_rss_reta_entry64 *reta_conf,
183634efbc2SNelio Laranjeiro 			 uint16_t reta_size)
184634efbc2SNelio Laranjeiro {
185634efbc2SNelio Laranjeiro 	int ret;
186634efbc2SNelio Laranjeiro 	struct priv *priv = dev->data->dev_private;
187af4f09f2SNélio Laranjeiro 	unsigned int idx;
188af4f09f2SNélio Laranjeiro 	unsigned int i;
189af4f09f2SNélio Laranjeiro 	unsigned int pos;
190634efbc2SNelio Laranjeiro 
191*a6d83b6aSNélio Laranjeiro 	if (!reta_size) {
192*a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
193*a6d83b6aSNélio Laranjeiro 		return -rte_errno;
194*a6d83b6aSNélio Laranjeiro 	}
195af4f09f2SNélio Laranjeiro 	ret = mlx5_rss_reta_index_resize(dev, reta_size);
196af4f09f2SNélio Laranjeiro 	if (ret)
197af4f09f2SNélio Laranjeiro 		return ret;
198af4f09f2SNélio Laranjeiro 	for (idx = 0, i = 0; (i != reta_size); ++i) {
199af4f09f2SNélio Laranjeiro 		idx = i / RTE_RETA_GROUP_SIZE;
200af4f09f2SNélio Laranjeiro 		pos = i % RTE_RETA_GROUP_SIZE;
201af4f09f2SNélio Laranjeiro 		if (((reta_conf[idx].mask >> i) & 0x1) == 0)
202af4f09f2SNélio Laranjeiro 			continue;
203af4f09f2SNélio Laranjeiro 		assert(reta_conf[idx].reta[pos] < priv->rxqs_n);
204af4f09f2SNélio Laranjeiro 		(*priv->reta_idx)[i] = reta_conf[idx].reta[pos];
205af4f09f2SNélio Laranjeiro 	}
2063f2fe392SNélio Laranjeiro 	if (dev->data->dev_started) {
2073f2fe392SNélio Laranjeiro 		mlx5_dev_stop(dev);
208*a6d83b6aSNélio Laranjeiro 		return mlx5_dev_start(dev);
2093f2fe392SNélio Laranjeiro 	}
210*a6d83b6aSNélio Laranjeiro 	return 0;
211634efbc2SNelio Laranjeiro }
212