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 /* Verbs header. */ 122f97422eSNelio Laranjeiro /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 132f97422eSNelio Laranjeiro #ifdef PEDANTIC 14fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic" 152f97422eSNelio Laranjeiro #endif 162f97422eSNelio Laranjeiro #include <infiniband/verbs.h> 172f97422eSNelio Laranjeiro #ifdef PEDANTIC 18fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic" 192f97422eSNelio Laranjeiro #endif 202f97422eSNelio Laranjeiro 212f97422eSNelio Laranjeiro #include <rte_malloc.h> 22ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 232f97422eSNelio Laranjeiro 24*83c2047cSSuanming Mou #include <mlx5_malloc.h> 25*83c2047cSSuanming Mou 26b365799bSNélio Laranjeiro #include "mlx5_defs.h" 277b4f1e6bSMatan Azrad #include "mlx5.h" 282f97422eSNelio Laranjeiro #include "mlx5_rxtx.h" 292f97422eSNelio Laranjeiro 302f97422eSNelio Laranjeiro /** 312f97422eSNelio Laranjeiro * DPDK callback to update the RSS hash configuration. 322f97422eSNelio Laranjeiro * 332f97422eSNelio Laranjeiro * @param dev 342f97422eSNelio Laranjeiro * Pointer to Ethernet device structure. 352f97422eSNelio Laranjeiro * @param[in] rss_conf 362f97422eSNelio Laranjeiro * RSS configuration data. 372f97422eSNelio Laranjeiro * 382f97422eSNelio Laranjeiro * @return 39a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 402f97422eSNelio Laranjeiro */ 412f97422eSNelio Laranjeiro int 422f97422eSNelio Laranjeiro mlx5_rss_hash_update(struct rte_eth_dev *dev, 432f97422eSNelio Laranjeiro struct rte_eth_rss_conf *rss_conf) 442f97422eSNelio Laranjeiro { 45dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 4666669155SDahir Osman unsigned int i; 4766669155SDahir Osman unsigned int idx; 482f97422eSNelio Laranjeiro 49b365799bSNélio Laranjeiro if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) { 50a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 51a6d83b6aSNélio Laranjeiro return -rte_errno; 52b365799bSNélio Laranjeiro } 53920b4e54SNélio Laranjeiro if (rss_conf->rss_key && rss_conf->rss_key_len) { 54c388a2f6SNelio Laranjeiro if (rss_conf->rss_key_len != MLX5_RSS_HASH_KEY_LEN) { 55a1572312SShahaf Shuler DRV_LOG(ERR, 56c388a2f6SNelio Laranjeiro "port %u RSS key len must be %s Bytes long", 57c388a2f6SNelio Laranjeiro dev->data->port_id, 58c388a2f6SNelio Laranjeiro RTE_STR(MLX5_RSS_HASH_KEY_LEN)); 59a1572312SShahaf Shuler rte_errno = EINVAL; 60a1572312SShahaf Shuler return -rte_errno; 61a1572312SShahaf Shuler } 62*83c2047cSSuanming Mou priv->rss_conf.rss_key = mlx5_realloc(priv->rss_conf.rss_key, 63*83c2047cSSuanming Mou MLX5_MEM_RTE, 64*83c2047cSSuanming Mou rss_conf->rss_key_len, 65*83c2047cSSuanming Mou 0, SOCKET_ID_ANY); 6629c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 67a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 68a6d83b6aSNélio Laranjeiro return -rte_errno; 6929c1d8bbSNélio Laranjeiro } 70920b4e54SNélio Laranjeiro memcpy(priv->rss_conf.rss_key, rss_conf->rss_key, 7129c1d8bbSNélio Laranjeiro rss_conf->rss_key_len); 7229c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len = rss_conf->rss_key_len; 7329c1d8bbSNélio Laranjeiro } 7429c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = rss_conf->rss_hf; 7566669155SDahir Osman /* Enable the RSS hash in all Rx queues. */ 7666669155SDahir Osman for (i = 0, idx = 0; idx != priv->rxqs_n; ++i) { 7766669155SDahir Osman if (!(*priv->rxqs)[i]) 7866669155SDahir Osman continue; 7966669155SDahir Osman (*priv->rxqs)[i]->rss_hash = !!rss_conf->rss_hf && 8066669155SDahir Osman !!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS); 8166669155SDahir Osman ++idx; 8266669155SDahir Osman } 83a6d83b6aSNélio Laranjeiro return 0; 842f97422eSNelio Laranjeiro } 852f97422eSNelio Laranjeiro 862f97422eSNelio Laranjeiro /** 872f97422eSNelio Laranjeiro * DPDK callback to get the RSS hash configuration. 882f97422eSNelio Laranjeiro * 892f97422eSNelio Laranjeiro * @param dev 902f97422eSNelio Laranjeiro * Pointer to Ethernet device structure. 912f97422eSNelio Laranjeiro * @param[in, out] rss_conf 922f97422eSNelio Laranjeiro * RSS configuration data. 932f97422eSNelio Laranjeiro * 942f97422eSNelio Laranjeiro * @return 95a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 962f97422eSNelio Laranjeiro */ 972f97422eSNelio Laranjeiro int 982f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev, 992f97422eSNelio Laranjeiro struct rte_eth_rss_conf *rss_conf) 1002f97422eSNelio Laranjeiro { 101dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 1022f97422eSNelio Laranjeiro 103a6d83b6aSNélio Laranjeiro if (!rss_conf) { 104a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 105a6d83b6aSNélio Laranjeiro return -rte_errno; 106a6d83b6aSNélio Laranjeiro } 107920b4e54SNélio Laranjeiro if (rss_conf->rss_key && 108920b4e54SNélio Laranjeiro (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) { 10929c1d8bbSNélio Laranjeiro memcpy(rss_conf->rss_key, priv->rss_conf.rss_key, 11029c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len); 111920b4e54SNélio Laranjeiro } 112920b4e54SNélio Laranjeiro rss_conf->rss_key_len = priv->rss_conf.rss_key_len; 113920b4e54SNélio Laranjeiro rss_conf->rss_hf = priv->rss_conf.rss_hf; 114920b4e54SNélio Laranjeiro return 0; 1152f97422eSNelio Laranjeiro } 116634efbc2SNelio Laranjeiro 117634efbc2SNelio Laranjeiro /** 118634efbc2SNelio Laranjeiro * Allocate/reallocate RETA index table. 119634efbc2SNelio Laranjeiro * 120af4f09f2SNélio Laranjeiro * @param dev 121af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 122634efbc2SNelio Laranjeiro * @praram reta_size 123634efbc2SNelio Laranjeiro * The size of the array to allocate. 124634efbc2SNelio Laranjeiro * 125634efbc2SNelio Laranjeiro * @return 126a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 127634efbc2SNelio Laranjeiro */ 128634efbc2SNelio Laranjeiro int 129af4f09f2SNélio Laranjeiro mlx5_rss_reta_index_resize(struct rte_eth_dev *dev, unsigned int reta_size) 130634efbc2SNelio Laranjeiro { 131dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 132634efbc2SNelio Laranjeiro void *mem; 133634efbc2SNelio Laranjeiro unsigned int old_size = priv->reta_idx_n; 134634efbc2SNelio Laranjeiro 135634efbc2SNelio Laranjeiro if (priv->reta_idx_n == reta_size) 136634efbc2SNelio Laranjeiro return 0; 137634efbc2SNelio Laranjeiro 138*83c2047cSSuanming Mou mem = mlx5_realloc(priv->reta_idx, MLX5_MEM_RTE, 139*83c2047cSSuanming Mou reta_size * sizeof((*priv->reta_idx)[0]), 0, 140*83c2047cSSuanming Mou SOCKET_ID_ANY); 141a6d83b6aSNélio Laranjeiro if (!mem) { 142a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 143a6d83b6aSNélio Laranjeiro return -rte_errno; 144a6d83b6aSNélio Laranjeiro } 145634efbc2SNelio Laranjeiro priv->reta_idx = mem; 146634efbc2SNelio Laranjeiro priv->reta_idx_n = reta_size; 147634efbc2SNelio Laranjeiro if (old_size < reta_size) 148634efbc2SNelio Laranjeiro memset(&(*priv->reta_idx)[old_size], 0, 149634efbc2SNelio Laranjeiro (reta_size - old_size) * 150634efbc2SNelio Laranjeiro sizeof((*priv->reta_idx)[0])); 151634efbc2SNelio Laranjeiro return 0; 152634efbc2SNelio Laranjeiro } 153634efbc2SNelio Laranjeiro 154634efbc2SNelio Laranjeiro /** 155634efbc2SNelio Laranjeiro * DPDK callback to get the RETA indirection table. 156634efbc2SNelio Laranjeiro * 157634efbc2SNelio Laranjeiro * @param dev 158634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 159634efbc2SNelio Laranjeiro * @param reta_conf 160634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 161634efbc2SNelio Laranjeiro * @param reta_size 162634efbc2SNelio Laranjeiro * Size of the RETA table. 163634efbc2SNelio Laranjeiro * 164634efbc2SNelio Laranjeiro * @return 165a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 166634efbc2SNelio Laranjeiro */ 167634efbc2SNelio Laranjeiro int 168634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev, 169634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 170634efbc2SNelio Laranjeiro uint16_t reta_size) 171634efbc2SNelio Laranjeiro { 172dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 173af4f09f2SNélio Laranjeiro unsigned int idx; 174af4f09f2SNélio Laranjeiro unsigned int i; 175634efbc2SNelio Laranjeiro 176a6d83b6aSNélio Laranjeiro if (!reta_size || reta_size > priv->reta_idx_n) { 177a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 178a6d83b6aSNélio Laranjeiro return -rte_errno; 179a6d83b6aSNélio Laranjeiro } 180af4f09f2SNélio Laranjeiro /* Fill each entry of the table even if its bit is not set. */ 181af4f09f2SNélio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 182af4f09f2SNélio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 183af4f09f2SNélio Laranjeiro reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] = 184af4f09f2SNélio Laranjeiro (*priv->reta_idx)[i]; 185af4f09f2SNélio Laranjeiro } 186af4f09f2SNélio Laranjeiro return 0; 187634efbc2SNelio Laranjeiro } 188634efbc2SNelio Laranjeiro 189634efbc2SNelio Laranjeiro /** 190634efbc2SNelio Laranjeiro * DPDK callback to update the RETA indirection table. 191634efbc2SNelio Laranjeiro * 192634efbc2SNelio Laranjeiro * @param dev 193634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 194634efbc2SNelio Laranjeiro * @param reta_conf 195634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 196634efbc2SNelio Laranjeiro * @param reta_size 197634efbc2SNelio Laranjeiro * Size of the RETA table. 198634efbc2SNelio Laranjeiro * 199634efbc2SNelio Laranjeiro * @return 200a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 201634efbc2SNelio Laranjeiro */ 202634efbc2SNelio Laranjeiro int 203634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev, 204634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 205634efbc2SNelio Laranjeiro uint16_t reta_size) 206634efbc2SNelio Laranjeiro { 207634efbc2SNelio Laranjeiro int ret; 208dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 209af4f09f2SNélio Laranjeiro unsigned int idx; 210af4f09f2SNélio Laranjeiro unsigned int i; 211af4f09f2SNélio Laranjeiro unsigned int pos; 212634efbc2SNelio Laranjeiro 213a6d83b6aSNélio Laranjeiro if (!reta_size) { 214a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 215a6d83b6aSNélio Laranjeiro return -rte_errno; 216a6d83b6aSNélio Laranjeiro } 217af4f09f2SNélio Laranjeiro ret = mlx5_rss_reta_index_resize(dev, reta_size); 218af4f09f2SNélio Laranjeiro if (ret) 219af4f09f2SNélio Laranjeiro return ret; 220af4f09f2SNélio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 221af4f09f2SNélio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 222af4f09f2SNélio Laranjeiro pos = i % RTE_RETA_GROUP_SIZE; 223af4f09f2SNélio Laranjeiro if (((reta_conf[idx].mask >> i) & 0x1) == 0) 224af4f09f2SNélio Laranjeiro continue; 2258e46d4e1SAlexander Kozyrev MLX5_ASSERT(reta_conf[idx].reta[pos] < priv->rxqs_n); 226af4f09f2SNélio Laranjeiro (*priv->reta_idx)[i] = reta_conf[idx].reta[pos]; 227af4f09f2SNélio Laranjeiro } 2283f2fe392SNélio Laranjeiro if (dev->data->dev_started) { 2293f2fe392SNélio Laranjeiro mlx5_dev_stop(dev); 23063bd1629SOri Kam priv->skip_default_rss_reta = 1; 231a6d83b6aSNélio Laranjeiro return mlx5_dev_start(dev); 2323f2fe392SNélio Laranjeiro } 233a6d83b6aSNélio Laranjeiro return 0; 234634efbc2SNelio Laranjeiro } 235