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