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
mlx5_rss_hash_update(struct rte_eth_dev * dev,struct rte_eth_rss_conf * rss_conf)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) {
685cf0707fSXueming Li struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, i);
695cf0707fSXueming Li
705cf0707fSXueming Li if (rxq == NULL || rxq->ctrl == NULL)
7166669155SDahir Osman continue;
725cf0707fSXueming Li rxq->ctrl->rxq.rss_hash = !!rss_conf->rss_hf &&
73295968d1SFerruh Yigit !!(dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS);
7466669155SDahir Osman ++idx;
7566669155SDahir Osman }
76a6d83b6aSNélio Laranjeiro return 0;
772f97422eSNelio Laranjeiro }
782f97422eSNelio Laranjeiro
792f97422eSNelio Laranjeiro /**
802f97422eSNelio Laranjeiro * DPDK callback to get the RSS hash configuration.
812f97422eSNelio Laranjeiro *
822f97422eSNelio Laranjeiro * @param dev
832f97422eSNelio Laranjeiro * Pointer to Ethernet device structure.
842f97422eSNelio Laranjeiro * @param[in, out] rss_conf
852f97422eSNelio Laranjeiro * RSS configuration data.
862f97422eSNelio Laranjeiro *
872f97422eSNelio Laranjeiro * @return
88a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set.
892f97422eSNelio Laranjeiro */
902f97422eSNelio Laranjeiro int
mlx5_rss_hash_conf_get(struct rte_eth_dev * dev,struct rte_eth_rss_conf * rss_conf)912f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev,
922f97422eSNelio Laranjeiro struct rte_eth_rss_conf *rss_conf)
932f97422eSNelio Laranjeiro {
94dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private;
952f97422eSNelio Laranjeiro
96a6d83b6aSNélio Laranjeiro if (!rss_conf) {
97a6d83b6aSNélio Laranjeiro rte_errno = EINVAL;
98a6d83b6aSNélio Laranjeiro return -rte_errno;
99a6d83b6aSNélio Laranjeiro }
100920b4e54SNélio Laranjeiro if (rss_conf->rss_key &&
101920b4e54SNélio Laranjeiro (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) {
10229c1d8bbSNélio Laranjeiro memcpy(rss_conf->rss_key, priv->rss_conf.rss_key,
10329c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len);
104920b4e54SNélio Laranjeiro }
105920b4e54SNélio Laranjeiro rss_conf->rss_key_len = priv->rss_conf.rss_key_len;
106920b4e54SNélio Laranjeiro rss_conf->rss_hf = priv->rss_conf.rss_hf;
107920b4e54SNélio Laranjeiro return 0;
1082f97422eSNelio Laranjeiro }
109634efbc2SNelio Laranjeiro
110634efbc2SNelio Laranjeiro /**
111634efbc2SNelio Laranjeiro * Allocate/reallocate RETA index table.
112634efbc2SNelio Laranjeiro *
113af4f09f2SNélio Laranjeiro * @param dev
114af4f09f2SNélio Laranjeiro * Pointer to Ethernet device.
115634efbc2SNelio Laranjeiro * @praram reta_size
116634efbc2SNelio Laranjeiro * The size of the array to allocate.
117634efbc2SNelio Laranjeiro *
118634efbc2SNelio Laranjeiro * @return
119a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set.
120634efbc2SNelio Laranjeiro */
121634efbc2SNelio Laranjeiro int
mlx5_rss_reta_index_resize(struct rte_eth_dev * dev,unsigned int reta_size)122af4f09f2SNélio Laranjeiro mlx5_rss_reta_index_resize(struct rte_eth_dev *dev, unsigned int reta_size)
123634efbc2SNelio Laranjeiro {
124dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private;
125634efbc2SNelio Laranjeiro void *mem;
126634efbc2SNelio Laranjeiro unsigned int old_size = priv->reta_idx_n;
127634efbc2SNelio Laranjeiro
128634efbc2SNelio Laranjeiro if (priv->reta_idx_n == reta_size)
129634efbc2SNelio Laranjeiro return 0;
130634efbc2SNelio Laranjeiro
13183c2047cSSuanming Mou mem = mlx5_realloc(priv->reta_idx, MLX5_MEM_RTE,
13283c2047cSSuanming Mou reta_size * sizeof((*priv->reta_idx)[0]), 0,
13383c2047cSSuanming Mou SOCKET_ID_ANY);
134a6d83b6aSNélio Laranjeiro if (!mem) {
135a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM;
136a6d83b6aSNélio Laranjeiro return -rte_errno;
137a6d83b6aSNélio Laranjeiro }
138634efbc2SNelio Laranjeiro priv->reta_idx = mem;
139634efbc2SNelio Laranjeiro priv->reta_idx_n = reta_size;
140634efbc2SNelio Laranjeiro if (old_size < reta_size)
141634efbc2SNelio Laranjeiro memset(&(*priv->reta_idx)[old_size], 0,
142634efbc2SNelio Laranjeiro (reta_size - old_size) *
143634efbc2SNelio Laranjeiro sizeof((*priv->reta_idx)[0]));
144634efbc2SNelio Laranjeiro return 0;
145634efbc2SNelio Laranjeiro }
146634efbc2SNelio Laranjeiro
147634efbc2SNelio Laranjeiro /**
148634efbc2SNelio Laranjeiro * DPDK callback to get the RETA indirection table.
149634efbc2SNelio Laranjeiro *
150634efbc2SNelio Laranjeiro * @param dev
151634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure.
152634efbc2SNelio Laranjeiro * @param reta_conf
153634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array.
154634efbc2SNelio Laranjeiro * @param reta_size
155634efbc2SNelio Laranjeiro * Size of the RETA table.
156634efbc2SNelio Laranjeiro *
157634efbc2SNelio Laranjeiro * @return
158a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set.
159634efbc2SNelio Laranjeiro */
160634efbc2SNelio Laranjeiro int
mlx5_dev_rss_reta_query(struct rte_eth_dev * dev,struct rte_eth_rss_reta_entry64 * reta_conf,uint16_t reta_size)161634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev,
162634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf,
163634efbc2SNelio Laranjeiro uint16_t reta_size)
164634efbc2SNelio Laranjeiro {
165dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private;
166af4f09f2SNélio Laranjeiro unsigned int idx;
167af4f09f2SNélio Laranjeiro unsigned int i;
168634efbc2SNelio Laranjeiro
169a6d83b6aSNélio Laranjeiro if (!reta_size || reta_size > priv->reta_idx_n) {
170a6d83b6aSNélio Laranjeiro rte_errno = EINVAL;
171a6d83b6aSNélio Laranjeiro return -rte_errno;
172a6d83b6aSNélio Laranjeiro }
173af4f09f2SNélio Laranjeiro /* Fill each entry of the table even if its bit is not set. */
174af4f09f2SNélio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) {
175295968d1SFerruh Yigit idx = i / RTE_ETH_RETA_GROUP_SIZE;
176295968d1SFerruh Yigit reta_conf[idx].reta[i % RTE_ETH_RETA_GROUP_SIZE] =
177af4f09f2SNélio Laranjeiro (*priv->reta_idx)[i];
178af4f09f2SNélio Laranjeiro }
179af4f09f2SNélio Laranjeiro return 0;
180634efbc2SNelio Laranjeiro }
181634efbc2SNelio Laranjeiro
182634efbc2SNelio Laranjeiro /**
183634efbc2SNelio Laranjeiro * DPDK callback to update the RETA indirection table.
184634efbc2SNelio Laranjeiro *
185634efbc2SNelio Laranjeiro * @param dev
186634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure.
187634efbc2SNelio Laranjeiro * @param reta_conf
188634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array.
189634efbc2SNelio Laranjeiro * @param reta_size
190634efbc2SNelio Laranjeiro * Size of the RETA table.
191634efbc2SNelio Laranjeiro *
192634efbc2SNelio Laranjeiro * @return
193a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set.
194634efbc2SNelio Laranjeiro */
195634efbc2SNelio Laranjeiro int
mlx5_dev_rss_reta_update(struct rte_eth_dev * dev,struct rte_eth_rss_reta_entry64 * reta_conf,uint16_t reta_size)196634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,
197634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf,
198634efbc2SNelio Laranjeiro uint16_t reta_size)
199634efbc2SNelio Laranjeiro {
200634efbc2SNelio Laranjeiro int ret;
201dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private;
202af4f09f2SNélio Laranjeiro unsigned int idx;
203af4f09f2SNélio Laranjeiro unsigned int i;
204af4f09f2SNélio Laranjeiro unsigned int pos;
205634efbc2SNelio Laranjeiro
206a6d83b6aSNélio Laranjeiro if (!reta_size) {
207a6d83b6aSNélio Laranjeiro rte_errno = EINVAL;
208a6d83b6aSNélio Laranjeiro return -rte_errno;
209a6d83b6aSNélio Laranjeiro }
210af4f09f2SNélio Laranjeiro ret = mlx5_rss_reta_index_resize(dev, reta_size);
211af4f09f2SNélio Laranjeiro if (ret)
212af4f09f2SNélio Laranjeiro return ret;
213af4f09f2SNélio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) {
214295968d1SFerruh Yigit idx = i / RTE_ETH_RETA_GROUP_SIZE;
215295968d1SFerruh Yigit pos = i % RTE_ETH_RETA_GROUP_SIZE;
2165aeb7fabSMaxime Coquelin if (((reta_conf[idx].mask >> pos) & 0x1) == 0)
217af4f09f2SNélio Laranjeiro continue;
2188e46d4e1SAlexander Kozyrev MLX5_ASSERT(reta_conf[idx].reta[pos] < priv->rxqs_n);
219af4f09f2SNélio Laranjeiro (*priv->reta_idx)[i] = reta_conf[idx].reta[pos];
220af4f09f2SNélio Laranjeiro }
221e0d44951SMaxime Leroy priv->skip_default_rss_reta = 1;
222*6b5b3005SBing Zhao return mlx5_traffic_restart(dev);
223634efbc2SNelio Laranjeiro }
224