get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 8543,
    "url": "https://patches.dpdk.org/api/patches/8543/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1446485467-17847-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": "<1446485467-17847-1-git-send-email-adrien.mazarguil@6wind.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1446485467-17847-1-git-send-email-adrien.mazarguil@6wind.com",
    "date": "2015-11-02T17:31:07",
    "name": "[dpdk-dev] mlx5: RETA query/update support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "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/1446485467-17847-1-git-send-email-adrien.mazarguil@6wind.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/8543/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/8543/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 216FA8DA1;\n\tMon,  2 Nov 2015 18:31:35 +0100 (CET)",
            "from mail-wm0-f44.google.com (mail-wm0-f44.google.com\n\t[74.125.82.44]) by dpdk.org (Postfix) with ESMTP id D221F5A50\n\tfor <dev@dpdk.org>; Mon,  2 Nov 2015 18:31:33 +0100 (CET)",
            "by wmeg8 with SMTP id g8so66861648wme.1\n\tfor <dev@dpdk.org>; Mon, 02 Nov 2015 09:31:33 -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\tgl9sm23456547wjb.10.2015.11.02.09.31.32\n\t(version=TLSv1.2 cipher=RC4-SHA bits=128/128);\n\tMon, 02 Nov 2015 09:31:32 -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=sVPY0ljpgu1G5CK6dUeVLgubktk0JrR6wmvH6eqmRQw=;\n\tb=RDtthIKAYYxtTUqIvBSZ81ZGLNkp/eRV8OKAYOovFex+skVB1F8vT4liAQIU0CV2hJ\n\tJP/bL7LNgHY/hvdIW+SAmNgN3Vr3tedyUDS+RHBDIqpiT0pjKkFyIo9GN0YovdnN9OM6\n\tt4TQDdjEieg+AGDpq1rzNm8SJZyhoedP+nEYeQncdxIrhfW4V273jQ2umTPgAifEVLoZ\n\t9o7pu8J5v+MMyZlbr7hkCcacq6MpEfSlyQdFjcftjADBgXFll5TEiq9HntUGBDzGLy/+\n\tVTU5Twjs/qWAAcOShVcMKBvjvvm+wAA2MeZ7CNcASfRk/d6pkypD9tco/4RNorOFxTz6\n\tjFYQ==",
        "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=sVPY0ljpgu1G5CK6dUeVLgubktk0JrR6wmvH6eqmRQw=;\n\tb=PX912P3/2xZkiQrAR5T6zEFaK/l/xAsYNQaqTaxWWKxJKjm/cKqm+yHRYnXYHEjjni\n\tK8HkMME1t7ucAtgqRH+3SrIWSS7dPeuXiAI4wpbFtgEU+jz+ItAYyFGPo+N2Xk8WHvOr\n\tzNBE18wR7FKDrwwn5Z4zdxFIOcjv0mGxT86GPyYsWa61JbyuuXiMavkrdSObVuiX71UB\n\thnODN2ANbevbMSZIj0BRRbGjsESLek3m/Y63244rwyxV1jW8Q/lQc5DaWKEEpHe9VREd\n\tjb/pTlhtij/7yroTJoszMZfbqJT7RCPbrrfER+9Nviua3JWTfB3vZMnoNg1fbj8KwA7+\n\tuauA==",
        "X-Gm-Message-State": "ALoCoQl1uW6s1HxKMysxsb831urv+A8VdVnnY307NdQw+FiAuePJ8/eMrWHNu7k7/FVHa1/Z9z2k",
        "X-Received": "by 10.28.175.208 with SMTP id y199mr15719199wme.24.1446485493598;\n\tMon, 02 Nov 2015 09:31:33 -0800 (PST)",
        "From": "Adrien Mazarguil <adrien.mazarguil@6wind.com>",
        "To": "dev@dpdk.org",
        "Date": "Mon,  2 Nov 2015 18:31:07 +0100",
        "Message-Id": "<1446485467-17847-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] 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 is able to use indirection tables size of power of two, but\nwith the current API it is impossible to predict its size, so to simplify,\nfor any query/update RETA command, the indirection table is modified to use\n256 entries.\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"
    ]
}