get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/8545/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 8545,
    "url": "https://patches.dpdk.org/api/patches/8545/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1446487917-18241-1-git-send-email-adrien.mazarguil@6wind.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1446487917-18241-1-git-send-email-adrien.mazarguil@6wind.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1446487917-18241-1-git-send-email-adrien.mazarguil@6wind.com",
    "date": "2015-11-02T18:11:57",
    "name": "[dpdk-dev,v3] mlx5: RETA query/update support",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "1a6c989ee559d10d22229bb97671cfd7ca22b317",
    "submitter": {
        "id": 165,
        "url": "https://patches.dpdk.org/api/people/165/?format=api",
        "name": "Adrien Mazarguil",
        "email": "adrien.mazarguil@6wind.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1446487917-18241-1-git-send-email-adrien.mazarguil@6wind.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/8545/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/8545/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 8C5D75954;\n\tMon,  2 Nov 2015 19:12:26 +0100 (CET)",
            "from mail-wi0-f177.google.com (mail-wi0-f177.google.com\n\t[209.85.212.177]) by dpdk.org (Postfix) with ESMTP id 7769A3787\n\tfor <dev@dpdk.org>; Mon,  2 Nov 2015 19:12:24 +0100 (CET)",
            "by wikq8 with SMTP id q8so57016973wik.1\n\tfor <dev@dpdk.org>; Mon, 02 Nov 2015 10:12:24 -0800 (PST)",
            "from 6wind.com (guy78-3-82-239-227-177.fbx.proxad.net.\n\t[82.239.227.177]) by smtp.gmail.com with ESMTPSA id\n\tl1sm19352628wmg.21.2015.11.02.10.12.22\n\t(version=TLSv1.2 cipher=RC4-SHA bits=128/128);\n\tMon, 02 Nov 2015 10:12:23 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=6wind_com.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=bJLMvHLl4VbYgmVYyxG12cwhqICx4BPJj8EncqUA8Xw=;\n\tb=LJAZmRdqnBtyyeWYgJ6n+STPdzvw3TnAUETf2uNzVNmY7lT97+okWadwo4DO2KLzgW\n\tTIWcZOivtNYr3u4rICOdeED3DY9OIDy19iyIwqiKBhgXM+0wUrQ6gfdkKX4jKv9hF15U\n\tWuHAdfKaqJZgAJbOS3DnWLuirOx3bB9yJUDHsHV2bJIx2myh3s252fFG4XIfAE/7P6W8\n\taNRXT69u+UCuebQlE19vQDzEj4OVcfsBOGXVZSir5oHbp8Q2QlVBOTd++FwEk1BUviEV\n\tWyUGUUideqMuZjCNhVK90mA8vAvVuWxMoyBgpA01LCIABFO8nsJqF3j+N2Ow2Q4cRWo5\n\tmpbw==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=bJLMvHLl4VbYgmVYyxG12cwhqICx4BPJj8EncqUA8Xw=;\n\tb=hd5fBfVQDXAWENND0C/i4MszZ2o/Knu12ZPGCNd0Z4KCPVw/No+3Lj8YH4KBwK8fk0\n\tucjNGeSsa9OKahcDfXYARjRf1IBoyp3Bla1kzSQd/e0pEIN+VkqgE0m3TOGFPjCQJgs5\n\tw8gtaqsUIryXGAsBqeWCypN97JKP2zMo1aXWyKtZQM8+asIqjGFZqr2MW93gRA+pAJQq\n\tXq9v3itWS1Esaw1hKOc0/Fk0KLUjJqkVq8C137Q+Pj38XY9GWnbFR6+xTQR56gtbF+lb\n\tI63MfWrPSsQqSh6cUCsGUEO+lTvn24x4ZatCJumaKR9b3RleB3yzW1LqxXL7OyCvfqIL\n\tj5cg==",
        "X-Gm-Message-State": "ALoCoQln1GqJaHdk3S06LnlL79yXyRXugZg/uGAsq7enfuALdfzaXOsGuVK/N+ZFGg059AruIzCd",
        "X-Received": "by 10.194.63.7 with SMTP id c7mr24777625wjs.70.1446487944267;\n\tMon, 02 Nov 2015 10:12:24 -0800 (PST)",
        "From": "Adrien Mazarguil <adrien.mazarguil@6wind.com>",
        "To": "dev@dpdk.org",
        "Date": "Mon,  2 Nov 2015 19:11:57 +0100",
        "Message-Id": "<1446487917-18241-1-git-send-email-adrien.mazarguil@6wind.com>",
        "X-Mailer": "git-send-email 2.1.0",
        "In-Reply-To": "<1446231537-8380-1-git-send-email-adrien.mazarguil@6wind.com>",
        "References": "<1446231537-8380-1-git-send-email-adrien.mazarguil@6wind.com>",
        "Subject": "[dpdk-dev] [PATCH v3] mlx5: RETA query/update support",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>\n\nConnectX-4 adapters to not have a constant indirection table size, which is\nset at runtime from the number of RX queues. The maximum size is retrieved\nusing a hardware query and is normally 512.\n\nSince the current RETA API cannot handle a variable size, any query/update\ncommand causes it to be silently updated to RSS_INDIRECTION_TABLE_SIZE\nentries regardless of the original size.\n\nAlso due to the underlying type of the configuration structure, the maximum\nsize is limited to RSS_INDIRECTION_TABLE_SIZE (currently 128, at most 256\nentries).\n\nA port stop/start must be done to apply the new RETA configuration.\n\nSigned-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>\n---\n drivers/net/mlx5/mlx5.c        |   8 +-\n drivers/net/mlx5/mlx5.h        |   7 ++\n drivers/net/mlx5/mlx5_ethdev.c |  29 ++++++++\n drivers/net/mlx5/mlx5_rss.c    | 163 +++++++++++++++++++++++++++++++++++++++++\n drivers/net/mlx5/mlx5_rxq.c    |  53 ++------------\n drivers/net/mlx5/mlx5_utils.h  |  20 +++++\n 6 files changed, 234 insertions(+), 46 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 9636588..5a95260 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -133,6 +133,8 @@ mlx5_dev_close(struct rte_eth_dev *dev)\n \t\t\trte_free((*priv->rss_conf)[i]);\n \t\trte_free(priv->rss_conf);\n \t}\n+\tif (priv->reta_idx != NULL)\n+\t\trte_free(priv->reta_idx);\n \tpriv_unlock(priv);\n \tmemset(priv, 0, sizeof(*priv));\n }\n@@ -160,6 +162,8 @@ static const struct eth_dev_ops mlx5_dev_ops = {\n \t.mac_addr_remove = mlx5_mac_addr_remove,\n \t.mac_addr_add = mlx5_mac_addr_add,\n \t.mtu_set = mlx5_dev_set_mtu,\n+\t.reta_update = mlx5_dev_rss_reta_update,\n+\t.reta_query = mlx5_dev_rss_reta_query,\n \t.rss_hash_update = mlx5_rss_hash_update,\n \t.rss_hash_conf_get = mlx5_rss_hash_conf_get,\n };\n@@ -373,7 +377,9 @@ mlx5_pci_devinit(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)\n \t\tDEBUG(\"L2 tunnel checksum offloads are %ssupported\",\n \t\t      (priv->hw_csum_l2tun ? \"\" : \"not \"));\n \n-\t\tpriv->ind_table_max_size = exp_device_attr.rx_hash_caps.max_rwq_indirection_table_size;\n+\t\tpriv->ind_table_max_size =\n+\t\t\tRTE_MIN((unsigned int)RSS_INDIRECTION_TABLE_SIZE,\n+\t\t\t\texp_device_attr.rx_hash_caps.max_rwq_indirection_table_size);\n \t\tDEBUG(\"maximum RX indirection table size is %u\",\n \t\t      priv->ind_table_max_size);\n \ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 0daacc8..b84d31d 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -118,6 +118,8 @@ struct priv {\n \t/* RSS configuration array indexed by hash RX queue type. */\n \tstruct rte_eth_rss_conf *(*rss_conf)[];\n \tstruct rte_intr_handle intr_handle; /* Interrupt handler. */\n+\tunsigned int (*reta_idx)[]; /* RETA index table. */\n+\tunsigned int reta_idx_n; /* RETA index size. */\n \trte_spinlock_t lock; /* Lock for control functions. */\n };\n \n@@ -184,6 +186,11 @@ int rss_hash_rss_conf_new_key(struct priv *, const uint8_t *, unsigned int,\n \t\t\t      uint64_t);\n int mlx5_rss_hash_update(struct rte_eth_dev *, struct rte_eth_rss_conf *);\n int mlx5_rss_hash_conf_get(struct rte_eth_dev *, struct rte_eth_rss_conf *);\n+int priv_rss_reta_index_resize(struct priv *, unsigned int);\n+int mlx5_dev_rss_reta_query(struct rte_eth_dev *,\n+\t\t\t    struct rte_eth_rss_reta_entry64 *, uint16_t);\n+int mlx5_dev_rss_reta_update(struct rte_eth_dev *,\n+\t\t\t     struct rte_eth_rss_reta_entry64 *, uint16_t);\n \n /* mlx5_rxmode.c */\n \ndiff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c\nindex 84e877c..1159fa3 100644\n--- a/drivers/net/mlx5/mlx5_ethdev.c\n+++ b/drivers/net/mlx5/mlx5_ethdev.c\n@@ -410,6 +410,9 @@ dev_configure(struct rte_eth_dev *dev)\n \tstruct priv *priv = dev->data->dev_private;\n \tunsigned int rxqs_n = dev->data->nb_rx_queues;\n \tunsigned int txqs_n = dev->data->nb_tx_queues;\n+\tunsigned int i;\n+\tunsigned int j;\n+\tunsigned int reta_idx_n;\n \n \tpriv->rxqs = (void *)dev->data->rx_queues;\n \tpriv->txqs = (void *)dev->data->tx_queues;\n@@ -418,11 +421,31 @@ dev_configure(struct rte_eth_dev *dev)\n \t\t     (void *)dev, priv->txqs_n, txqs_n);\n \t\tpriv->txqs_n = txqs_n;\n \t}\n+\tif (rxqs_n > priv->ind_table_max_size) {\n+\t\tERROR(\"cannot handle this many RX queues (%u)\", rxqs_n);\n+\t\treturn EINVAL;\n+\t}\n \tif (rxqs_n == priv->rxqs_n)\n \t\treturn 0;\n \tINFO(\"%p: RX queues number update: %u -> %u\",\n \t     (void *)dev, priv->rxqs_n, rxqs_n);\n \tpriv->rxqs_n = rxqs_n;\n+\t/* If the requested number of RX queues is not a power of two, use the\n+\t * maximum indirection table size for better balancing.\n+\t * The result is always rounded to the next power of two. */\n+\treta_idx_n = (1 << log2above((rxqs_n & (rxqs_n - 1)) ?\n+\t\t\t\t     priv->ind_table_max_size :\n+\t\t\t\t     rxqs_n));\n+\tif (priv_rss_reta_index_resize(priv, reta_idx_n))\n+\t\treturn ENOMEM;\n+\t/* When the number of RX queues is not a power of two, the remaining\n+\t * table entries are padded with reused WQs and hashes are not spread\n+\t * uniformly. */\n+\tfor (i = 0, j = 0; (i != reta_idx_n); ++i) {\n+\t\t(*priv->reta_idx)[i] = j;\n+\t\tif (++j == rxqs_n)\n+\t\t\tj = 0;\n+\t}\n \treturn 0;\n }\n \n@@ -494,6 +517,12 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)\n \t\t 0);\n \tif (priv_get_ifname(priv, &ifname) == 0)\n \t\tinfo->if_index = if_nametoindex(ifname);\n+\t/* FIXME: RETA update/query API expects the callee to know the size of\n+\t * the indirection table, for this PMD the size varies depending on\n+\t * the number of RX queues, it becomes impossible to find the correct\n+\t * size if it is not fixed.\n+\t * The API should be updated to solve this problem. */\n+\tinfo->reta_size = priv->ind_table_max_size;\n \tpriv_unlock(priv);\n }\n \ndiff --git a/drivers/net/mlx5/mlx5_rss.c b/drivers/net/mlx5/mlx5_rss.c\nindex bf19aca..7eb688a 100644\n--- a/drivers/net/mlx5/mlx5_rss.c\n+++ b/drivers/net/mlx5/mlx5_rss.c\n@@ -211,3 +211,166 @@ mlx5_rss_hash_conf_get(struct rte_eth_dev *dev,\n \tpriv_unlock(priv);\n \treturn 0;\n }\n+\n+/**\n+ * Allocate/reallocate RETA index table.\n+ *\n+ * @param priv\n+ *   Pointer to private structure.\n+ * @praram reta_size\n+ *   The size of the array to allocate.\n+ *\n+ * @return\n+ *   0 on success, errno value on failure.\n+ */\n+int\n+priv_rss_reta_index_resize(struct priv *priv, unsigned int reta_size)\n+{\n+\tvoid *mem;\n+\tunsigned int old_size = priv->reta_idx_n;\n+\n+\tif (priv->reta_idx_n == reta_size)\n+\t\treturn 0;\n+\n+\tmem = rte_realloc(priv->reta_idx,\n+\t\t\t  reta_size * sizeof((*priv->reta_idx)[0]), 0);\n+\tif (!mem)\n+\t\treturn ENOMEM;\n+\tpriv->reta_idx = mem;\n+\tpriv->reta_idx_n = reta_size;\n+\n+\tif (old_size < reta_size)\n+\t\tmemset(&(*priv->reta_idx)[old_size], 0,\n+\t\t       (reta_size - old_size) *\n+\t\t       sizeof((*priv->reta_idx)[0]));\n+\treturn 0;\n+}\n+\n+/**\n+ * Query RETA table.\n+ *\n+ * @param priv\n+ *   Pointer to private structure.\n+ * @param[in, out] reta_conf\n+ *   Pointer to the first RETA configuration structure.\n+ * @param reta_size\n+ *   Number of entries.\n+ *\n+ * @return\n+ *   0 on success, errno value on failure.\n+ */\n+static int\n+priv_dev_rss_reta_query(struct priv *priv,\n+\t\t\tstruct rte_eth_rss_reta_entry64 *reta_conf,\n+\t\t\tunsigned int reta_size)\n+{\n+\tunsigned int idx;\n+\tunsigned int i;\n+\tint ret;\n+\n+\t/* See RETA comment in mlx5_dev_infos_get(). */\n+\tret = priv_rss_reta_index_resize(priv, priv->ind_table_max_size);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Fill each entry of the table even if its bit is not set. */\n+\tfor (idx = 0, i = 0; (i != reta_size); ++i) {\n+\t\tidx = i / RTE_RETA_GROUP_SIZE;\n+\t\treta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] =\n+\t\t\t(*priv->reta_idx)[i];\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * Update RETA table.\n+ *\n+ * @param priv\n+ *   Pointer to private structure.\n+ * @param[in] reta_conf\n+ *   Pointer to the first RETA configuration structure.\n+ * @param reta_size\n+ *   Number of entries.\n+ *\n+ * @return\n+ *   0 on success, errno value on failure.\n+ */\n+static int\n+priv_dev_rss_reta_update(struct priv *priv,\n+\t\t\t struct rte_eth_rss_reta_entry64 *reta_conf,\n+\t\t\t unsigned int reta_size)\n+{\n+\tunsigned int idx;\n+\tunsigned int i;\n+\tunsigned int pos;\n+\tint ret;\n+\n+\t/* See RETA comment in mlx5_dev_infos_get(). */\n+\tret = priv_rss_reta_index_resize(priv, priv->ind_table_max_size);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tfor (idx = 0, i = 0; (i != reta_size); ++i) {\n+\t\tidx = i / RTE_RETA_GROUP_SIZE;\n+\t\tpos = i % RTE_RETA_GROUP_SIZE;\n+\t\tif (((reta_conf[idx].mask >> i) & 0x1) == 0)\n+\t\t\tcontinue;\n+\t\tassert(reta_conf[idx].reta[pos] < priv->rxqs_n);\n+\t\t(*priv->reta_idx)[i] = reta_conf[idx].reta[pos];\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * DPDK callback to get the RETA indirection table.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device structure.\n+ * @param reta_conf\n+ *   Pointer to RETA configuration structure array.\n+ * @param reta_size\n+ *   Size of the RETA table.\n+ *\n+ * @return\n+ *   0 on success, negative errno value on failure.\n+ */\n+int\n+mlx5_dev_rss_reta_query(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_rss_reta_entry64 *reta_conf,\n+\t\t\tuint16_t reta_size)\n+{\n+\tint ret;\n+\tstruct priv *priv = dev->data->dev_private;\n+\n+\tpriv_lock(priv);\n+\tret = priv_dev_rss_reta_query(priv, reta_conf, reta_size);\n+\tpriv_unlock(priv);\n+\treturn -ret;\n+}\n+\n+/**\n+ * DPDK callback to update the RETA indirection table.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device structure.\n+ * @param reta_conf\n+ *   Pointer to RETA configuration structure array.\n+ * @param reta_size\n+ *   Size of the RETA table.\n+ *\n+ * @return\n+ *   0 on success, negative errno value on failure.\n+ */\n+int\n+mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,\n+\t\t\t struct rte_eth_rss_reta_entry64 *reta_conf,\n+\t\t\t uint16_t reta_size)\n+{\n+\tint ret;\n+\tstruct priv *priv = dev->data->dev_private;\n+\n+\tpriv_lock(priv);\n+\tret = priv_dev_rss_reta_update(priv, reta_conf, reta_size);\n+\tpriv_unlock(priv);\n+\treturn -ret;\n+}\ndiff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c\nindex 084bf41..3d7ae7e 100644\n--- a/drivers/net/mlx5/mlx5_rxq.c\n+++ b/drivers/net/mlx5/mlx5_rxq.c\n@@ -259,26 +259,6 @@ hash_rxq_flow_attr(const struct hash_rxq *hash_rxq,\n }\n \n /**\n- * Return nearest power of two above input value.\n- *\n- * @param v\n- *   Input value.\n- *\n- * @return\n- *   Nearest power of two above input value.\n- */\n-static unsigned int\n-log2above(unsigned int v)\n-{\n-\tunsigned int l;\n-\tunsigned int r;\n-\n-\tfor (l = 0, r = 0; (v >> 1); ++l, v >>= 1)\n-\t\tr |= (v & 1);\n-\treturn (l + r);\n-}\n-\n-/**\n  * Return the type corresponding to the n'th bit set.\n  *\n  * @param table\n@@ -360,14 +340,7 @@ priv_make_ind_table_init(struct priv *priv,\n int\n priv_create_hash_rxqs(struct priv *priv)\n {\n-\t/* If the requested number of WQs is not a power of two, use the\n-\t * maximum indirection table size for better balancing.\n-\t * The result is always rounded to the next power of two. */\n-\tunsigned int wqs_n =\n-\t\t(1 << log2above((priv->rxqs_n & (priv->rxqs_n - 1)) ?\n-\t\t\t\tpriv->ind_table_max_size :\n-\t\t\t\tpriv->rxqs_n));\n-\tstruct ibv_exp_wq *wqs[wqs_n];\n+\tstruct ibv_exp_wq *wqs[priv->reta_idx_n];\n \tstruct ind_table_init ind_table_init[IND_TABLE_INIT_N];\n \tunsigned int ind_tables_n =\n \t\tpriv_make_ind_table_init(priv, &ind_table_init);\n@@ -393,25 +366,15 @@ priv_create_hash_rxqs(struct priv *priv)\n \t\t      \" indirection table cannot be created\");\n \t\treturn EINVAL;\n \t}\n-\tif ((wqs_n < priv->rxqs_n) || (wqs_n > priv->ind_table_max_size)) {\n-\t\tERROR(\"cannot handle this many RX queues (%u)\", priv->rxqs_n);\n-\t\terr = ERANGE;\n-\t\tgoto error;\n-\t}\n-\tif (wqs_n != priv->rxqs_n) {\n+\tif (priv->rxqs_n & (priv->rxqs_n - 1)) {\n \t\tINFO(\"%u RX queues are configured, consider rounding this\"\n \t\t     \" number to the next power of two for better balancing\",\n \t\t     priv->rxqs_n);\n-\t\tDEBUG(\"indirection table extended to assume %u WQs\", wqs_n);\n-\t}\n-\t/* When the number of RX queues is not a power of two, the remaining\n-\t * table entries are padded with reused WQs and hashes are not spread\n-\t * uniformly. */\n-\tfor (i = 0, j = 0; (i != wqs_n); ++i) {\n-\t\twqs[i] = (*priv->rxqs)[j]->wq;\n-\t\tif (++j == priv->rxqs_n)\n-\t\t\tj = 0;\n+\t\tDEBUG(\"indirection table extended to assume %u WQs\",\n+\t\t      priv->reta_idx_n);\n \t}\n+\tfor (i = 0; (i != priv->reta_idx_n); ++i)\n+\t\twqs[i] = (*priv->rxqs)[(*priv->reta_idx)[i]]->wq;\n \t/* Get number of hash RX queues to configure. */\n \tfor (i = 0, hash_rxqs_n = 0; (i != ind_tables_n); ++i)\n \t\thash_rxqs_n += ind_table_init[i].hash_types_n;\n@@ -436,8 +399,8 @@ priv_create_hash_rxqs(struct priv *priv)\n \t\tunsigned int ind_tbl_size = ind_table_init[i].max_size;\n \t\tstruct ibv_exp_rwq_ind_table *ind_table;\n \n-\t\tif (wqs_n < ind_tbl_size)\n-\t\t\tind_tbl_size = wqs_n;\n+\t\tif (priv->reta_idx_n < ind_tbl_size)\n+\t\t\tind_tbl_size = priv->reta_idx_n;\n \t\tind_init_attr.log_ind_tbl_size = log2above(ind_tbl_size);\n \t\terrno = 0;\n \t\tind_table = ibv_exp_create_rwq_ind_table(priv->ctx,\ndiff --git a/drivers/net/mlx5/mlx5_utils.h b/drivers/net/mlx5/mlx5_utils.h\nindex f1fad18..9b5e86a 100644\n--- a/drivers/net/mlx5/mlx5_utils.h\n+++ b/drivers/net/mlx5/mlx5_utils.h\n@@ -161,4 +161,24 @@ pmd_drv_log_basename(const char *s)\n \t\\\n \tsnprintf(name, sizeof(name), __VA_ARGS__)\n \n+/**\n+ * Return nearest power of two above input value.\n+ *\n+ * @param v\n+ *   Input value.\n+ *\n+ * @return\n+ *   Nearest power of two above input value.\n+ */\n+static inline unsigned int\n+log2above(unsigned int v)\n+{\n+\tunsigned int l;\n+\tunsigned int r;\n+\n+\tfor (l = 0, r = 0; (v >> 1); ++l, v >>= 1)\n+\t\tr |= (v & 1);\n+\treturn (l + r);\n+}\n+\n #endif /* RTE_PMD_MLX5_UTILS_H_ */\n",
    "prefixes": [
        "dpdk-dev",
        "v3"
    ]
}