12f97422eSNelio Laranjeiro /*- 22f97422eSNelio Laranjeiro * BSD LICENSE 32f97422eSNelio Laranjeiro * 42f97422eSNelio Laranjeiro * Copyright 2015 6WIND S.A. 52f97422eSNelio Laranjeiro * Copyright 2015 Mellanox. 62f97422eSNelio Laranjeiro * 72f97422eSNelio Laranjeiro * Redistribution and use in source and binary forms, with or without 82f97422eSNelio Laranjeiro * modification, are permitted provided that the following conditions 92f97422eSNelio Laranjeiro * are met: 102f97422eSNelio Laranjeiro * 112f97422eSNelio Laranjeiro * * Redistributions of source code must retain the above copyright 122f97422eSNelio Laranjeiro * notice, this list of conditions and the following disclaimer. 132f97422eSNelio Laranjeiro * * Redistributions in binary form must reproduce the above copyright 142f97422eSNelio Laranjeiro * notice, this list of conditions and the following disclaimer in 152f97422eSNelio Laranjeiro * the documentation and/or other materials provided with the 162f97422eSNelio Laranjeiro * distribution. 172f97422eSNelio Laranjeiro * * Neither the name of 6WIND S.A. nor the names of its 182f97422eSNelio Laranjeiro * contributors may be used to endorse or promote products derived 192f97422eSNelio Laranjeiro * from this software without specific prior written permission. 202f97422eSNelio Laranjeiro * 212f97422eSNelio Laranjeiro * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 222f97422eSNelio Laranjeiro * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 232f97422eSNelio Laranjeiro * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 242f97422eSNelio Laranjeiro * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 252f97422eSNelio Laranjeiro * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 262f97422eSNelio Laranjeiro * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 272f97422eSNelio Laranjeiro * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 282f97422eSNelio Laranjeiro * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 292f97422eSNelio Laranjeiro * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 302f97422eSNelio Laranjeiro * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 312f97422eSNelio Laranjeiro * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 322f97422eSNelio Laranjeiro */ 332f97422eSNelio Laranjeiro 342f97422eSNelio Laranjeiro #include <stddef.h> 352f97422eSNelio Laranjeiro #include <stdint.h> 362f97422eSNelio Laranjeiro #include <errno.h> 372f97422eSNelio Laranjeiro #include <string.h> 382f97422eSNelio Laranjeiro #include <assert.h> 392f97422eSNelio Laranjeiro 402f97422eSNelio Laranjeiro /* Verbs header. */ 412f97422eSNelio Laranjeiro /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 422f97422eSNelio Laranjeiro #ifdef PEDANTIC 43fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic" 442f97422eSNelio Laranjeiro #endif 452f97422eSNelio Laranjeiro #include <infiniband/verbs.h> 462f97422eSNelio Laranjeiro #ifdef PEDANTIC 47fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic" 482f97422eSNelio Laranjeiro #endif 492f97422eSNelio Laranjeiro 502f97422eSNelio Laranjeiro #include <rte_malloc.h> 512f97422eSNelio Laranjeiro #include <rte_ethdev.h> 522f97422eSNelio Laranjeiro 532f97422eSNelio Laranjeiro #include "mlx5.h" 54*b365799bSNélio Laranjeiro #include "mlx5_defs.h" 552f97422eSNelio Laranjeiro #include "mlx5_rxtx.h" 562f97422eSNelio Laranjeiro 572f97422eSNelio Laranjeiro /** 582f97422eSNelio Laranjeiro * DPDK callback to update the RSS hash configuration. 592f97422eSNelio Laranjeiro * 602f97422eSNelio Laranjeiro * @param dev 612f97422eSNelio Laranjeiro * Pointer to Ethernet device structure. 622f97422eSNelio Laranjeiro * @param[in] rss_conf 632f97422eSNelio Laranjeiro * RSS configuration data. 642f97422eSNelio Laranjeiro * 652f97422eSNelio Laranjeiro * @return 662f97422eSNelio Laranjeiro * 0 on success, negative errno value on failure. 672f97422eSNelio Laranjeiro */ 682f97422eSNelio Laranjeiro int 692f97422eSNelio Laranjeiro mlx5_rss_hash_update(struct rte_eth_dev *dev, 702f97422eSNelio Laranjeiro struct rte_eth_rss_conf *rss_conf) 712f97422eSNelio Laranjeiro { 722f97422eSNelio Laranjeiro struct priv *priv = dev->data->dev_private; 7329c1d8bbSNélio Laranjeiro int ret = 0; 742f97422eSNelio Laranjeiro 752f97422eSNelio Laranjeiro priv_lock(priv); 76*b365799bSNélio Laranjeiro if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) { 77*b365799bSNélio Laranjeiro ret = -EINVAL; 78*b365799bSNélio Laranjeiro goto out; 79*b365799bSNélio Laranjeiro } 80920b4e54SNélio Laranjeiro if (rss_conf->rss_key && rss_conf->rss_key_len) { 8129c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key, 8229c1d8bbSNélio Laranjeiro rss_conf->rss_key_len, 0); 8329c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 8429c1d8bbSNélio Laranjeiro ret = -ENOMEM; 8529c1d8bbSNélio Laranjeiro goto out; 8629c1d8bbSNélio Laranjeiro } 87920b4e54SNélio Laranjeiro memcpy(priv->rss_conf.rss_key, rss_conf->rss_key, 8829c1d8bbSNélio Laranjeiro rss_conf->rss_key_len); 8929c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len = rss_conf->rss_key_len; 9029c1d8bbSNélio Laranjeiro } 9129c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = rss_conf->rss_hf; 9229c1d8bbSNélio Laranjeiro out: 932f97422eSNelio Laranjeiro priv_unlock(priv); 9429c1d8bbSNélio Laranjeiro return ret; 952f97422eSNelio Laranjeiro } 962f97422eSNelio Laranjeiro 972f97422eSNelio Laranjeiro /** 982f97422eSNelio Laranjeiro * DPDK callback to get the RSS hash configuration. 992f97422eSNelio Laranjeiro * 1002f97422eSNelio Laranjeiro * @param dev 1012f97422eSNelio Laranjeiro * Pointer to Ethernet device structure. 1022f97422eSNelio Laranjeiro * @param[in, out] rss_conf 1032f97422eSNelio Laranjeiro * RSS configuration data. 1042f97422eSNelio Laranjeiro * 1052f97422eSNelio Laranjeiro * @return 1062f97422eSNelio Laranjeiro * 0 on success, negative errno value on failure. 1072f97422eSNelio Laranjeiro */ 1082f97422eSNelio Laranjeiro int 1092f97422eSNelio Laranjeiro mlx5_rss_hash_conf_get(struct rte_eth_dev *dev, 1102f97422eSNelio Laranjeiro struct rte_eth_rss_conf *rss_conf) 1112f97422eSNelio Laranjeiro { 1122f97422eSNelio Laranjeiro struct priv *priv = dev->data->dev_private; 1132f97422eSNelio Laranjeiro 114920b4e54SNélio Laranjeiro if (!rss_conf) 115920b4e54SNélio Laranjeiro return -EINVAL; 1162f97422eSNelio Laranjeiro priv_lock(priv); 117920b4e54SNélio Laranjeiro if (rss_conf->rss_key && 118920b4e54SNélio Laranjeiro (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) { 11929c1d8bbSNélio Laranjeiro memcpy(rss_conf->rss_key, priv->rss_conf.rss_key, 12029c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len); 121920b4e54SNélio Laranjeiro } 122920b4e54SNélio Laranjeiro rss_conf->rss_key_len = priv->rss_conf.rss_key_len; 123920b4e54SNélio Laranjeiro rss_conf->rss_hf = priv->rss_conf.rss_hf; 1242f97422eSNelio Laranjeiro priv_unlock(priv); 125920b4e54SNélio Laranjeiro return 0; 1262f97422eSNelio Laranjeiro } 127634efbc2SNelio Laranjeiro 128634efbc2SNelio Laranjeiro /** 129634efbc2SNelio Laranjeiro * Allocate/reallocate RETA index table. 130634efbc2SNelio Laranjeiro * 131634efbc2SNelio Laranjeiro * @param priv 132634efbc2SNelio Laranjeiro * Pointer to private structure. 133634efbc2SNelio Laranjeiro * @praram reta_size 134634efbc2SNelio Laranjeiro * The size of the array to allocate. 135634efbc2SNelio Laranjeiro * 136634efbc2SNelio Laranjeiro * @return 137634efbc2SNelio Laranjeiro * 0 on success, errno value on failure. 138634efbc2SNelio Laranjeiro */ 139634efbc2SNelio Laranjeiro int 140634efbc2SNelio Laranjeiro priv_rss_reta_index_resize(struct priv *priv, unsigned int reta_size) 141634efbc2SNelio Laranjeiro { 142634efbc2SNelio Laranjeiro void *mem; 143634efbc2SNelio Laranjeiro unsigned int old_size = priv->reta_idx_n; 144634efbc2SNelio Laranjeiro 145634efbc2SNelio Laranjeiro if (priv->reta_idx_n == reta_size) 146634efbc2SNelio Laranjeiro return 0; 147634efbc2SNelio Laranjeiro 148634efbc2SNelio Laranjeiro mem = rte_realloc(priv->reta_idx, 149634efbc2SNelio Laranjeiro reta_size * sizeof((*priv->reta_idx)[0]), 0); 150634efbc2SNelio Laranjeiro if (!mem) 151634efbc2SNelio Laranjeiro return ENOMEM; 152634efbc2SNelio Laranjeiro priv->reta_idx = mem; 153634efbc2SNelio Laranjeiro priv->reta_idx_n = reta_size; 154634efbc2SNelio Laranjeiro 155634efbc2SNelio Laranjeiro if (old_size < reta_size) 156634efbc2SNelio Laranjeiro memset(&(*priv->reta_idx)[old_size], 0, 157634efbc2SNelio Laranjeiro (reta_size - old_size) * 158634efbc2SNelio Laranjeiro sizeof((*priv->reta_idx)[0])); 159634efbc2SNelio Laranjeiro return 0; 160634efbc2SNelio Laranjeiro } 161634efbc2SNelio Laranjeiro 162634efbc2SNelio Laranjeiro /** 163634efbc2SNelio Laranjeiro * Query RETA table. 164634efbc2SNelio Laranjeiro * 165634efbc2SNelio Laranjeiro * @param priv 166634efbc2SNelio Laranjeiro * Pointer to private structure. 167634efbc2SNelio Laranjeiro * @param[in, out] reta_conf 168634efbc2SNelio Laranjeiro * Pointer to the first RETA configuration structure. 169634efbc2SNelio Laranjeiro * @param reta_size 170634efbc2SNelio Laranjeiro * Number of entries. 171634efbc2SNelio Laranjeiro * 172634efbc2SNelio Laranjeiro * @return 173634efbc2SNelio Laranjeiro * 0 on success, errno value on failure. 174634efbc2SNelio Laranjeiro */ 175634efbc2SNelio Laranjeiro static int 176634efbc2SNelio Laranjeiro priv_dev_rss_reta_query(struct priv *priv, 177634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 178634efbc2SNelio Laranjeiro unsigned int reta_size) 179634efbc2SNelio Laranjeiro { 180634efbc2SNelio Laranjeiro unsigned int idx; 181634efbc2SNelio Laranjeiro unsigned int i; 182634efbc2SNelio Laranjeiro 183d365210eSYongseok Koh if (!reta_size || reta_size > priv->reta_idx_n) 184d365210eSYongseok Koh return EINVAL; 185634efbc2SNelio Laranjeiro /* Fill each entry of the table even if its bit is not set. */ 186634efbc2SNelio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 187634efbc2SNelio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 188634efbc2SNelio Laranjeiro reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] = 189634efbc2SNelio Laranjeiro (*priv->reta_idx)[i]; 190634efbc2SNelio Laranjeiro } 191634efbc2SNelio Laranjeiro return 0; 192634efbc2SNelio Laranjeiro } 193634efbc2SNelio Laranjeiro 194634efbc2SNelio Laranjeiro /** 195634efbc2SNelio Laranjeiro * Update RETA table. 196634efbc2SNelio Laranjeiro * 197634efbc2SNelio Laranjeiro * @param priv 198634efbc2SNelio Laranjeiro * Pointer to private structure. 199634efbc2SNelio Laranjeiro * @param[in] reta_conf 200634efbc2SNelio Laranjeiro * Pointer to the first RETA configuration structure. 201634efbc2SNelio Laranjeiro * @param reta_size 202634efbc2SNelio Laranjeiro * Number of entries. 203634efbc2SNelio Laranjeiro * 204634efbc2SNelio Laranjeiro * @return 205634efbc2SNelio Laranjeiro * 0 on success, errno value on failure. 206634efbc2SNelio Laranjeiro */ 207634efbc2SNelio Laranjeiro static int 208634efbc2SNelio Laranjeiro priv_dev_rss_reta_update(struct priv *priv, 209634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 210634efbc2SNelio Laranjeiro unsigned int reta_size) 211634efbc2SNelio Laranjeiro { 212634efbc2SNelio Laranjeiro unsigned int idx; 213634efbc2SNelio Laranjeiro unsigned int i; 214634efbc2SNelio Laranjeiro unsigned int pos; 215634efbc2SNelio Laranjeiro int ret; 216634efbc2SNelio Laranjeiro 217d365210eSYongseok Koh if (!reta_size) 218d365210eSYongseok Koh return EINVAL; 219d365210eSYongseok Koh ret = priv_rss_reta_index_resize(priv, reta_size); 220634efbc2SNelio Laranjeiro if (ret) 221634efbc2SNelio Laranjeiro return ret; 222634efbc2SNelio Laranjeiro 223634efbc2SNelio Laranjeiro for (idx = 0, i = 0; (i != reta_size); ++i) { 224634efbc2SNelio Laranjeiro idx = i / RTE_RETA_GROUP_SIZE; 225634efbc2SNelio Laranjeiro pos = i % RTE_RETA_GROUP_SIZE; 226634efbc2SNelio Laranjeiro if (((reta_conf[idx].mask >> i) & 0x1) == 0) 227634efbc2SNelio Laranjeiro continue; 228634efbc2SNelio Laranjeiro assert(reta_conf[idx].reta[pos] < priv->rxqs_n); 229634efbc2SNelio Laranjeiro (*priv->reta_idx)[i] = reta_conf[idx].reta[pos]; 230634efbc2SNelio Laranjeiro } 231634efbc2SNelio Laranjeiro return 0; 232634efbc2SNelio Laranjeiro } 233634efbc2SNelio Laranjeiro 234634efbc2SNelio Laranjeiro /** 235634efbc2SNelio Laranjeiro * DPDK callback to get the RETA indirection table. 236634efbc2SNelio Laranjeiro * 237634efbc2SNelio Laranjeiro * @param dev 238634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 239634efbc2SNelio Laranjeiro * @param reta_conf 240634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 241634efbc2SNelio Laranjeiro * @param reta_size 242634efbc2SNelio Laranjeiro * Size of the RETA table. 243634efbc2SNelio Laranjeiro * 244634efbc2SNelio Laranjeiro * @return 245634efbc2SNelio Laranjeiro * 0 on success, negative errno value on failure. 246634efbc2SNelio Laranjeiro */ 247634efbc2SNelio Laranjeiro int 248634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_query(struct rte_eth_dev *dev, 249634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 250634efbc2SNelio Laranjeiro uint16_t reta_size) 251634efbc2SNelio Laranjeiro { 252634efbc2SNelio Laranjeiro int ret; 253634efbc2SNelio Laranjeiro struct priv *priv = dev->data->dev_private; 254634efbc2SNelio Laranjeiro 255634efbc2SNelio Laranjeiro priv_lock(priv); 256634efbc2SNelio Laranjeiro ret = priv_dev_rss_reta_query(priv, reta_conf, reta_size); 257634efbc2SNelio Laranjeiro priv_unlock(priv); 258634efbc2SNelio Laranjeiro return -ret; 259634efbc2SNelio Laranjeiro } 260634efbc2SNelio Laranjeiro 261634efbc2SNelio Laranjeiro /** 262634efbc2SNelio Laranjeiro * DPDK callback to update the RETA indirection table. 263634efbc2SNelio Laranjeiro * 264634efbc2SNelio Laranjeiro * @param dev 265634efbc2SNelio Laranjeiro * Pointer to Ethernet device structure. 266634efbc2SNelio Laranjeiro * @param reta_conf 267634efbc2SNelio Laranjeiro * Pointer to RETA configuration structure array. 268634efbc2SNelio Laranjeiro * @param reta_size 269634efbc2SNelio Laranjeiro * Size of the RETA table. 270634efbc2SNelio Laranjeiro * 271634efbc2SNelio Laranjeiro * @return 272634efbc2SNelio Laranjeiro * 0 on success, negative errno value on failure. 273634efbc2SNelio Laranjeiro */ 274634efbc2SNelio Laranjeiro int 275634efbc2SNelio Laranjeiro mlx5_dev_rss_reta_update(struct rte_eth_dev *dev, 276634efbc2SNelio Laranjeiro struct rte_eth_rss_reta_entry64 *reta_conf, 277634efbc2SNelio Laranjeiro uint16_t reta_size) 278634efbc2SNelio Laranjeiro { 279634efbc2SNelio Laranjeiro int ret; 280634efbc2SNelio Laranjeiro struct priv *priv = dev->data->dev_private; 281634efbc2SNelio Laranjeiro 282634efbc2SNelio Laranjeiro priv_lock(priv); 283634efbc2SNelio Laranjeiro ret = priv_dev_rss_reta_update(priv, reta_conf, reta_size); 284634efbc2SNelio Laranjeiro priv_unlock(priv); 2853f2fe392SNélio Laranjeiro if (dev->data->dev_started) { 2863f2fe392SNélio Laranjeiro mlx5_dev_stop(dev); 2873f2fe392SNélio Laranjeiro mlx5_dev_start(dev); 2883f2fe392SNélio Laranjeiro } 289634efbc2SNelio Laranjeiro return -ret; 290634efbc2SNelio Laranjeiro } 291