18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 22f97422eSNelio Laranjeiro * Copyright 2015 6WIND S.A. 3*5feecc57SShahaf 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 { 442f97422eSNelio Laranjeiro struct 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) { 53a1572312SShahaf Shuler if (rss_conf->rss_key_len != rss_hash_default_key_len) { 54a1572312SShahaf Shuler DRV_LOG(ERR, 55a1572312SShahaf Shuler "port %u RSS key len must be %zu Bytes long", 56a1572312SShahaf Shuler dev->data->port_id, rss_hash_default_key_len); 57a1572312SShahaf Shuler rte_errno = EINVAL; 58a1572312SShahaf Shuler return -rte_errno; 59a1572312SShahaf Shuler } 6029c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key, 6129c1d8bbSNélio Laranjeiro rss_conf->rss_key_len, 0); 6229c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 63a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 64a6d83b6aSNélio Laranjeiro return -rte_errno; 6529c1d8bbSNélio Laranjeiro } 66920b4e54SNélio Laranjeiro memcpy(priv->rss_conf.rss_key, rss_conf->rss_key, 6729c1d8bbSNélio Laranjeiro rss_conf->rss_key_len); 6829c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len = rss_conf->rss_key_len; 6929c1d8bbSNélio Laranjeiro } 7029c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = rss_conf->rss_hf; 7166669155SDahir Osman /* Enable the RSS hash in all Rx queues. */ 7266669155SDahir Osman for (i = 0, idx = 0; idx != priv->rxqs_n; ++i) { 7366669155SDahir Osman if (!(*priv->rxqs)[i]) 7466669155SDahir Osman continue; 7566669155SDahir Osman (*priv->rxqs)[i]->rss_hash = !!rss_conf->rss_hf && 7666669155SDahir Osman !!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS); 7766669155SDahir Osman ++idx; 7866669155SDahir Osman } 79a6d83b6aSNélio Laranjeiro return 0; 802f97422eSNelio Laranjeiro } 812f97422eSNelio Laranjeiro 822f97422eSNelio Laranjeiro /** 832f97422eSNelio Laranjeiro * DPDK callback to get the RSS hash configuration. 842f97422eSNelio Laranjeiro * 852f97422eSNelio Laranjeiro * @param dev 862f97422eSNelio Laranjeiro * Pointer to Ethernet device structure. 872f97422eSNelio Laranjeiro * @param[in, out] rss_conf 882f97422eSNelio Laranjeiro * RSS configuration data. 892f97422eSNelio Laranjeiro * 902f97422eSNelio Laranjeiro * @return 91a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 922f97422eSNelio Laranjeiro */ 932f97422eSNelio Laranjeiro int 942f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev, 952f97422eSNelio Laranjeiro struct rte_eth_rss_conf *rss_conf) 962f97422eSNelio Laranjeiro { 972f97422eSNelio Laranjeiro struct priv *priv = dev->data->dev_private; 982f97422eSNelio Laranjeiro 99a6d83b6aSNélio Laranjeiro if (!rss_conf) { 100a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 101a6d83b6aSNélio Laranjeiro return -rte_errno; 102a6d83b6aSNélio Laranjeiro } 103920b4e54SNélio Laranjeiro if (rss_conf->rss_key && 104920b4e54SNélio Laranjeiro (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) { 10529c1d8bbSNélio Laranjeiro memcpy(rss_conf->rss_key, priv->rss_conf.rss_key, 10629c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len); 107920b4e54SNélio Laranjeiro } 108920b4e54SNélio Laranjeiro rss_conf->rss_key_len = priv->rss_conf.rss_key_len; 109920b4e54SNélio Laranjeiro rss_conf->rss_hf = priv->rss_conf.rss_hf; 110920b4e54SNélio Laranjeiro return 0; 1112f97422eSNelio Laranjeiro } 112634efbc2SNelio Laranjeiro 113634efbc2SNelio Laranjeiro /** 114634efbc2SNelio Laranjeiro * Allocate/reallocate RETA index table. 115634efbc2SNelio Laranjeiro * 116af4f09f2SNélio Laranjeiro * @param dev 117af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 118634efbc2SNelio Laranjeiro * @praram reta_size 119634efbc2SNelio Laranjeiro * The size of the array to allocate. 120634efbc2SNelio Laranjeiro * 121634efbc2SNelio Laranjeiro * @return 122a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 123634efbc2SNelio Laranjeiro */ 124634efbc2SNelio Laranjeiro int 125af4f09f2SNélio Laranjeiro mlx5_rss_reta_index_resize(struct rte_eth_dev *dev, unsigned int reta_size) 126634efbc2SNelio Laranjeiro { 127af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 128634efbc2SNelio Laranjeiro void *mem; 129634efbc2SNelio Laranjeiro unsigned int old_size = priv->reta_idx_n; 130634efbc2SNelio Laranjeiro 131634efbc2SNelio Laranjeiro if (priv->reta_idx_n == reta_size) 132634efbc2SNelio Laranjeiro return 0; 133634efbc2SNelio Laranjeiro 134634efbc2SNelio Laranjeiro mem = rte_realloc(priv->reta_idx, 135634efbc2SNelio Laranjeiro reta_size * sizeof((*priv->reta_idx)[0]), 0); 136a6d83b6aSNélio Laranjeiro if (!mem) { 137a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 138a6d83b6aSNélio Laranjeiro return -rte_errno; 139a6d83b6aSNélio Laranjeiro } 140634efbc2SNelio Laranjeiro priv->reta_idx = mem; 141634efbc2SNelio Laranjeiro priv->reta_idx_n = reta_size; 142634efbc2SNelio Laranjeiro if (old_size < reta_size) 143634efbc2SNelio Laranjeiro memset(&(*priv->reta_idx)[old_size], 0, 144634efbc2SNelio Laranjeiro (reta_size - old_size) * 145634efbc2SNelio Laranjeiro sizeof((*priv->reta_idx)[0])); 146634efbc2SNelio Laranjeiro return 0; 147634efbc2SNelio Laranjeiro } 148634efbc2SNelio Laranjeiro 149634efbc2SNelio Laranjeiro /** 150634efbc2SNelio Laranjeiro * DPDK callback to get the RETA indirection table. 151634efbc2SNelio Laranjeiro * 152634efbc2SNelio Laranjeiro * @param dev 153634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 154634efbc2SNelio Laranjeiro * @param reta_conf 155634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 156634efbc2SNelio Laranjeiro * @param reta_size 157634efbc2SNelio Laranjeiro * Size of the RETA table. 158634efbc2SNelio Laranjeiro * 159634efbc2SNelio Laranjeiro * @return 160a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 161634efbc2SNelio Laranjeiro */ 162634efbc2SNelio Laranjeiro int 163634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev, 164634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 165634efbc2SNelio Laranjeiro uint16_t reta_size) 166634efbc2SNelio Laranjeiro { 167634efbc2SNelio Laranjeiro struct priv *priv = dev->data->dev_private; 168af4f09f2SNélio Laranjeiro unsigned int idx; 169af4f09f2SNélio Laranjeiro unsigned int i; 170634efbc2SNelio Laranjeiro 171a6d83b6aSNélio Laranjeiro if (!reta_size || reta_size > priv->reta_idx_n) { 172a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 173a6d83b6aSNélio Laranjeiro return -rte_errno; 174a6d83b6aSNélio Laranjeiro } 175af4f09f2SNélio Laranjeiro /* Fill each entry of the table even if its bit is not set. */ 176af4f09f2SNélio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 177af4f09f2SNélio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 178af4f09f2SNélio Laranjeiro reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] = 179af4f09f2SNélio Laranjeiro (*priv->reta_idx)[i]; 180af4f09f2SNélio Laranjeiro } 181af4f09f2SNélio Laranjeiro return 0; 182634efbc2SNelio Laranjeiro } 183634efbc2SNelio Laranjeiro 184634efbc2SNelio Laranjeiro /** 185634efbc2SNelio Laranjeiro * DPDK callback to update the RETA indirection table. 186634efbc2SNelio Laranjeiro * 187634efbc2SNelio Laranjeiro * @param dev 188634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 189634efbc2SNelio Laranjeiro * @param reta_conf 190634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 191634efbc2SNelio Laranjeiro * @param reta_size 192634efbc2SNelio Laranjeiro * Size of the RETA table. 193634efbc2SNelio Laranjeiro * 194634efbc2SNelio Laranjeiro * @return 195a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 196634efbc2SNelio Laranjeiro */ 197634efbc2SNelio Laranjeiro int 198634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev, 199634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 200634efbc2SNelio Laranjeiro uint16_t reta_size) 201634efbc2SNelio Laranjeiro { 202634efbc2SNelio Laranjeiro int ret; 203634efbc2SNelio Laranjeiro struct priv *priv = dev->data->dev_private; 204af4f09f2SNélio Laranjeiro unsigned int idx; 205af4f09f2SNélio Laranjeiro unsigned int i; 206af4f09f2SNélio Laranjeiro unsigned int pos; 207634efbc2SNelio Laranjeiro 208a6d83b6aSNélio Laranjeiro if (!reta_size) { 209a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 210a6d83b6aSNélio Laranjeiro return -rte_errno; 211a6d83b6aSNélio Laranjeiro } 212af4f09f2SNélio Laranjeiro ret = mlx5_rss_reta_index_resize(dev, reta_size); 213af4f09f2SNélio Laranjeiro if (ret) 214af4f09f2SNélio Laranjeiro return ret; 215af4f09f2SNélio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 216af4f09f2SNélio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 217af4f09f2SNélio Laranjeiro pos = i % RTE_RETA_GROUP_SIZE; 218af4f09f2SNélio Laranjeiro if (((reta_conf[idx].mask >> i) & 0x1) == 0) 219af4f09f2SNélio Laranjeiro continue; 220af4f09f2SNélio Laranjeiro assert(reta_conf[idx].reta[pos] < priv->rxqs_n); 221af4f09f2SNélio Laranjeiro (*priv->reta_idx)[i] = reta_conf[idx].reta[pos]; 222af4f09f2SNélio Laranjeiro } 2233f2fe392SNélio Laranjeiro if (dev->data->dev_started) { 2243f2fe392SNélio Laranjeiro mlx5_dev_stop(dev); 225a6d83b6aSNélio Laranjeiro return mlx5_dev_start(dev); 2263f2fe392SNélio Laranjeiro } 227a6d83b6aSNélio Laranjeiro return 0; 228634efbc2SNelio Laranjeiro } 229