18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 22f97422eSNelio Laranjeiro * Copyright 2015 6WIND S.A. 32f97422eSNelio Laranjeiro * Copyright 2015 Mellanox. 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 38*a6d83b6aSNé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; 452f97422eSNelio Laranjeiro 46b365799bSNélio Laranjeiro if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) { 47*a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 48*a6d83b6aSNélio Laranjeiro return -rte_errno; 49b365799bSNélio Laranjeiro } 50920b4e54SNélio Laranjeiro if (rss_conf->rss_key && rss_conf->rss_key_len) { 5129c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key, 5229c1d8bbSNélio Laranjeiro rss_conf->rss_key_len, 0); 5329c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 54*a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 55*a6d83b6aSNélio Laranjeiro return -rte_errno; 5629c1d8bbSNélio Laranjeiro } 57920b4e54SNélio Laranjeiro memcpy(priv->rss_conf.rss_key, rss_conf->rss_key, 5829c1d8bbSNélio Laranjeiro rss_conf->rss_key_len); 5929c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len = rss_conf->rss_key_len; 6029c1d8bbSNélio Laranjeiro } 6129c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = rss_conf->rss_hf; 62*a6d83b6aSNélio Laranjeiro return 0; 632f97422eSNelio Laranjeiro } 642f97422eSNelio Laranjeiro 652f97422eSNelio Laranjeiro /** 662f97422eSNelio Laranjeiro * DPDK callback to get the RSS hash configuration. 672f97422eSNelio Laranjeiro * 682f97422eSNelio Laranjeiro * @param dev 692f97422eSNelio Laranjeiro * Pointer to Ethernet device structure. 702f97422eSNelio Laranjeiro * @param[in, out] rss_conf 712f97422eSNelio Laranjeiro * RSS configuration data. 722f97422eSNelio Laranjeiro * 732f97422eSNelio Laranjeiro * @return 74*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 752f97422eSNelio Laranjeiro */ 762f97422eSNelio Laranjeiro int 772f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev, 782f97422eSNelio Laranjeiro struct rte_eth_rss_conf *rss_conf) 792f97422eSNelio Laranjeiro { 802f97422eSNelio Laranjeiro struct priv *priv = dev->data->dev_private; 812f97422eSNelio Laranjeiro 82*a6d83b6aSNélio Laranjeiro if (!rss_conf) { 83*a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 84*a6d83b6aSNélio Laranjeiro return -rte_errno; 85*a6d83b6aSNélio Laranjeiro } 86920b4e54SNélio Laranjeiro if (rss_conf->rss_key && 87920b4e54SNélio Laranjeiro (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) { 8829c1d8bbSNélio Laranjeiro memcpy(rss_conf->rss_key, priv->rss_conf.rss_key, 8929c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len); 90920b4e54SNélio Laranjeiro } 91920b4e54SNélio Laranjeiro rss_conf->rss_key_len = priv->rss_conf.rss_key_len; 92920b4e54SNélio Laranjeiro rss_conf->rss_hf = priv->rss_conf.rss_hf; 93920b4e54SNélio Laranjeiro return 0; 942f97422eSNelio Laranjeiro } 95634efbc2SNelio Laranjeiro 96634efbc2SNelio Laranjeiro /** 97634efbc2SNelio Laranjeiro * Allocate/reallocate RETA index table. 98634efbc2SNelio Laranjeiro * 99af4f09f2SNélio Laranjeiro * @param dev 100af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 101634efbc2SNelio Laranjeiro * @praram reta_size 102634efbc2SNelio Laranjeiro * The size of the array to allocate. 103634efbc2SNelio Laranjeiro * 104634efbc2SNelio Laranjeiro * @return 105*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 106634efbc2SNelio Laranjeiro */ 107634efbc2SNelio Laranjeiro int 108af4f09f2SNélio Laranjeiro mlx5_rss_reta_index_resize(struct rte_eth_dev *dev, unsigned int reta_size) 109634efbc2SNelio Laranjeiro { 110af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 111634efbc2SNelio Laranjeiro void *mem; 112634efbc2SNelio Laranjeiro unsigned int old_size = priv->reta_idx_n; 113634efbc2SNelio Laranjeiro 114634efbc2SNelio Laranjeiro if (priv->reta_idx_n == reta_size) 115634efbc2SNelio Laranjeiro return 0; 116634efbc2SNelio Laranjeiro 117634efbc2SNelio Laranjeiro mem = rte_realloc(priv->reta_idx, 118634efbc2SNelio Laranjeiro reta_size * sizeof((*priv->reta_idx)[0]), 0); 119*a6d83b6aSNélio Laranjeiro if (!mem) { 120*a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 121*a6d83b6aSNélio Laranjeiro return -rte_errno; 122*a6d83b6aSNélio Laranjeiro } 123634efbc2SNelio Laranjeiro priv->reta_idx = mem; 124634efbc2SNelio Laranjeiro priv->reta_idx_n = reta_size; 125634efbc2SNelio Laranjeiro if (old_size < reta_size) 126634efbc2SNelio Laranjeiro memset(&(*priv->reta_idx)[old_size], 0, 127634efbc2SNelio Laranjeiro (reta_size - old_size) * 128634efbc2SNelio Laranjeiro sizeof((*priv->reta_idx)[0])); 129634efbc2SNelio Laranjeiro return 0; 130634efbc2SNelio Laranjeiro } 131634efbc2SNelio Laranjeiro 132634efbc2SNelio Laranjeiro /** 133634efbc2SNelio Laranjeiro * DPDK callback to get the RETA indirection table. 134634efbc2SNelio Laranjeiro * 135634efbc2SNelio Laranjeiro * @param dev 136634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 137634efbc2SNelio Laranjeiro * @param reta_conf 138634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 139634efbc2SNelio Laranjeiro * @param reta_size 140634efbc2SNelio Laranjeiro * Size of the RETA table. 141634efbc2SNelio Laranjeiro * 142634efbc2SNelio Laranjeiro * @return 143*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 144634efbc2SNelio Laranjeiro */ 145634efbc2SNelio Laranjeiro int 146634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev, 147634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 148634efbc2SNelio Laranjeiro uint16_t reta_size) 149634efbc2SNelio Laranjeiro { 150634efbc2SNelio Laranjeiro struct priv *priv = dev->data->dev_private; 151af4f09f2SNélio Laranjeiro unsigned int idx; 152af4f09f2SNélio Laranjeiro unsigned int i; 153634efbc2SNelio Laranjeiro 154*a6d83b6aSNélio Laranjeiro if (!reta_size || reta_size > priv->reta_idx_n) { 155*a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 156*a6d83b6aSNélio Laranjeiro return -rte_errno; 157*a6d83b6aSNélio Laranjeiro } 158af4f09f2SNélio Laranjeiro /* Fill each entry of the table even if its bit is not set. */ 159af4f09f2SNélio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 160af4f09f2SNélio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 161af4f09f2SNélio Laranjeiro reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] = 162af4f09f2SNélio Laranjeiro (*priv->reta_idx)[i]; 163af4f09f2SNélio Laranjeiro } 164af4f09f2SNélio Laranjeiro return 0; 165634efbc2SNelio Laranjeiro } 166634efbc2SNelio Laranjeiro 167634efbc2SNelio Laranjeiro /** 168634efbc2SNelio Laranjeiro * DPDK callback to update the RETA indirection table. 169634efbc2SNelio Laranjeiro * 170634efbc2SNelio Laranjeiro * @param dev 171634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 172634efbc2SNelio Laranjeiro * @param reta_conf 173634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 174634efbc2SNelio Laranjeiro * @param reta_size 175634efbc2SNelio Laranjeiro * Size of the RETA table. 176634efbc2SNelio Laranjeiro * 177634efbc2SNelio Laranjeiro * @return 178*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 179634efbc2SNelio Laranjeiro */ 180634efbc2SNelio Laranjeiro int 181634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev, 182634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 183634efbc2SNelio Laranjeiro uint16_t reta_size) 184634efbc2SNelio Laranjeiro { 185634efbc2SNelio Laranjeiro int ret; 186634efbc2SNelio Laranjeiro struct priv *priv = dev->data->dev_private; 187af4f09f2SNélio Laranjeiro unsigned int idx; 188af4f09f2SNélio Laranjeiro unsigned int i; 189af4f09f2SNélio Laranjeiro unsigned int pos; 190634efbc2SNelio Laranjeiro 191*a6d83b6aSNélio Laranjeiro if (!reta_size) { 192*a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 193*a6d83b6aSNélio Laranjeiro return -rte_errno; 194*a6d83b6aSNélio Laranjeiro } 195af4f09f2SNélio Laranjeiro ret = mlx5_rss_reta_index_resize(dev, reta_size); 196af4f09f2SNélio Laranjeiro if (ret) 197af4f09f2SNélio Laranjeiro return ret; 198af4f09f2SNélio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 199af4f09f2SNélio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 200af4f09f2SNélio Laranjeiro pos = i % RTE_RETA_GROUP_SIZE; 201af4f09f2SNélio Laranjeiro if (((reta_conf[idx].mask >> i) & 0x1) == 0) 202af4f09f2SNélio Laranjeiro continue; 203af4f09f2SNélio Laranjeiro assert(reta_conf[idx].reta[pos] < priv->rxqs_n); 204af4f09f2SNélio Laranjeiro (*priv->reta_idx)[i] = reta_conf[idx].reta[pos]; 205af4f09f2SNélio Laranjeiro } 2063f2fe392SNélio Laranjeiro if (dev->data->dev_started) { 2073f2fe392SNélio Laranjeiro mlx5_dev_stop(dev); 208*a6d83b6aSNélio Laranjeiro return mlx5_dev_start(dev); 2093f2fe392SNélio Laranjeiro } 210*a6d83b6aSNélio Laranjeiro return 0; 211634efbc2SNelio Laranjeiro } 212