1*8fd92a66SOlivier 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 382f97422eSNelio Laranjeiro * 0 on success, negative errno value on failure. 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; 4529c1d8bbSNélio Laranjeiro int ret = 0; 462f97422eSNelio Laranjeiro 472f97422eSNelio Laranjeiro priv_lock(priv); 48b365799bSNélio Laranjeiro if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) { 49b365799bSNélio Laranjeiro ret = -EINVAL; 50b365799bSNélio Laranjeiro goto out; 51b365799bSNélio Laranjeiro } 52920b4e54SNélio Laranjeiro if (rss_conf->rss_key && rss_conf->rss_key_len) { 5329c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key, 5429c1d8bbSNélio Laranjeiro rss_conf->rss_key_len, 0); 5529c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 5629c1d8bbSNélio Laranjeiro ret = -ENOMEM; 5729c1d8bbSNélio Laranjeiro goto out; 5829c1d8bbSNélio Laranjeiro } 59920b4e54SNélio Laranjeiro memcpy(priv->rss_conf.rss_key, rss_conf->rss_key, 6029c1d8bbSNélio Laranjeiro rss_conf->rss_key_len); 6129c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len = rss_conf->rss_key_len; 6229c1d8bbSNélio Laranjeiro } 6329c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = rss_conf->rss_hf; 6429c1d8bbSNélio Laranjeiro out: 652f97422eSNelio Laranjeiro priv_unlock(priv); 6629c1d8bbSNélio Laranjeiro return ret; 672f97422eSNelio Laranjeiro } 682f97422eSNelio Laranjeiro 692f97422eSNelio Laranjeiro /** 702f97422eSNelio Laranjeiro * DPDK callback to get the RSS hash configuration. 712f97422eSNelio Laranjeiro * 722f97422eSNelio Laranjeiro * @param dev 732f97422eSNelio Laranjeiro * Pointer to Ethernet device structure. 742f97422eSNelio Laranjeiro * @param[in, out] rss_conf 752f97422eSNelio Laranjeiro * RSS configuration data. 762f97422eSNelio Laranjeiro * 772f97422eSNelio Laranjeiro * @return 782f97422eSNelio Laranjeiro * 0 on success, negative errno value on failure. 792f97422eSNelio Laranjeiro */ 802f97422eSNelio Laranjeiro int 812f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev, 822f97422eSNelio Laranjeiro struct rte_eth_rss_conf *rss_conf) 832f97422eSNelio Laranjeiro { 842f97422eSNelio Laranjeiro struct priv *priv = dev->data->dev_private; 852f97422eSNelio Laranjeiro 86920b4e54SNélio Laranjeiro if (!rss_conf) 87920b4e54SNélio Laranjeiro return -EINVAL; 882f97422eSNelio Laranjeiro priv_lock(priv); 89920b4e54SNélio Laranjeiro if (rss_conf->rss_key && 90920b4e54SNélio Laranjeiro (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) { 9129c1d8bbSNélio Laranjeiro memcpy(rss_conf->rss_key, priv->rss_conf.rss_key, 9229c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len); 93920b4e54SNélio Laranjeiro } 94920b4e54SNélio Laranjeiro rss_conf->rss_key_len = priv->rss_conf.rss_key_len; 95920b4e54SNélio Laranjeiro rss_conf->rss_hf = priv->rss_conf.rss_hf; 962f97422eSNelio Laranjeiro priv_unlock(priv); 97920b4e54SNélio Laranjeiro return 0; 982f97422eSNelio Laranjeiro } 99634efbc2SNelio Laranjeiro 100634efbc2SNelio Laranjeiro /** 101634efbc2SNelio Laranjeiro * Allocate/reallocate RETA index table. 102634efbc2SNelio Laranjeiro * 103634efbc2SNelio Laranjeiro * @param priv 104634efbc2SNelio Laranjeiro * Pointer to private structure. 105634efbc2SNelio Laranjeiro * @praram reta_size 106634efbc2SNelio Laranjeiro * The size of the array to allocate. 107634efbc2SNelio Laranjeiro * 108634efbc2SNelio Laranjeiro * @return 109634efbc2SNelio Laranjeiro * 0 on success, errno value on failure. 110634efbc2SNelio Laranjeiro */ 111634efbc2SNelio Laranjeiro int 112634efbc2SNelio Laranjeiro priv_rss_reta_index_resize(struct priv *priv, unsigned int reta_size) 113634efbc2SNelio Laranjeiro { 114634efbc2SNelio Laranjeiro void *mem; 115634efbc2SNelio Laranjeiro unsigned int old_size = priv->reta_idx_n; 116634efbc2SNelio Laranjeiro 117634efbc2SNelio Laranjeiro if (priv->reta_idx_n == reta_size) 118634efbc2SNelio Laranjeiro return 0; 119634efbc2SNelio Laranjeiro 120634efbc2SNelio Laranjeiro mem = rte_realloc(priv->reta_idx, 121634efbc2SNelio Laranjeiro reta_size * sizeof((*priv->reta_idx)[0]), 0); 122634efbc2SNelio Laranjeiro if (!mem) 123634efbc2SNelio Laranjeiro return ENOMEM; 124634efbc2SNelio Laranjeiro priv->reta_idx = mem; 125634efbc2SNelio Laranjeiro priv->reta_idx_n = reta_size; 126634efbc2SNelio Laranjeiro 127634efbc2SNelio Laranjeiro if (old_size < reta_size) 128634efbc2SNelio Laranjeiro memset(&(*priv->reta_idx)[old_size], 0, 129634efbc2SNelio Laranjeiro (reta_size - old_size) * 130634efbc2SNelio Laranjeiro sizeof((*priv->reta_idx)[0])); 131634efbc2SNelio Laranjeiro return 0; 132634efbc2SNelio Laranjeiro } 133634efbc2SNelio Laranjeiro 134634efbc2SNelio Laranjeiro /** 135634efbc2SNelio Laranjeiro * Query RETA table. 136634efbc2SNelio Laranjeiro * 137634efbc2SNelio Laranjeiro * @param priv 138634efbc2SNelio Laranjeiro * Pointer to private structure. 139634efbc2SNelio Laranjeiro * @param[in, out] reta_conf 140634efbc2SNelio Laranjeiro * Pointer to the first RETA configuration structure. 141634efbc2SNelio Laranjeiro * @param reta_size 142634efbc2SNelio Laranjeiro * Number of entries. 143634efbc2SNelio Laranjeiro * 144634efbc2SNelio Laranjeiro * @return 145634efbc2SNelio Laranjeiro * 0 on success, errno value on failure. 146634efbc2SNelio Laranjeiro */ 147634efbc2SNelio Laranjeiro static int 148634efbc2SNelio Laranjeiro priv_dev_rss_reta_query(struct priv *priv, 149634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 150634efbc2SNelio Laranjeiro unsigned int reta_size) 151634efbc2SNelio Laranjeiro { 152634efbc2SNelio Laranjeiro unsigned int idx; 153634efbc2SNelio Laranjeiro unsigned int i; 154634efbc2SNelio Laranjeiro 155d365210eSYongseok Koh if (!reta_size || reta_size > priv->reta_idx_n) 156d365210eSYongseok Koh return EINVAL; 157634efbc2SNelio Laranjeiro /* Fill each entry of the table even if its bit is not set. */ 158634efbc2SNelio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 159634efbc2SNelio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 160634efbc2SNelio Laranjeiro reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] = 161634efbc2SNelio Laranjeiro (*priv->reta_idx)[i]; 162634efbc2SNelio Laranjeiro } 163634efbc2SNelio Laranjeiro return 0; 164634efbc2SNelio Laranjeiro } 165634efbc2SNelio Laranjeiro 166634efbc2SNelio Laranjeiro /** 167634efbc2SNelio Laranjeiro * Update RETA table. 168634efbc2SNelio Laranjeiro * 169634efbc2SNelio Laranjeiro * @param priv 170634efbc2SNelio Laranjeiro * Pointer to private structure. 171634efbc2SNelio Laranjeiro * @param[in] reta_conf 172634efbc2SNelio Laranjeiro * Pointer to the first RETA configuration structure. 173634efbc2SNelio Laranjeiro * @param reta_size 174634efbc2SNelio Laranjeiro * Number of entries. 175634efbc2SNelio Laranjeiro * 176634efbc2SNelio Laranjeiro * @return 177634efbc2SNelio Laranjeiro * 0 on success, errno value on failure. 178634efbc2SNelio Laranjeiro */ 179634efbc2SNelio Laranjeiro static int 180634efbc2SNelio Laranjeiro priv_dev_rss_reta_update(struct priv *priv, 181634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 182634efbc2SNelio Laranjeiro unsigned int reta_size) 183634efbc2SNelio Laranjeiro { 184634efbc2SNelio Laranjeiro unsigned int idx; 185634efbc2SNelio Laranjeiro unsigned int i; 186634efbc2SNelio Laranjeiro unsigned int pos; 187634efbc2SNelio Laranjeiro int ret; 188634efbc2SNelio Laranjeiro 189d365210eSYongseok Koh if (!reta_size) 190d365210eSYongseok Koh return EINVAL; 191d365210eSYongseok Koh ret = priv_rss_reta_index_resize(priv, reta_size); 192634efbc2SNelio Laranjeiro if (ret) 193634efbc2SNelio Laranjeiro return ret; 194634efbc2SNelio Laranjeiro 195634efbc2SNelio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 196634efbc2SNelio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 197634efbc2SNelio Laranjeiro pos = i % RTE_RETA_GROUP_SIZE; 198634efbc2SNelio Laranjeiro if (((reta_conf[idx].mask >> i) & 0x1) == 0) 199634efbc2SNelio Laranjeiro continue; 200634efbc2SNelio Laranjeiro assert(reta_conf[idx].reta[pos] < priv->rxqs_n); 201634efbc2SNelio Laranjeiro (*priv->reta_idx)[i] = reta_conf[idx].reta[pos]; 202634efbc2SNelio Laranjeiro } 203634efbc2SNelio Laranjeiro return 0; 204634efbc2SNelio Laranjeiro } 205634efbc2SNelio Laranjeiro 206634efbc2SNelio Laranjeiro /** 207634efbc2SNelio Laranjeiro * DPDK callback to get the RETA indirection table. 208634efbc2SNelio Laranjeiro * 209634efbc2SNelio Laranjeiro * @param dev 210634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 211634efbc2SNelio Laranjeiro * @param reta_conf 212634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 213634efbc2SNelio Laranjeiro * @param reta_size 214634efbc2SNelio Laranjeiro * Size of the RETA table. 215634efbc2SNelio Laranjeiro * 216634efbc2SNelio Laranjeiro * @return 217634efbc2SNelio Laranjeiro * 0 on success, negative errno value on failure. 218634efbc2SNelio Laranjeiro */ 219634efbc2SNelio Laranjeiro int 220634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev, 221634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 222634efbc2SNelio Laranjeiro uint16_t reta_size) 223634efbc2SNelio Laranjeiro { 224634efbc2SNelio Laranjeiro int ret; 225634efbc2SNelio Laranjeiro struct priv *priv = dev->data->dev_private; 226634efbc2SNelio Laranjeiro 227634efbc2SNelio Laranjeiro priv_lock(priv); 228634efbc2SNelio Laranjeiro ret = priv_dev_rss_reta_query(priv, reta_conf, reta_size); 229634efbc2SNelio Laranjeiro priv_unlock(priv); 230634efbc2SNelio Laranjeiro return -ret; 231634efbc2SNelio Laranjeiro } 232634efbc2SNelio Laranjeiro 233634efbc2SNelio Laranjeiro /** 234634efbc2SNelio Laranjeiro * DPDK callback to update the RETA indirection table. 235634efbc2SNelio Laranjeiro * 236634efbc2SNelio Laranjeiro * @param dev 237634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 238634efbc2SNelio Laranjeiro * @param reta_conf 239634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 240634efbc2SNelio Laranjeiro * @param reta_size 241634efbc2SNelio Laranjeiro * Size of the RETA table. 242634efbc2SNelio Laranjeiro * 243634efbc2SNelio Laranjeiro * @return 244634efbc2SNelio Laranjeiro * 0 on success, negative errno value on failure. 245634efbc2SNelio Laranjeiro */ 246634efbc2SNelio Laranjeiro int 247634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev, 248634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 249634efbc2SNelio Laranjeiro uint16_t reta_size) 250634efbc2SNelio Laranjeiro { 251634efbc2SNelio Laranjeiro int ret; 252634efbc2SNelio Laranjeiro struct priv *priv = dev->data->dev_private; 253634efbc2SNelio Laranjeiro 254634efbc2SNelio Laranjeiro priv_lock(priv); 255634efbc2SNelio Laranjeiro ret = priv_dev_rss_reta_update(priv, reta_conf, reta_size); 256634efbc2SNelio Laranjeiro priv_unlock(priv); 2573f2fe392SNélio Laranjeiro if (dev->data->dev_started) { 2583f2fe392SNélio Laranjeiro mlx5_dev_stop(dev); 2593f2fe392SNélio Laranjeiro mlx5_dev_start(dev); 2603f2fe392SNélio Laranjeiro } 261634efbc2SNelio Laranjeiro return -ret; 262634efbc2SNelio Laranjeiro } 263