get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 96242,
    "url": "http://patchwork.dpdk.org/api/patches/96242/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20210723102454.12206-6-mk@semihalf.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<20210723102454.12206-6-mk@semihalf.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210723102454.12206-6-mk@semihalf.com",
    "date": "2021-07-23T10:24:53",
    "name": "[v4,5/6] net/ena: rework RSS configuration",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "bc20263ac8aeb2aaf0eac419a956671839dfde7f",
    "submitter": {
        "id": 786,
        "url": "http://patchwork.dpdk.org/api/people/786/?format=api",
        "name": "Michal Krawczyk",
        "email": "mk@semihalf.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20210723102454.12206-6-mk@semihalf.com/mbox/",
    "series": [
        {
            "id": 17968,
            "url": "http://patchwork.dpdk.org/api/series/17968/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=17968",
            "date": "2021-07-23T10:24:48",
            "name": "net/ena: v2.4.0 driver update",
            "version": 4,
            "mbox": "http://patchwork.dpdk.org/series/17968/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/96242/comments/",
    "check": "warning",
    "checks": "http://patchwork.dpdk.org/api/patches/96242/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 9B860A0C46;\n\tFri, 23 Jul 2021 12:27:11 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 662C641101;\n\tFri, 23 Jul 2021 12:26:47 +0200 (CEST)",
            "from mail-ej1-f46.google.com (mail-ej1-f46.google.com\n [209.85.218.46]) by mails.dpdk.org (Postfix) with ESMTP id 3A167410E8\n for <dev@dpdk.org>; Fri, 23 Jul 2021 12:26:44 +0200 (CEST)",
            "by mail-ej1-f46.google.com with SMTP id l13so3011675ejo.3\n for <dev@dpdk.org>; Fri, 23 Jul 2021 03:26:44 -0700 (PDT)",
            "from DESKTOP-U5LNN3J.localdomain\n (093105178068.dynamic-ww-01.vectranet.pl. [93.105.178.68])\n by smtp.gmail.com with ESMTPSA id jp26sm10506142ejb.28.2021.07.23.03.26.41\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Fri, 23 Jul 2021 03:26:42 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=semihalf-com.20150623.gappssmtp.com; s=20150623;\n h=from:to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-transfer-encoding;\n bh=RY4odtA0ohjX8dWJSD6bOCQVsLJf13CItWXB0/iBwhw=;\n b=ZbaFGyy9calQRoZ8OrP4qYttdRF20BAPrsPoVzFs6Ks1Z5T+PoCoOX29nvmDzWHLAL\n pcF+vlKODZFWuAXj5n2DBCOA3js0HKkzEJSwA92YvjrLfpSbJ6OkN0b5YwLKBovgYeL1\n e8RuIvRqHW+glH9nfZNmC2OnD3HGWbHR7n3N09aWPs7L8JuxphgAxCjtV3CHx1TWSSC2\n 8sisJ0Ug+8P+cWOd6OYiwxBXa+Z3SHfbCVVA612iYqArGNPzmE0Z6vis88P7ccKCbJ5D\n 11ooJx7zWi8P0eKhqk364GlAmeElGrpCL1eMwP0lmCeW/gY8jLyl9ZRkXNd/LKbcVEDn\n aAhA==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20161025;\n h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n :references:mime-version:content-transfer-encoding;\n bh=RY4odtA0ohjX8dWJSD6bOCQVsLJf13CItWXB0/iBwhw=;\n b=kmu5mA6zqXTB5horzk4PQ44xvK6RW80ssQo9LALnNLVOBw7z+G3G9HWE2Exjr3EJ+k\n mAJU9GfULb4f0muFPQP3j3+lUuqtEmXQY/Tf8pj9RtSleKg+vcInMxrzdIe5NgL1slLU\n Pa+dz3NmRBmZ9/zrpPknSuGh0Dc5fGuJK6AtdC9KrmPvHblIm1FA9nbVBYUrt2lmANdL\n 9QFPbSibL9UodRB3CnxwvRBjaZ8x3qaf26XRx9LT6I8+lMha9ZZFw9pVzK/qymRHHn8v\n twMKWrBxc+xbB1xIx/++K/hgG+D67ylOeLkANfbQ7fHRtY8/RQGdzyvmEG2218ZBRSH0\n djBg==",
        "X-Gm-Message-State": "AOAM532KlQIEg+aSdyVraeXEIYOJ2RnCOuIBu+o5ZUNiq/R1tq4MHnad\n 8u6uCth26VZnYBsjz+30dhtFaMF2LiEXP1gF",
        "X-Google-Smtp-Source": "\n ABdhPJzjCHuyaX+QbwPZWfQXN5AL9grmllVeBONdkBHtYlAdG9ne9+zJdpLjTp4iZYS61o/qlq7ATA==",
        "X-Received": "by 2002:a17:906:b89a:: with SMTP id\n hb26mr3992908ejb.492.1627036003299;\n Fri, 23 Jul 2021 03:26:43 -0700 (PDT)",
        "From": "Michal Krawczyk <mk@semihalf.com>",
        "To": "dev@dpdk.org",
        "Cc": "ndagan@amazon.com, shaibran@amazon.com, upstream@semihalf.com,\n Michal Krawczyk <mk@semihalf.com>, Shay Agroskin <shayagr@amazon.com>,\n Amit Bernstein <amitbern@amazon.com>",
        "Date": "Fri, 23 Jul 2021 12:24:53 +0200",
        "Message-Id": "<20210723102454.12206-6-mk@semihalf.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20210723102454.12206-1-mk@semihalf.com>",
        "References": "<20210714104320.4096-1-mk@semihalf.com>\n <20210723102454.12206-1-mk@semihalf.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v4 5/6] net/ena: rework RSS configuration",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Allow user to specify his own hash key and hash ctrl if the\ndevice is supporting that. HW interprets the key in reverse byte order,\nso the PMD reorders the key before passing it to the ena_com layer.\n\nDefault key is being set in random matter each time the device is being\ninitialized.\n\nMoreover, make minor adjustments for reta size setting in terms\nof returning error values.\n\nRSS code was moved to ena_rss.c file to improve readability.\n\nSigned-off-by: Michal Krawczyk <mk@semihalf.com>\nReviewed-by: Shai Brandes <shaibran@amazon.com>\nReviewed-by: Shay Agroskin <shayagr@amazon.com>\nReviewed-by: Amit Bernstein <amitbern@amazon.com>\n---\n doc/guides/nics/features/ena.ini       |   1 +\n doc/guides/rel_notes/release_21_08.rst |   1 +\n drivers/net/ena/ena_ethdev.c           | 230 ++--------\n drivers/net/ena/ena_ethdev.h           |  34 ++\n drivers/net/ena/ena_rss.c              | 591 +++++++++++++++++++++++++\n drivers/net/ena/meson.build            |   1 +\n 6 files changed, 663 insertions(+), 195 deletions(-)\n create mode 100644 drivers/net/ena/ena_rss.c",
    "diff": "diff --git a/doc/guides/nics/features/ena.ini b/doc/guides/nics/features/ena.ini\nindex 3976bbbda6..b971243ff0 100644\n--- a/doc/guides/nics/features/ena.ini\n+++ b/doc/guides/nics/features/ena.ini\n@@ -12,6 +12,7 @@ Jumbo frame          = Y\n Scattered Rx         = Y\n TSO                  = Y\n RSS hash             = Y\n+RSS key update       = Y\n RSS reta update      = Y\n L3 checksum offload  = Y\n L4 checksum offload  = Y\ndiff --git a/doc/guides/rel_notes/release_21_08.rst b/doc/guides/rel_notes/release_21_08.rst\nindex 616e2cdea9..2586360439 100644\n--- a/doc/guides/rel_notes/release_21_08.rst\n+++ b/doc/guides/rel_notes/release_21_08.rst\n@@ -101,6 +101,7 @@ New Features\n   including:\n \n   * Added Rx interrupt support.\n+  * RSS hash function key reconfiguration support.\n \n * **Added support for Marvell CNXK crypto driver.**\n \ndiff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c\nindex 72f9887797..ee059fc165 100644\n--- a/drivers/net/ena/ena_ethdev.c\n+++ b/drivers/net/ena/ena_ethdev.c\n@@ -4,12 +4,6 @@\n  */\n \n #include <rte_string_fns.h>\n-#include <rte_ether.h>\n-#include <ethdev_driver.h>\n-#include <ethdev_pci.h>\n-#include <rte_tcp.h>\n-#include <rte_atomic.h>\n-#include <rte_dev.h>\n #include <rte_errno.h>\n #include <rte_version.h>\n #include <rte_net.h>\n@@ -30,21 +24,12 @@\n #define DRV_MODULE_VER_MINOR\t3\n #define DRV_MODULE_VER_SUBMINOR\t0\n \n-#define ENA_IO_TXQ_IDX(q)\t(2 * (q))\n-#define ENA_IO_RXQ_IDX(q)\t(2 * (q) + 1)\n-/*reverse version of ENA_IO_RXQ_IDX*/\n-#define ENA_IO_RXQ_IDX_REV(q)\t((q - 1) / 2)\n-\n #define __MERGE_64B_H_L(h, l) (((uint64_t)h << 32) | l)\n-#define TEST_BIT(val, bit_shift) (val & (1UL << bit_shift))\n \n #define GET_L4_HDR_LEN(mbuf)\t\t\t\t\t\\\n \t((rte_pktmbuf_mtod_offset(mbuf,\tstruct rte_tcp_hdr *,\t\\\n \t\tmbuf->l3_len + mbuf->l2_len)->data_off) >> 4)\n \n-#define ENA_RX_RSS_TABLE_LOG_SIZE  7\n-#define ENA_RX_RSS_TABLE_SIZE\t(1 << ENA_RX_RSS_TABLE_LOG_SIZE)\n-#define ENA_HASH_KEY_SIZE\t40\n #define ETH_GSTRING_LEN\t32\n \n #define ARRAY_SIZE(x) RTE_DIM(x)\n@@ -223,12 +208,6 @@ static int ena_queue_start_all(struct rte_eth_dev *dev,\n static void ena_stats_restart(struct rte_eth_dev *dev);\n static int ena_infos_get(struct rte_eth_dev *dev,\n \t\t\t struct rte_eth_dev_info *dev_info);\n-static int ena_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-static int ena_rss_reta_query(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 static void ena_interrupt_handler_rte(void *cb_arg);\n static void ena_timer_wd_callback(struct rte_timer *timer, void *arg);\n static void ena_destroy_device(struct rte_eth_dev *eth_dev);\n@@ -276,27 +255,13 @@ static const struct eth_dev_ops ena_dev_ops = {\n \t.reta_query           = ena_rss_reta_query,\n \t.rx_queue_intr_enable = ena_rx_queue_intr_enable,\n \t.rx_queue_intr_disable = ena_rx_queue_intr_disable,\n+\t.rss_hash_update      = ena_rss_hash_update,\n+\t.rss_hash_conf_get    = ena_rss_hash_conf_get,\n };\n \n-void ena_rss_key_fill(void *key, size_t size)\n-{\n-\tstatic bool key_generated;\n-\tstatic uint8_t default_key[ENA_HASH_KEY_SIZE];\n-\tsize_t i;\n-\n-\tRTE_ASSERT(size <= ENA_HASH_KEY_SIZE);\n-\n-\tif (!key_generated) {\n-\t\tfor (i = 0; i < ENA_HASH_KEY_SIZE; ++i)\n-\t\t\tdefault_key[i] = rte_rand() & 0xff;\n-\t\tkey_generated = true;\n-\t}\n-\n-\trte_memcpy(key, default_key, size);\n-}\n-\n static inline void ena_rx_mbuf_prepare(struct rte_mbuf *mbuf,\n-\t\t\t\t       struct ena_com_rx_ctx *ena_rx_ctx)\n+\t\t\t\t       struct ena_com_rx_ctx *ena_rx_ctx,\n+\t\t\t\t       bool fill_hash)\n {\n \tuint64_t ol_flags = 0;\n \tuint32_t packet_type = 0;\n@@ -324,7 +289,8 @@ static inline void ena_rx_mbuf_prepare(struct rte_mbuf *mbuf,\n \t\telse\n \t\t\tol_flags |= PKT_RX_L4_CKSUM_GOOD;\n \n-\tif (likely((packet_type & ENA_PTYPE_HAS_HASH) && !ena_rx_ctx->frag)) {\n+\tif (fill_hash &&\n+\t    likely((packet_type & ENA_PTYPE_HAS_HASH) && !ena_rx_ctx->frag)) {\n \t\tol_flags |= PKT_RX_RSS_HASH;\n \t\tmbuf->hash.rss = ena_rx_ctx->hash;\n \t}\n@@ -446,7 +412,8 @@ static void ena_config_host_info(struct ena_com_dev *ena_dev)\n \thost_info->num_cpus = rte_lcore_count();\n \n \thost_info->driver_supported_features =\n-\t\tENA_ADMIN_HOST_INFO_RX_OFFSET_MASK;\n+\t\tENA_ADMIN_HOST_INFO_RX_OFFSET_MASK |\n+\t\tENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK;\n \n \trc = ena_com_set_host_attributes(ena_dev);\n \tif (rc) {\n@@ -556,151 +523,6 @@ ena_dev_reset(struct rte_eth_dev *dev)\n \treturn rc;\n }\n \n-static int ena_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-\tstruct ena_adapter *adapter = dev->data->dev_private;\n-\tstruct ena_com_dev *ena_dev = &adapter->ena_dev;\n-\tint rc, i;\n-\tu16 entry_value;\n-\tint conf_idx;\n-\tint idx;\n-\n-\tif ((reta_size == 0) || (reta_conf == NULL))\n-\t\treturn -EINVAL;\n-\n-\tif (reta_size > ENA_RX_RSS_TABLE_SIZE) {\n-\t\tPMD_DRV_LOG(WARNING,\n-\t\t\t\"Requested indirection table size (%d) is bigger than supported: %d\\n\",\n-\t\t\treta_size, ENA_RX_RSS_TABLE_SIZE);\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tfor (i = 0 ; i < reta_size ; i++) {\n-\t\t/* each reta_conf is for 64 entries.\n-\t\t * to support 128 we use 2 conf of 64\n-\t\t */\n-\t\tconf_idx = i / RTE_RETA_GROUP_SIZE;\n-\t\tidx = i % RTE_RETA_GROUP_SIZE;\n-\t\tif (TEST_BIT(reta_conf[conf_idx].mask, idx)) {\n-\t\t\tentry_value =\n-\t\t\t\tENA_IO_RXQ_IDX(reta_conf[conf_idx].reta[idx]);\n-\n-\t\t\trc = ena_com_indirect_table_fill_entry(ena_dev,\n-\t\t\t\t\t\t\t       i,\n-\t\t\t\t\t\t\t       entry_value);\n-\t\t\tif (unlikely(rc && rc != ENA_COM_UNSUPPORTED)) {\n-\t\t\t\tPMD_DRV_LOG(ERR,\n-\t\t\t\t\t\"Cannot fill indirect table\\n\");\n-\t\t\t\treturn rc;\n-\t\t\t}\n-\t\t}\n-\t}\n-\n-\trte_spinlock_lock(&adapter->admin_lock);\n-\trc = ena_com_indirect_table_set(ena_dev);\n-\trte_spinlock_unlock(&adapter->admin_lock);\n-\tif (unlikely(rc && rc != ENA_COM_UNSUPPORTED)) {\n-\t\tPMD_DRV_LOG(ERR, \"Cannot flush the indirect table\\n\");\n-\t\treturn rc;\n-\t}\n-\n-\tPMD_DRV_LOG(DEBUG, \"RSS configured %d entries for port %d\\n\",\n-\t\treta_size, dev->data->port_id);\n-\n-\treturn 0;\n-}\n-\n-/* Query redirection table. */\n-static int ena_rss_reta_query(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-\tstruct ena_adapter *adapter = dev->data->dev_private;\n-\tstruct ena_com_dev *ena_dev = &adapter->ena_dev;\n-\tint rc;\n-\tint i;\n-\tu32 indirect_table[ENA_RX_RSS_TABLE_SIZE] = {0};\n-\tint reta_conf_idx;\n-\tint reta_idx;\n-\n-\tif (reta_size == 0 || reta_conf == NULL ||\n-\t    (reta_size > RTE_RETA_GROUP_SIZE && ((reta_conf + 1) == NULL)))\n-\t\treturn -EINVAL;\n-\n-\trte_spinlock_lock(&adapter->admin_lock);\n-\trc = ena_com_indirect_table_get(ena_dev, indirect_table);\n-\trte_spinlock_unlock(&adapter->admin_lock);\n-\tif (unlikely(rc && rc != ENA_COM_UNSUPPORTED)) {\n-\t\tPMD_DRV_LOG(ERR, \"Cannot get indirection table\\n\");\n-\t\treturn -ENOTSUP;\n-\t}\n-\n-\tfor (i = 0 ; i < reta_size ; i++) {\n-\t\treta_conf_idx = i / RTE_RETA_GROUP_SIZE;\n-\t\treta_idx = i % RTE_RETA_GROUP_SIZE;\n-\t\tif (TEST_BIT(reta_conf[reta_conf_idx].mask, reta_idx))\n-\t\t\treta_conf[reta_conf_idx].reta[reta_idx] =\n-\t\t\t\tENA_IO_RXQ_IDX_REV(indirect_table[i]);\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int ena_rss_init_default(struct ena_adapter *adapter)\n-{\n-\tstruct ena_com_dev *ena_dev = &adapter->ena_dev;\n-\tuint16_t nb_rx_queues = adapter->edev_data->nb_rx_queues;\n-\tint rc, i;\n-\tu32 val;\n-\n-\trc = ena_com_rss_init(ena_dev, ENA_RX_RSS_TABLE_LOG_SIZE);\n-\tif (unlikely(rc)) {\n-\t\tPMD_DRV_LOG(ERR, \"Cannot init indirection table\\n\");\n-\t\tgoto err_rss_init;\n-\t}\n-\n-\tfor (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) {\n-\t\tval = i % nb_rx_queues;\n-\t\trc = ena_com_indirect_table_fill_entry(ena_dev, i,\n-\t\t\t\t\t\t       ENA_IO_RXQ_IDX(val));\n-\t\tif (unlikely(rc && (rc != ENA_COM_UNSUPPORTED))) {\n-\t\t\tPMD_DRV_LOG(ERR, \"Cannot fill indirection table\\n\");\n-\t\t\tgoto err_fill_indir;\n-\t\t}\n-\t}\n-\n-\trc = ena_com_fill_hash_function(ena_dev, ENA_ADMIN_CRC32, NULL,\n-\t\t\t\t\tENA_HASH_KEY_SIZE, 0xFFFFFFFF);\n-\tif (unlikely(rc && (rc != ENA_COM_UNSUPPORTED))) {\n-\t\tPMD_DRV_LOG(INFO, \"Cannot fill hash function\\n\");\n-\t\tgoto err_fill_indir;\n-\t}\n-\n-\trc = ena_com_set_default_hash_ctrl(ena_dev);\n-\tif (unlikely(rc && (rc != ENA_COM_UNSUPPORTED))) {\n-\t\tPMD_DRV_LOG(INFO, \"Cannot fill hash control\\n\");\n-\t\tgoto err_fill_indir;\n-\t}\n-\n-\trc = ena_com_indirect_table_set(ena_dev);\n-\tif (unlikely(rc && (rc != ENA_COM_UNSUPPORTED))) {\n-\t\tPMD_DRV_LOG(ERR, \"Cannot flush indirection table\\n\");\n-\t\tgoto err_fill_indir;\n-\t}\n-\tPMD_DRV_LOG(DEBUG, \"RSS configured for port %d\\n\",\n-\t\tadapter->edev_data->port_id);\n-\n-\treturn 0;\n-\n-err_fill_indir:\n-\tena_com_rss_destroy(ena_dev);\n-err_rss_init:\n-\n-\treturn rc;\n-}\n-\n static void ena_rx_queue_release_all(struct rte_eth_dev *dev)\n {\n \tstruct ena_ring **queues = (struct ena_ring **)dev->data->rx_queues;\n@@ -1093,9 +915,8 @@ static int ena_start(struct rte_eth_dev *dev)\n \tif (rc)\n \t\tgoto err_start_tx;\n \n-\tif (adapter->edev_data->dev_conf.rxmode.mq_mode &\n-\t    ETH_MQ_RX_RSS_FLAG && adapter->edev_data->nb_rx_queues > 0) {\n-\t\trc = ena_rss_init_default(adapter);\n+\tif (adapter->edev_data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) {\n+\t\trc = ena_rss_configure(adapter);\n \t\tif (rc)\n \t\t\tgoto err_rss_init;\n \t}\n@@ -1385,7 +1206,7 @@ static int ena_rx_queue_setup(struct rte_eth_dev *dev,\n \t\t\t      uint16_t queue_idx,\n \t\t\t      uint16_t nb_desc,\n \t\t\t      unsigned int socket_id,\n-\t\t\t      __rte_unused const struct rte_eth_rxconf *rx_conf,\n+\t\t\t      const struct rte_eth_rxconf *rx_conf,\n \t\t\t      struct rte_mempool *mp)\n {\n \tstruct ena_adapter *adapter = dev->data->dev_private;\n@@ -1469,6 +1290,8 @@ static int ena_rx_queue_setup(struct rte_eth_dev *dev,\n \tfor (i = 0; i < nb_desc; i++)\n \t\trxq->empty_rx_reqs[i] = i;\n \n+\trxq->offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads;\n+\n \t/* Store pointer to this queue in upper layer */\n \trxq->configured = 1;\n \tdev->data->rx_queues[queue_idx] = rxq;\n@@ -1932,6 +1755,9 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)\n \tadapter->offloads.rx_csum_supported =\n \t\t(get_feat_ctx.offload.rx_supported &\n \t\tENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV4_CSUM_MASK) != 0;\n+\tadapter->offloads.rss_hash_supported =\n+\t\t(get_feat_ctx.offload.rx_supported &\n+\t\tENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_HASH_MASK) != 0;\n \n \t/* Copy MAC address and point DPDK to it */\n \teth_dev->data->mac_addrs = (struct rte_ether_addr *)adapter->mac_addr;\n@@ -1939,6 +1765,12 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)\n \t\t\tget_feat_ctx.dev_attr.mac_addr,\n \t\t\t(struct rte_ether_addr *)adapter->mac_addr);\n \n+\trc = ena_com_rss_init(ena_dev, ENA_RX_RSS_TABLE_LOG_SIZE);\n+\tif (unlikely(rc != 0)) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to initialize RSS in ENA device\\n\");\n+\t\tgoto err_delete_debug_area;\n+\t}\n+\n \tadapter->drv_stats = rte_zmalloc(\"adapter stats\",\n \t\t\t\t\t sizeof(*adapter->drv_stats),\n \t\t\t\t\t RTE_CACHE_LINE_SIZE);\n@@ -1946,7 +1778,7 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)\n \t\tPMD_DRV_LOG(ERR,\n \t\t\t\"Failed to allocate memory for adapter statistics\\n\");\n \t\trc = -ENOMEM;\n-\t\tgoto err_delete_debug_area;\n+\t\tgoto err_rss_destroy;\n \t}\n \n \trte_spinlock_init(&adapter->admin_lock);\n@@ -1967,6 +1799,8 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)\n \n \treturn 0;\n \n+err_rss_destroy:\n+\tena_com_rss_destroy(ena_dev);\n err_delete_debug_area:\n \tena_com_delete_debug_area(ena_dev);\n \n@@ -1991,6 +1825,8 @@ static void ena_destroy_device(struct rte_eth_dev *eth_dev)\n \tif (adapter->state != ENA_ADAPTER_STATE_CLOSED)\n \t\tena_close(eth_dev);\n \n+\tena_com_rss_destroy(ena_dev);\n+\n \tena_com_delete_debug_area(ena_dev);\n \tena_com_delete_host_info(ena_dev);\n \n@@ -2097,13 +1933,14 @@ static int ena_infos_get(struct rte_eth_dev *dev,\n \n \t/* Inform framework about available features */\n \tdev_info->rx_offload_capa = rx_feat;\n-\tdev_info->rx_offload_capa |= DEV_RX_OFFLOAD_RSS_HASH;\n+\tif (adapter->offloads.rss_hash_supported)\n+\t\tdev_info->rx_offload_capa |= DEV_RX_OFFLOAD_RSS_HASH;\n \tdev_info->rx_queue_offload_capa = rx_feat;\n \tdev_info->tx_offload_capa = tx_feat;\n \tdev_info->tx_queue_offload_capa = tx_feat;\n \n-\tdev_info->flow_type_rss_offloads = ETH_RSS_IP | ETH_RSS_TCP |\n-\t\t\t\t\t   ETH_RSS_UDP;\n+\tdev_info->flow_type_rss_offloads = ENA_ALL_RSS_HF;\n+\tdev_info->hash_key_size = ENA_HASH_KEY_SIZE;\n \n \tdev_info->min_rx_bufsize = ENA_MIN_FRAME_LEN;\n \tdev_info->max_rx_pktlen  = adapter->max_mtu;\n@@ -2250,6 +2087,7 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,\n \tuint16_t completed;\n \tstruct ena_com_rx_ctx ena_rx_ctx;\n \tint i, rc = 0;\n+\tbool fill_hash;\n \n #ifdef RTE_ETHDEV_DEBUG_RX\n \t/* Check adapter state */\n@@ -2260,6 +2098,8 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,\n \t}\n #endif\n \n+\tfill_hash = rx_ring->offloads & DEV_RX_OFFLOAD_RSS_HASH;\n+\n \tdescs_in_use = rx_ring->ring_size -\n \t\tena_com_free_q_entries(rx_ring->ena_com_io_sq) - 1;\n \tnb_pkts = RTE_MIN(descs_in_use, nb_pkts);\n@@ -2306,7 +2146,7 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,\n \t\t}\n \n \t\t/* fill mbuf attributes if any */\n-\t\tena_rx_mbuf_prepare(mbuf, &ena_rx_ctx);\n+\t\tena_rx_mbuf_prepare(mbuf, &ena_rx_ctx, fill_hash);\n \n \t\tif (unlikely(mbuf->ol_flags &\n \t\t\t\t(PKT_RX_IP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD))) {\ndiff --git a/drivers/net/ena/ena_ethdev.h b/drivers/net/ena/ena_ethdev.h\nindex 78718b759b..06ac8b06b5 100644\n--- a/drivers/net/ena/ena_ethdev.h\n+++ b/drivers/net/ena/ena_ethdev.h\n@@ -6,10 +6,16 @@\n #ifndef _ENA_ETHDEV_H_\n #define _ENA_ETHDEV_H_\n \n+#include <rte_atomic.h>\n+#include <rte_ether.h>\n+#include <ethdev_driver.h>\n+#include <ethdev_pci.h>\n #include <rte_cycles.h>\n #include <rte_pci.h>\n #include <rte_bus_pci.h>\n #include <rte_timer.h>\n+#include <rte_dev.h>\n+#include <rte_net.h>\n \n #include \"ena_com.h\"\n \n@@ -43,6 +49,21 @@\n #define ENA_IDX_NEXT_MASKED(idx, mask) (((idx) + 1) & (mask))\n #define ENA_IDX_ADD_MASKED(idx, n, mask) (((idx) + (n)) & (mask))\n \n+#define ENA_RX_RSS_TABLE_LOG_SIZE\t7\n+#define ENA_RX_RSS_TABLE_SIZE\t\t(1 << ENA_RX_RSS_TABLE_LOG_SIZE)\n+\n+#define ENA_HASH_KEY_SIZE\t\t40\n+\n+#define ENA_ALL_RSS_HF (ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_NONFRAG_IPV4_UDP | \\\n+\t\t\tETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_NONFRAG_IPV6_UDP)\n+\n+#define ENA_IO_TXQ_IDX(q)\t\t(2 * (q))\n+#define ENA_IO_RXQ_IDX(q)\t\t(2 * (q) + 1)\n+/* Reversed version of ENA_IO_RXQ_IDX */\n+#define ENA_IO_RXQ_IDX_REV(q)\t\t(((q) - 1) / 2)\n+\n+extern struct ena_shared_data *ena_shared_data;\n+\n struct ena_adapter;\n \n enum ena_ring_type {\n@@ -205,6 +226,7 @@ struct ena_offloads {\n \tbool tso4_supported;\n \tbool tx_csum_supported;\n \tbool rx_csum_supported;\n+\tbool rss_hash_supported;\n };\n \n /* board specific private data structure */\n@@ -268,4 +290,16 @@ struct ena_adapter {\n \tbool use_large_llq_hdr;\n };\n \n+int ena_rss_reta_update(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_rss_reta_entry64 *reta_conf,\n+\t\t\tuint16_t reta_size);\n+int ena_rss_reta_query(struct rte_eth_dev *dev,\n+\t\t       struct rte_eth_rss_reta_entry64 *reta_conf,\n+\t\t       uint16_t reta_size);\n+int ena_rss_hash_update(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_rss_conf *rss_conf);\n+int ena_rss_hash_conf_get(struct rte_eth_dev *dev,\n+\t\t\t  struct rte_eth_rss_conf *rss_conf);\n+int ena_rss_configure(struct ena_adapter *adapter);\n+\n #endif /* _ENA_ETHDEV_H_ */\ndiff --git a/drivers/net/ena/ena_rss.c b/drivers/net/ena/ena_rss.c\nnew file mode 100644\nindex 0000000000..88afe13da0\n--- /dev/null\n+++ b/drivers/net/ena/ena_rss.c\n@@ -0,0 +1,591 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright (c) 2020 Amazon.com, Inc. or its affiliates.\n+ * All rights reserved.\n+ */\n+\n+#include \"ena_ethdev.h\"\n+#include \"ena_logs.h\"\n+\n+#include <ena_admin_defs.h>\n+\n+#define TEST_BIT(val, bit_shift) ((val) & (1UL << (bit_shift)))\n+\n+#define ENA_HF_RSS_ALL_L2\t(ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA)\n+#define ENA_HF_RSS_ALL_L3\t(ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA)\n+#define ENA_HF_RSS_ALL_L4\t(ENA_ADMIN_RSS_L4_SP | ENA_ADMIN_RSS_L4_DP)\n+#define ENA_HF_RSS_ALL_L3_L4\t(ENA_HF_RSS_ALL_L3 | ENA_HF_RSS_ALL_L4)\n+#define ENA_HF_RSS_ALL_L2_L3_L4\t(ENA_HF_RSS_ALL_L2 | ENA_HF_RSS_ALL_L3_L4)\n+\n+enum ena_rss_hash_fields {\n+\tENA_HF_RSS_TCP4\t\t= ENA_HF_RSS_ALL_L3_L4,\n+\tENA_HF_RSS_UDP4\t\t= ENA_HF_RSS_ALL_L3_L4,\n+\tENA_HF_RSS_TCP6\t\t= ENA_HF_RSS_ALL_L3_L4,\n+\tENA_HF_RSS_UDP6\t\t= ENA_HF_RSS_ALL_L3_L4,\n+\tENA_HF_RSS_IP4\t\t= ENA_HF_RSS_ALL_L3,\n+\tENA_HF_RSS_IP6\t\t= ENA_HF_RSS_ALL_L3,\n+\tENA_HF_RSS_IP4_FRAG\t= ENA_HF_RSS_ALL_L3,\n+\tENA_HF_RSS_NOT_IP\t= ENA_HF_RSS_ALL_L2,\n+\tENA_HF_RSS_TCP6_EX\t= ENA_HF_RSS_ALL_L3_L4,\n+\tENA_HF_RSS_IP6_EX\t= ENA_HF_RSS_ALL_L3,\n+};\n+\n+static int ena_fill_indirect_table_default(struct ena_com_dev *ena_dev,\n+\t\t\t\t\t   size_t tbl_size,\n+\t\t\t\t\t   size_t queue_num);\n+static uint64_t ena_admin_hf_to_eth_hf(enum ena_admin_flow_hash_proto proto,\n+\t\t\t\t       uint16_t field);\n+static uint16_t ena_eth_hf_to_admin_hf(enum ena_admin_flow_hash_proto proto,\n+\t\t\t\t       uint64_t rss_hf);\n+static int ena_set_hash_fields(struct ena_com_dev *ena_dev, uint64_t rss_hf);\n+static int ena_rss_hash_set(struct ena_com_dev *ena_dev,\n+\t\t\t    struct rte_eth_rss_conf *rss_conf,\n+\t\t\t    bool default_allowed);\n+static void ena_reorder_rss_hash_key(uint8_t *reordered_key,\n+\t\t\t\t     uint8_t *key,\n+\t\t\t\t     size_t key_size);\n+static int ena_get_rss_hash_key(struct ena_com_dev *ena_dev, uint8_t *rss_key);\n+\n+void ena_rss_key_fill(void *key, size_t size)\n+{\n+\tstatic bool key_generated;\n+\tstatic uint8_t default_key[ENA_HASH_KEY_SIZE];\n+\tsize_t i;\n+\n+\tRTE_ASSERT(size <= ENA_HASH_KEY_SIZE);\n+\n+\tif (!key_generated) {\n+\t\tfor (i = 0; i < ENA_HASH_KEY_SIZE; ++i)\n+\t\t\tdefault_key[i] = rte_rand() & 0xff;\n+\t\tkey_generated = true;\n+\t}\n+\n+\trte_memcpy(key, default_key, size);\n+}\n+\n+int ena_rss_reta_update(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+\tstruct ena_adapter *adapter = dev->data->dev_private;\n+\tstruct ena_com_dev *ena_dev = &adapter->ena_dev;\n+\tint rc, i;\n+\tu16 entry_value;\n+\tint conf_idx;\n+\tint idx;\n+\n+\tif (reta_size == 0 || reta_conf == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (!(dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_RSS_HASH)) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\"RSS was not configured for the PMD\\n\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\tif (reta_size > ENA_RX_RSS_TABLE_SIZE) {\n+\t\tPMD_DRV_LOG(WARNING,\n+\t\t\t\"Requested indirection table size (%d) is bigger than supported: %d\\n\",\n+\t\t\treta_size, ENA_RX_RSS_TABLE_SIZE);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (i = 0 ; i < reta_size ; i++) {\n+\t\t/* Each reta_conf is for 64 entries.\n+\t\t * To support 128 we use 2 conf of 64.\n+\t\t */\n+\t\tconf_idx = i / RTE_RETA_GROUP_SIZE;\n+\t\tidx = i % RTE_RETA_GROUP_SIZE;\n+\t\tif (TEST_BIT(reta_conf[conf_idx].mask, idx)) {\n+\t\t\tentry_value =\n+\t\t\t\tENA_IO_RXQ_IDX(reta_conf[conf_idx].reta[idx]);\n+\n+\t\t\trc = ena_com_indirect_table_fill_entry(ena_dev, i,\n+\t\t\t\tentry_value);\n+\t\t\tif (unlikely(rc != 0)) {\n+\t\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t\t\"Cannot fill indirection table\\n\");\n+\t\t\t\treturn rc;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\trte_spinlock_lock(&adapter->admin_lock);\n+\trc = ena_com_indirect_table_set(ena_dev);\n+\trte_spinlock_unlock(&adapter->admin_lock);\n+\tif (unlikely(rc != 0)) {\n+\t\tPMD_DRV_LOG(ERR, \"Cannot set the indirection table\\n\");\n+\t\treturn rc;\n+\t}\n+\n+\tPMD_DRV_LOG(DEBUG, \"RSS configured %d entries for port %d\\n\",\n+\t\treta_size, dev->data->port_id);\n+\n+\treturn 0;\n+}\n+\n+/* Query redirection table. */\n+int ena_rss_reta_query(struct rte_eth_dev *dev,\n+\t\t       struct rte_eth_rss_reta_entry64 *reta_conf,\n+\t\t       uint16_t reta_size)\n+{\n+\tuint32_t indirect_table[ENA_RX_RSS_TABLE_SIZE] = { 0 };\n+\tstruct ena_adapter *adapter = dev->data->dev_private;\n+\tstruct ena_com_dev *ena_dev = &adapter->ena_dev;\n+\tint rc;\n+\tint i;\n+\tint reta_conf_idx;\n+\tint reta_idx;\n+\n+\tif (reta_size == 0 || reta_conf == NULL ||\n+\t    (reta_size > RTE_RETA_GROUP_SIZE && ((reta_conf + 1) == NULL)))\n+\t\treturn -EINVAL;\n+\n+\tif (!(dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_RSS_HASH)) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\"RSS was not configured for the PMD\\n\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\trte_spinlock_lock(&adapter->admin_lock);\n+\trc = ena_com_indirect_table_get(ena_dev, indirect_table);\n+\trte_spinlock_unlock(&adapter->admin_lock);\n+\tif (unlikely(rc != 0)) {\n+\t\tPMD_DRV_LOG(ERR, \"Cannot get indirection table\\n\");\n+\t\treturn rc;\n+\t}\n+\n+\tfor (i = 0 ; i < reta_size ; i++) {\n+\t\treta_conf_idx = i / RTE_RETA_GROUP_SIZE;\n+\t\treta_idx = i % RTE_RETA_GROUP_SIZE;\n+\t\tif (TEST_BIT(reta_conf[reta_conf_idx].mask, reta_idx))\n+\t\t\treta_conf[reta_conf_idx].reta[reta_idx] =\n+\t\t\t\tENA_IO_RXQ_IDX_REV(indirect_table[i]);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int ena_fill_indirect_table_default(struct ena_com_dev *ena_dev,\n+\t\t\t\t\t   size_t tbl_size,\n+\t\t\t\t\t   size_t queue_num)\n+{\n+\tsize_t i;\n+\tint rc;\n+\tuint16_t val;\n+\n+\tfor (i = 0; i < tbl_size; ++i) {\n+\t\tval = i % queue_num;\n+\t\trc = ena_com_indirect_table_fill_entry(ena_dev, i,\n+\t\t\tENA_IO_RXQ_IDX(val));\n+\t\tif (unlikely(rc != 0)) {\n+\t\t\tPMD_DRV_LOG(DEBUG,\n+\t\t\t\t\"Failed to set %zu indirection table entry with val %\" PRIu16 \"\\n\",\n+\t\t\t\ti, val);\n+\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static uint64_t ena_admin_hf_to_eth_hf(enum ena_admin_flow_hash_proto proto,\n+\t\t\t\t       uint16_t fields)\n+{\n+\tuint64_t rss_hf = 0;\n+\n+\t/* If no fields are activated, then RSS is disabled for this proto */\n+\tif ((fields & ENA_HF_RSS_ALL_L2_L3_L4) == 0)\n+\t\treturn 0;\n+\n+\t/* Convert proto to ETH flag */\n+\tswitch (proto) {\n+\tcase ENA_ADMIN_RSS_TCP4:\n+\t\trss_hf |= ETH_RSS_NONFRAG_IPV4_TCP;\n+\t\tbreak;\n+\tcase ENA_ADMIN_RSS_UDP4:\n+\t\trss_hf |= ETH_RSS_NONFRAG_IPV4_UDP;\n+\t\tbreak;\n+\tcase ENA_ADMIN_RSS_TCP6:\n+\t\trss_hf |= ETH_RSS_NONFRAG_IPV6_TCP;\n+\t\tbreak;\n+\tcase ENA_ADMIN_RSS_UDP6:\n+\t\trss_hf |= ETH_RSS_NONFRAG_IPV6_UDP;\n+\t\tbreak;\n+\tcase ENA_ADMIN_RSS_IP4:\n+\t\trss_hf |= ETH_RSS_IPV4;\n+\t\tbreak;\n+\tcase ENA_ADMIN_RSS_IP6:\n+\t\trss_hf |= ETH_RSS_IPV6;\n+\t\tbreak;\n+\tcase ENA_ADMIN_RSS_IP4_FRAG:\n+\t\trss_hf |= ETH_RSS_FRAG_IPV4;\n+\t\tbreak;\n+\tcase ENA_ADMIN_RSS_NOT_IP:\n+\t\trss_hf |= ETH_RSS_L2_PAYLOAD;\n+\t\tbreak;\n+\tcase ENA_ADMIN_RSS_TCP6_EX:\n+\t\trss_hf |= ETH_RSS_IPV6_TCP_EX;\n+\t\tbreak;\n+\tcase ENA_ADMIN_RSS_IP6_EX:\n+\t\trss_hf |= ETH_RSS_IPV6_EX;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t};\n+\n+\t/* Check if only DA or SA is being used for L3. */\n+\tswitch (fields & ENA_HF_RSS_ALL_L3) {\n+\tcase ENA_ADMIN_RSS_L3_SA:\n+\t\trss_hf |= ETH_RSS_L3_SRC_ONLY;\n+\t\tbreak;\n+\tcase ENA_ADMIN_RSS_L3_DA:\n+\t\trss_hf |= ETH_RSS_L3_DST_ONLY;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t};\n+\n+\t/* Check if only DA or SA is being used for L4. */\n+\tswitch (fields & ENA_HF_RSS_ALL_L4) {\n+\tcase ENA_ADMIN_RSS_L4_SP:\n+\t\trss_hf |= ETH_RSS_L4_SRC_ONLY;\n+\t\tbreak;\n+\tcase ENA_ADMIN_RSS_L4_DP:\n+\t\trss_hf |= ETH_RSS_L4_DST_ONLY;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t};\n+\n+\treturn rss_hf;\n+}\n+\n+static uint16_t ena_eth_hf_to_admin_hf(enum ena_admin_flow_hash_proto proto,\n+\t\t\t\t       uint64_t rss_hf)\n+{\n+\tuint16_t fields_mask = 0;\n+\n+\t/* L2 always uses source and destination addresses. */\n+\tfields_mask = ENA_ADMIN_RSS_L2_DA | ENA_ADMIN_RSS_L2_SA;\n+\n+\t/* Determine which fields of L3 should be used. */\n+\tswitch (rss_hf & (ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY)) {\n+\tcase ETH_RSS_L3_DST_ONLY:\n+\t\tfields_mask |= ENA_ADMIN_RSS_L3_DA;\n+\t\tbreak;\n+\tcase ETH_RSS_L3_SRC_ONLY:\n+\t\tfields_mask |= ENA_ADMIN_RSS_L3_SA;\n+\t\tbreak;\n+\tdefault:\n+\t\t/*\n+\t\t * If SRC nor DST aren't set, it means both of them should be\n+\t\t * used.\n+\t\t */\n+\t\tfields_mask |= ENA_HF_RSS_ALL_L3;\n+\t}\n+\n+\t/* Determine which fields of L4 should be used. */\n+\tswitch (rss_hf & (ETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY)) {\n+\tcase ETH_RSS_L4_DST_ONLY:\n+\t\tfields_mask |= ENA_ADMIN_RSS_L4_DP;\n+\t\tbreak;\n+\tcase ETH_RSS_L4_SRC_ONLY:\n+\t\tfields_mask |= ENA_ADMIN_RSS_L4_SP;\n+\t\tbreak;\n+\tdefault:\n+\t\t/*\n+\t\t * If SRC nor DST aren't set, it means both of them should be\n+\t\t * used.\n+\t\t */\n+\t\tfields_mask |= ENA_HF_RSS_ALL_L4;\n+\t}\n+\n+\t/* Return appropriate hash fields. */\n+\tswitch (proto) {\n+\tcase ENA_ADMIN_RSS_TCP4:\n+\t\treturn ENA_HF_RSS_TCP4 & fields_mask;\n+\tcase ENA_ADMIN_RSS_UDP4:\n+\t\treturn ENA_HF_RSS_UDP4 & fields_mask;\n+\tcase ENA_ADMIN_RSS_TCP6:\n+\t\treturn ENA_HF_RSS_TCP6 & fields_mask;\n+\tcase ENA_ADMIN_RSS_UDP6:\n+\t\treturn ENA_HF_RSS_UDP6 & fields_mask;\n+\tcase ENA_ADMIN_RSS_IP4:\n+\t\treturn ENA_HF_RSS_IP4 & fields_mask;\n+\tcase ENA_ADMIN_RSS_IP6:\n+\t\treturn ENA_HF_RSS_IP6 & fields_mask;\n+\tcase ENA_ADMIN_RSS_IP4_FRAG:\n+\t\treturn ENA_HF_RSS_IP4_FRAG & fields_mask;\n+\tcase ENA_ADMIN_RSS_NOT_IP:\n+\t\treturn ENA_HF_RSS_NOT_IP & fields_mask;\n+\tcase ENA_ADMIN_RSS_TCP6_EX:\n+\t\treturn ENA_HF_RSS_TCP6_EX & fields_mask;\n+\tcase ENA_ADMIN_RSS_IP6_EX:\n+\t\treturn ENA_HF_RSS_IP6_EX & fields_mask;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int ena_set_hash_fields(struct ena_com_dev *ena_dev, uint64_t rss_hf)\n+{\n+\tstruct ena_admin_proto_input selected_fields[ENA_ADMIN_RSS_PROTO_NUM] = {};\n+\tint rc, i;\n+\n+\t/* Turn on appropriate fields for each requested packet type */\n+\tif ((rss_hf & ETH_RSS_NONFRAG_IPV4_TCP) != 0)\n+\t\tselected_fields[ENA_ADMIN_RSS_TCP4].fields =\n+\t\t\tena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_TCP4, rss_hf);\n+\n+\tif ((rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) != 0)\n+\t\tselected_fields[ENA_ADMIN_RSS_UDP4].fields =\n+\t\t\tena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_UDP4, rss_hf);\n+\n+\tif ((rss_hf & ETH_RSS_NONFRAG_IPV6_TCP) != 0)\n+\t\tselected_fields[ENA_ADMIN_RSS_TCP6].fields =\n+\t\t\tena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_TCP6, rss_hf);\n+\n+\tif ((rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) != 0)\n+\t\tselected_fields[ENA_ADMIN_RSS_UDP6].fields =\n+\t\t\tena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_UDP6, rss_hf);\n+\n+\tif ((rss_hf & ETH_RSS_IPV4) != 0)\n+\t\tselected_fields[ENA_ADMIN_RSS_IP4].fields =\n+\t\t\tena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_IP4, rss_hf);\n+\n+\tif ((rss_hf & ETH_RSS_IPV6) != 0)\n+\t\tselected_fields[ENA_ADMIN_RSS_IP6].fields =\n+\t\t\tena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_IP6, rss_hf);\n+\n+\tif ((rss_hf & ETH_RSS_FRAG_IPV4) != 0)\n+\t\tselected_fields[ENA_ADMIN_RSS_IP4_FRAG].fields =\n+\t\t\tena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_IP4_FRAG, rss_hf);\n+\n+\tif ((rss_hf & ETH_RSS_L2_PAYLOAD) != 0)\n+\t\tselected_fields[ENA_ADMIN_RSS_NOT_IP].fields =\n+\t\t\tena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_NOT_IP, rss_hf);\n+\n+\tif ((rss_hf & ETH_RSS_IPV6_TCP_EX) != 0)\n+\t\tselected_fields[ENA_ADMIN_RSS_TCP6_EX].fields =\n+\t\t\tena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_TCP6_EX, rss_hf);\n+\n+\tif ((rss_hf & ETH_RSS_IPV6_EX) != 0)\n+\t\tselected_fields[ENA_ADMIN_RSS_IP6_EX].fields =\n+\t\t\tena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_IP6_EX, rss_hf);\n+\n+\t/* Try to write them to the device */\n+\tfor (i = 0; i < ENA_ADMIN_RSS_PROTO_NUM; i++) {\n+\t\trc = ena_com_fill_hash_ctrl(ena_dev,\n+\t\t\t(enum ena_admin_flow_hash_proto)i,\n+\t\t\tselected_fields[i].fields);\n+\t\tif (unlikely(rc != 0)) {\n+\t\t\tPMD_DRV_LOG(DEBUG,\n+\t\t\t\t\"Failed to set ENA HF %d with fields %\" PRIu16 \"\\n\",\n+\t\t\t\ti, selected_fields[i].fields);\n+\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int ena_rss_hash_set(struct ena_com_dev *ena_dev,\n+\t\t\t    struct rte_eth_rss_conf *rss_conf,\n+\t\t\t    bool default_allowed)\n+{\n+\tuint8_t hw_rss_key[ENA_HASH_KEY_SIZE];\n+\tuint8_t *rss_key;\n+\tint rc;\n+\n+\tif (rss_conf->rss_key != NULL) {\n+\t\t/* Reorder the RSS key bytes for the hardware requirements. */\n+\t\tena_reorder_rss_hash_key(hw_rss_key, rss_conf->rss_key,\n+\t\t\tENA_HASH_KEY_SIZE);\n+\t\trss_key = hw_rss_key;\n+\t} else {\n+\t\trss_key = NULL;\n+\t}\n+\n+\t/* If the rss_key is NULL, then the randomized key will be used. */\n+\trc = ena_com_fill_hash_function(ena_dev, ENA_ADMIN_TOEPLITZ,\n+\t\trss_key, ENA_HASH_KEY_SIZE, 0);\n+\tif (rc != 0 && !(default_allowed && rc == ENA_COM_UNSUPPORTED)) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\"Failed to set RSS hash function in the device\\n\");\n+\t\treturn rc;\n+\t}\n+\n+\trc = ena_set_hash_fields(ena_dev, rss_conf->rss_hf);\n+\tif (rc == ENA_COM_UNSUPPORTED) {\n+\t\tif (rss_conf->rss_key == NULL && !default_allowed) {\n+\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t\"Setting RSS hash fields is not supported\\n\");\n+\t\t\treturn -ENOTSUP;\n+\t\t}\n+\t\tPMD_DRV_LOG(WARNING,\n+\t\t\t\"Setting RSS hash fields is not supported. Using default values: 0x%\" PRIx64 \"\\n\",\n+\t\t\t(uint64_t)(ENA_ALL_RSS_HF));\n+\t} else if (rc != 0)  {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to set RSS hash fields\\n\");\n+\t\treturn rc;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/* ENA HW interprets the RSS key in reverse bytes order. Because of that, the\n+ * key must be processed upon interaction with ena_com layer.\n+ */\n+static void ena_reorder_rss_hash_key(uint8_t *reordered_key,\n+\t\t\t\t     uint8_t *key,\n+\t\t\t\t     size_t key_size)\n+{\n+\tsize_t i, rev_i;\n+\n+\tfor (i = 0, rev_i = key_size - 1; i < key_size; ++i, --rev_i)\n+\t\treordered_key[i] = key[rev_i];\n+}\n+\n+static int ena_get_rss_hash_key(struct ena_com_dev *ena_dev, uint8_t *rss_key)\n+{\n+\tuint8_t hw_rss_key[ENA_HASH_KEY_SIZE];\n+\tint rc;\n+\n+\t/* The default RSS hash key cannot be retrieved from the HW. Unless it's\n+\t * explicitly set, this operation shouldn't be supported.\n+\t */\n+\tif (ena_dev->rss.hash_key == NULL) {\n+\t\tPMD_DRV_LOG(WARNING,\n+\t\t\t\"Retrieving default RSS hash key is not supported\\n\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\trc = ena_com_get_hash_key(ena_dev, hw_rss_key);\n+\tif (rc != 0)\n+\t\treturn rc;\n+\n+\tena_reorder_rss_hash_key(rss_key, hw_rss_key, ENA_HASH_KEY_SIZE);\n+\n+\treturn 0;\n+}\n+\n+int ena_rss_configure(struct ena_adapter *adapter)\n+{\n+\tstruct rte_eth_rss_conf *rss_conf;\n+\tstruct ena_com_dev *ena_dev;\n+\tint rc;\n+\n+\tena_dev = &adapter->ena_dev;\n+\trss_conf = &adapter->edev_data->dev_conf.rx_adv_conf.rss_conf;\n+\n+\tif (adapter->edev_data->nb_rx_queues == 0)\n+\t\treturn 0;\n+\n+\t/* Restart the indirection table. The number of queues could change\n+\t * between start/stop calls, so it must be reinitialized with default\n+\t * values.\n+\t */\n+\trc = ena_fill_indirect_table_default(ena_dev, ENA_RX_RSS_TABLE_SIZE,\n+\t\tadapter->edev_data->nb_rx_queues);\n+\tif (unlikely(rc != 0)) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\"Failed to fill indirection table with default values\\n\");\n+\t\treturn rc;\n+\t}\n+\n+\trc = ena_com_indirect_table_set(ena_dev);\n+\tif (unlikely(rc != 0 && rc != ENA_COM_UNSUPPORTED)) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\"Failed to set indirection table in the device\\n\");\n+\t\treturn rc;\n+\t}\n+\n+\trc = ena_rss_hash_set(ena_dev, rss_conf, true);\n+\tif (unlikely(rc != 0)) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to set RSS hash\\n\");\n+\t\treturn rc;\n+\t}\n+\n+\tPMD_DRV_LOG(DEBUG, \"RSS configured for port %d\\n\",\n+\t\tadapter->edev_data->port_id);\n+\n+\treturn 0;\n+}\n+\n+int ena_rss_hash_update(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_rss_conf *rss_conf)\n+{\n+\tstruct ena_adapter *adapter = dev->data->dev_private;\n+\tint rc;\n+\n+\trte_spinlock_lock(&adapter->admin_lock);\n+\trc = ena_rss_hash_set(&adapter->ena_dev, rss_conf, false);\n+\trte_spinlock_unlock(&adapter->admin_lock);\n+\tif (unlikely(rc != 0)) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to set RSS hash\\n\");\n+\t\treturn rc;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int ena_rss_hash_conf_get(struct rte_eth_dev *dev,\n+\t\t\t  struct rte_eth_rss_conf *rss_conf)\n+{\n+\tstruct ena_adapter *adapter = dev->data->dev_private;\n+\tstruct ena_com_dev *ena_dev = &adapter->ena_dev;\n+\tenum ena_admin_flow_hash_proto proto;\n+\tuint64_t rss_hf = 0;\n+\tint rc, i;\n+\tuint16_t admin_hf;\n+\tstatic bool warn_once;\n+\n+\tif (!(dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_RSS_HASH)) {\n+\t\tPMD_DRV_LOG(ERR, \"RSS was not configured for the PMD\\n\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\tif (rss_conf->rss_key != NULL) {\n+\t\trc = ena_get_rss_hash_key(ena_dev, rss_conf->rss_key);\n+\t\tif (unlikely(rc != 0)) {\n+\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t\"Cannot retrieve RSS hash key, err: %d\\n\",\n+\t\t\t\trc);\n+\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n+\tfor (i = 0; i < ENA_ADMIN_RSS_PROTO_NUM; ++i) {\n+\t\tproto = (enum ena_admin_flow_hash_proto)i;\n+\t\trte_spinlock_lock(&adapter->admin_lock);\n+\t\trc = ena_com_get_hash_ctrl(ena_dev, proto, &admin_hf);\n+\t\trte_spinlock_unlock(&adapter->admin_lock);\n+\t\tif (rc == ENA_COM_UNSUPPORTED) {\n+\t\t\t/* As some devices may support only reading rss hash\n+\t\t\t * key and not the hash ctrl, we want to notify the\n+\t\t\t * caller that this feature is only partially supported\n+\t\t\t * and do not return an error - the caller could be\n+\t\t\t * interested only in the key value.\n+\t\t\t */\n+\t\t\tif (!warn_once) {\n+\t\t\t\tPMD_DRV_LOG(WARNING,\n+\t\t\t\t\t\"Reading hash control from the device is not supported. .rss_hf will contain a default value.\\n\");\n+\t\t\t\twarn_once = true;\n+\t\t\t}\n+\t\t\trss_hf = ENA_ALL_RSS_HF;\n+\t\t\tbreak;\n+\t\t} else if (rc != 0) {\n+\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t\"Failed to retrieve hash ctrl for proto: %d with err: %d\\n\",\n+\t\t\t\ti, rc);\n+\t\t\treturn rc;\n+\t\t}\n+\n+\t\trss_hf |= ena_admin_hf_to_eth_hf(proto, admin_hf);\n+\t}\n+\n+\trss_conf->rss_hf = rss_hf;\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ena/meson.build b/drivers/net/ena/meson.build\nindex cc912fceba..d02ed3f64f 100644\n--- a/drivers/net/ena/meson.build\n+++ b/drivers/net/ena/meson.build\n@@ -9,6 +9,7 @@ endif\n \n sources = files(\n         'ena_ethdev.c',\n+        'ena_rss.c',\n         'base/ena_com.c',\n         'base/ena_eth_com.c',\n )\n",
    "prefixes": [
        "v4",
        "5/6"
    ]
}