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 #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 { 44dbeba4cfSThomas Monjalon struct mlx5_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) { 53c388a2f6SNelio Laranjeiro if (rss_conf->rss_key_len != MLX5_RSS_HASH_KEY_LEN) { 54a1572312SShahaf Shuler DRV_LOG(ERR, 55c388a2f6SNelio Laranjeiro "port %u RSS key len must be %s Bytes long", 56c388a2f6SNelio Laranjeiro dev->data->port_id, 57c388a2f6SNelio Laranjeiro RTE_STR(MLX5_RSS_HASH_KEY_LEN)); 58a1572312SShahaf Shuler rte_errno = EINVAL; 59a1572312SShahaf Shuler return -rte_errno; 60a1572312SShahaf Shuler } 6129c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key, 6229c1d8bbSNélio Laranjeiro rss_conf->rss_key_len, 0); 6329c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 64a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 65a6d83b6aSNélio Laranjeiro return -rte_errno; 6629c1d8bbSNélio Laranjeiro } 67920b4e54SNélio Laranjeiro memcpy(priv->rss_conf.rss_key, rss_conf->rss_key, 6829c1d8bbSNélio Laranjeiro rss_conf->rss_key_len); 6929c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len = rss_conf->rss_key_len; 7029c1d8bbSNélio Laranjeiro } 7129c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = rss_conf->rss_hf; 7266669155SDahir Osman /* Enable the RSS hash in all Rx queues. */ 7366669155SDahir Osman for (i = 0, idx = 0; idx != priv->rxqs_n; ++i) { 7466669155SDahir Osman if (!(*priv->rxqs)[i]) 7566669155SDahir Osman continue; 7666669155SDahir Osman (*priv->rxqs)[i]->rss_hash = !!rss_conf->rss_hf && 7766669155SDahir Osman !!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS); 7866669155SDahir Osman ++idx; 7966669155SDahir Osman } 80a6d83b6aSNélio Laranjeiro return 0; 812f97422eSNelio Laranjeiro } 822f97422eSNelio Laranjeiro 832f97422eSNelio Laranjeiro /** 842f97422eSNelio Laranjeiro * DPDK callback to get the RSS hash configuration. 852f97422eSNelio Laranjeiro * 862f97422eSNelio Laranjeiro * @param dev 872f97422eSNelio Laranjeiro * Pointer to Ethernet device structure. 882f97422eSNelio Laranjeiro * @param[in, out] rss_conf 892f97422eSNelio Laranjeiro * RSS configuration data. 902f97422eSNelio Laranjeiro * 912f97422eSNelio Laranjeiro * @return 92a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 932f97422eSNelio Laranjeiro */ 942f97422eSNelio Laranjeiro int 952f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev, 962f97422eSNelio Laranjeiro struct rte_eth_rss_conf *rss_conf) 972f97422eSNelio Laranjeiro { 98dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 992f97422eSNelio Laranjeiro 100a6d83b6aSNélio Laranjeiro if (!rss_conf) { 101a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 102a6d83b6aSNélio Laranjeiro return -rte_errno; 103a6d83b6aSNélio Laranjeiro } 104920b4e54SNélio Laranjeiro if (rss_conf->rss_key && 105920b4e54SNélio Laranjeiro (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) { 10629c1d8bbSNélio Laranjeiro memcpy(rss_conf->rss_key, priv->rss_conf.rss_key, 10729c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len); 108920b4e54SNélio Laranjeiro } 109920b4e54SNélio Laranjeiro rss_conf->rss_key_len = priv->rss_conf.rss_key_len; 110920b4e54SNélio Laranjeiro rss_conf->rss_hf = priv->rss_conf.rss_hf; 111920b4e54SNélio Laranjeiro return 0; 1122f97422eSNelio Laranjeiro } 113634efbc2SNelio Laranjeiro 114634efbc2SNelio Laranjeiro /** 115634efbc2SNelio Laranjeiro * Allocate/reallocate RETA index table. 116634efbc2SNelio Laranjeiro * 117af4f09f2SNélio Laranjeiro * @param dev 118af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 119634efbc2SNelio Laranjeiro * @praram reta_size 120634efbc2SNelio Laranjeiro * The size of the array to allocate. 121634efbc2SNelio Laranjeiro * 122634efbc2SNelio Laranjeiro * @return 123a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 124634efbc2SNelio Laranjeiro */ 125634efbc2SNelio Laranjeiro int 126af4f09f2SNélio Laranjeiro mlx5_rss_reta_index_resize(struct rte_eth_dev *dev, unsigned int reta_size) 127634efbc2SNelio Laranjeiro { 128dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 129634efbc2SNelio Laranjeiro void *mem; 130634efbc2SNelio Laranjeiro unsigned int old_size = priv->reta_idx_n; 131634efbc2SNelio Laranjeiro 132634efbc2SNelio Laranjeiro if (priv->reta_idx_n == reta_size) 133634efbc2SNelio Laranjeiro return 0; 134634efbc2SNelio Laranjeiro 135634efbc2SNelio Laranjeiro mem = rte_realloc(priv->reta_idx, 136634efbc2SNelio Laranjeiro reta_size * sizeof((*priv->reta_idx)[0]), 0); 137a6d83b6aSNélio Laranjeiro if (!mem) { 138a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 139a6d83b6aSNélio Laranjeiro return -rte_errno; 140a6d83b6aSNélio Laranjeiro } 141634efbc2SNelio Laranjeiro priv->reta_idx = mem; 142634efbc2SNelio Laranjeiro priv->reta_idx_n = reta_size; 143634efbc2SNelio Laranjeiro if (old_size < reta_size) 144634efbc2SNelio Laranjeiro memset(&(*priv->reta_idx)[old_size], 0, 145634efbc2SNelio Laranjeiro (reta_size - old_size) * 146634efbc2SNelio Laranjeiro sizeof((*priv->reta_idx)[0])); 147634efbc2SNelio Laranjeiro return 0; 148634efbc2SNelio Laranjeiro } 149634efbc2SNelio Laranjeiro 150634efbc2SNelio Laranjeiro /** 151634efbc2SNelio Laranjeiro * DPDK callback to get the RETA indirection table. 152634efbc2SNelio Laranjeiro * 153634efbc2SNelio Laranjeiro * @param dev 154634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 155634efbc2SNelio Laranjeiro * @param reta_conf 156634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 157634efbc2SNelio Laranjeiro * @param reta_size 158634efbc2SNelio Laranjeiro * Size of the RETA table. 159634efbc2SNelio Laranjeiro * 160634efbc2SNelio Laranjeiro * @return 161a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 162634efbc2SNelio Laranjeiro */ 163634efbc2SNelio Laranjeiro int 164634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev, 165634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 166634efbc2SNelio Laranjeiro uint16_t reta_size) 167634efbc2SNelio Laranjeiro { 168dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 169af4f09f2SNélio Laranjeiro unsigned int idx; 170af4f09f2SNélio Laranjeiro unsigned int i; 171634efbc2SNelio Laranjeiro 172a6d83b6aSNélio Laranjeiro if (!reta_size || reta_size > priv->reta_idx_n) { 173a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 174a6d83b6aSNélio Laranjeiro return -rte_errno; 175a6d83b6aSNélio Laranjeiro } 176af4f09f2SNélio Laranjeiro /* Fill each entry of the table even if its bit is not set. */ 177af4f09f2SNélio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 178af4f09f2SNélio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 179af4f09f2SNélio Laranjeiro reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] = 180af4f09f2SNélio Laranjeiro (*priv->reta_idx)[i]; 181af4f09f2SNélio Laranjeiro } 182af4f09f2SNélio Laranjeiro return 0; 183634efbc2SNelio Laranjeiro } 184634efbc2SNelio Laranjeiro 185634efbc2SNelio Laranjeiro /** 186634efbc2SNelio Laranjeiro * DPDK callback to update the RETA indirection table. 187634efbc2SNelio Laranjeiro * 188634efbc2SNelio Laranjeiro * @param dev 189634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 190634efbc2SNelio Laranjeiro * @param reta_conf 191634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 192634efbc2SNelio Laranjeiro * @param reta_size 193634efbc2SNelio Laranjeiro * Size of the RETA table. 194634efbc2SNelio Laranjeiro * 195634efbc2SNelio Laranjeiro * @return 196a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 197634efbc2SNelio Laranjeiro */ 198634efbc2SNelio Laranjeiro int 199634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev, 200634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 201634efbc2SNelio Laranjeiro uint16_t reta_size) 202634efbc2SNelio Laranjeiro { 203634efbc2SNelio Laranjeiro int ret; 204dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 205af4f09f2SNélio Laranjeiro unsigned int idx; 206af4f09f2SNélio Laranjeiro unsigned int i; 207af4f09f2SNélio Laranjeiro unsigned int pos; 208634efbc2SNelio Laranjeiro 209a6d83b6aSNélio Laranjeiro if (!reta_size) { 210a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 211a6d83b6aSNélio Laranjeiro return -rte_errno; 212a6d83b6aSNélio Laranjeiro } 213af4f09f2SNélio Laranjeiro ret = mlx5_rss_reta_index_resize(dev, reta_size); 214af4f09f2SNélio Laranjeiro if (ret) 215af4f09f2SNélio Laranjeiro return ret; 216af4f09f2SNélio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 217af4f09f2SNélio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 218af4f09f2SNélio Laranjeiro pos = i % RTE_RETA_GROUP_SIZE; 219af4f09f2SNélio Laranjeiro if (((reta_conf[idx].mask >> i) & 0x1) == 0) 220af4f09f2SNélio Laranjeiro continue; 221af4f09f2SNélio Laranjeiro assert(reta_conf[idx].reta[pos] < priv->rxqs_n); 222af4f09f2SNélio Laranjeiro (*priv->reta_idx)[i] = reta_conf[idx].reta[pos]; 223af4f09f2SNélio Laranjeiro } 2243f2fe392SNélio Laranjeiro if (dev->data->dev_started) { 2253f2fe392SNélio Laranjeiro mlx5_dev_stop(dev); 226*63bd1629SOri Kam priv->skip_default_rss_reta = 1; 227a6d83b6aSNélio Laranjeiro return mlx5_dev_start(dev); 2283f2fe392SNélio Laranjeiro } 229a6d83b6aSNélio Laranjeiro return 0; 230634efbc2SNelio Laranjeiro } 231