[10/21] net/ena: proxy AQ calls to primary process

Message ID 20220222160634.24489-11-mk@semihalf.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series net/ena: v2.6.0 driver update |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Michal Krawczyk Feb. 22, 2022, 4:06 p.m. UTC
  From: Stanislaw Kardach <kda@semihalf.com>

Due to how the ena_com compatibility layer is written, all AQ commands
triggering functions use stack to save results of AQ and then copy them
to user given function.
Therefore to keep the compatibility layer common, introduce ENA_PROXY
macro. It either calls the wrapped function directly (in primary
process) or proxies it to the primary via DPDK IPC mechanism. Since all
proxied calls are taken under a lock share the result data through
shared memory (in struct ena_adapter) to work around 256B IPC parameter
size limit.

New proxy calls can be added by
1. Adding a new message type at the end of enum ena_mp_req
2. Adding new message arguments to the struct ena_mp_body if needed
3. Defining proxy request descriptor with ENA_PROXY_DESC. Its arguments
   include handlers for request preparation and response processing.
   Any of those may be empty (aside of marking arguments as used).
4. Adding request handling logic to ena_mp_primary_handle()
5. Replacing proxied function calls with ENA_PROXY(adapter, <func>, ...)

Signed-off-by: Stanislaw Kardach <kda@semihalf.com>
Reviewed-by: Michal Krawczyk <mk@semihalf.com>
Reviewed-by: Dawid Gorecki <dgr@semihalf.com>
Reviewed-by: Shai Brandes <shaibran@amazon.com>
---
 doc/guides/rel_notes/release_22_03.rst |   1 +
 drivers/net/ena/ena_ethdev.c           | 384 ++++++++++++++++++++++++-
 drivers/net/ena/ena_ethdev.h           |   9 +
 drivers/net/ena/ena_rss.c              |  10 +-
 4 files changed, 384 insertions(+), 20 deletions(-)
  

Patch

diff --git a/doc/guides/rel_notes/release_22_03.rst b/doc/guides/rel_notes/release_22_03.rst
index 9c7e246348..92f36fa8ab 100644
--- a/doc/guides/rel_notes/release_22_03.rst
+++ b/doc/guides/rel_notes/release_22_03.rst
@@ -113,6 +113,7 @@  New Features
     ``l4_csum_good``.
   * Added support for the link status configuration.
   * Added optimized memcpy support for the ARM platforms.
+  * Added ENA admin queue support for the MP applications.
 
 * **Updated Cisco enic driver.**
 
diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
index ed3dd162ba..bb532923b6 100644
--- a/drivers/net/ena/ena_ethdev.c
+++ b/drivers/net/ena/ena_ethdev.c
@@ -242,13 +242,16 @@  static int ena_process_bool_devarg(const char *key,
 				   void *opaque);
 static int ena_parse_devargs(struct ena_adapter *adapter,
 			     struct rte_devargs *devargs);
-static int ena_copy_eni_stats(struct ena_adapter *adapter);
+static int ena_copy_eni_stats(struct ena_adapter *adapter,
+			      struct ena_stats_eni *stats);
 static int ena_setup_rx_intr(struct rte_eth_dev *dev);
 static int ena_rx_queue_intr_enable(struct rte_eth_dev *dev,
 				    uint16_t queue_id);
 static int ena_rx_queue_intr_disable(struct rte_eth_dev *dev,
 				     uint16_t queue_id);
 static int ena_configure_aenq(struct ena_adapter *adapter);
+static int ena_mp_primary_handle(const struct rte_mp_msg *mp_msg,
+				 const void *peer);
 
 static const struct eth_dev_ops ena_dev_ops = {
 	.dev_configure        = ena_dev_configure,
@@ -275,6 +278,261 @@  static const struct eth_dev_ops ena_dev_ops = {
 	.rss_hash_conf_get    = ena_rss_hash_conf_get,
 };
 
+/*********************************************************************
+ *  Multi-Process communication bits
+ *********************************************************************/
+/* rte_mp IPC message name */
+#define ENA_MP_NAME	"net_ena_mp"
+/* Request timeout in seconds */
+#define ENA_MP_REQ_TMO	5
+
+/** Proxy request type */
+enum ena_mp_req {
+	ENA_MP_DEV_STATS_GET,
+	ENA_MP_ENI_STATS_GET,
+	ENA_MP_MTU_SET,
+	ENA_MP_IND_TBL_GET,
+	ENA_MP_IND_TBL_SET
+};
+
+/** Proxy message body. Shared between requests and responses. */
+struct ena_mp_body {
+	/* Message type */
+	enum ena_mp_req type;
+	int port_id;
+	/* Processing result. Set in replies. 0 if message succeeded, negative
+	 * error code otherwise.
+	 */
+	int result;
+	union {
+		int mtu; /* For ENA_MP_MTU_SET */
+	} args;
+};
+
+/**
+ * Initialize IPC message.
+ *
+ * @param[out] msg
+ *   Pointer to the message to initialize.
+ * @param[in] type
+ *   Message type.
+ * @param[in] port_id
+ *   Port ID of target device.
+ *
+ */
+static void
+mp_msg_init(struct rte_mp_msg *msg, enum ena_mp_req type, int port_id)
+{
+	struct ena_mp_body *body = (struct ena_mp_body *)&msg->param;
+
+	memset(msg, 0, sizeof(*msg));
+	strlcpy(msg->name, ENA_MP_NAME, sizeof(msg->name));
+	msg->len_param = sizeof(*body);
+	body->type = type;
+	body->port_id = port_id;
+}
+
+/*********************************************************************
+ *  Multi-Process communication PMD API
+ *********************************************************************/
+/**
+ * Define proxy request descriptor
+ *
+ * Used to define all structures and functions required for proxying a given
+ * function to the primary process including the code to perform to prepare the
+ * request and process the response.
+ *
+ * @param[in] f
+ *   Name of the function to proxy
+ * @param[in] t
+ *   Message type to use
+ * @param[in] prep
+ *   Body of a function to prepare the request in form of a statement
+ *   expression. It is passed all the original function arguments along with two
+ *   extra ones:
+ *   - struct ena_adapter *adapter - PMD data of the device calling the proxy.
+ *   - struct ena_mp_body *req - body of a request to prepare.
+ * @param[in] proc
+ *   Body of a function to process the response in form of a statement
+ *   expression. It is passed all the original function arguments along with two
+ *   extra ones:
+ *   - struct ena_adapter *adapter - PMD data of the device calling the proxy.
+ *   - struct ena_mp_body *rsp - body of a response to process.
+ * @param ...
+ *   Proxied function's arguments
+ *
+ * @note Inside prep and proc any parameters which aren't used should be marked
+ *       as such (with ENA_TOUCH or __rte_unused).
+ */
+#define ENA_PROXY_DESC(f, t, prep, proc, ...)			\
+	static const enum ena_mp_req mp_type_ ## f =  t;	\
+	static const char *mp_name_ ## f = #t;			\
+	static void mp_prep_ ## f(struct ena_adapter *adapter,	\
+				  struct ena_mp_body *req,	\
+				  __VA_ARGS__)			\
+	{							\
+		prep;						\
+	}							\
+	static void mp_proc_ ## f(struct ena_adapter *adapter,	\
+				  struct ena_mp_body *rsp,	\
+				  __VA_ARGS__)			\
+	{							\
+		proc;						\
+	}
+
+/**
+ * Proxy wrapper for calling primary functions in a secondary process.
+ *
+ * Depending on whether called in primary or secondary process, calls the
+ * @p func directly or proxies the call to the primary process via rte_mp IPC.
+ * This macro requires a proxy request descriptor to be defined for @p func
+ * using ENA_PROXY_DESC() macro.
+ *
+ * @param[in/out] a
+ *   Device PMD data. Used for sending the message and sharing message results
+ *   between primary and secondary.
+ * @param[in] f
+ *   Function to proxy.
+ * @param ...
+ *   Arguments of @p func.
+ *
+ * @return
+ *   - 0: Processing succeeded and response handler was called.
+ *   - -EPERM: IPC is unavailable on this platform. This means only primary
+ *             process may call the proxied function.
+ *   - -ECOMM: IPC returned error on request send. Inspect rte_errno detailed
+ *             error code.
+ *   - Negative error code from the proxied function.
+ *
+ * @note This mechanism is geared towards control-path tasks. Avoid calling it
+ *       in fast-path unless unbound delays are allowed. This is due to the IPC
+ *       mechanism itself (socket based).
+ * @note Due to IPC parameter size limitations the proxy logic shares call
+ *       results through the struct ena_adapter shared memory. This makes the
+ *       proxy mechanism strictly single-threaded. Therefore be sure to make all
+ *       calls to the same proxied function under the same lock.
+ */
+#define ENA_PROXY(a, f, ...)						\
+({									\
+	struct ena_adapter *_a = (a);					\
+	struct timespec ts = { .tv_sec = ENA_MP_REQ_TMO };		\
+	struct ena_mp_body *req, *rsp;					\
+	struct rte_mp_reply mp_rep;					\
+	struct rte_mp_msg mp_req;					\
+	int ret;							\
+									\
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {		\
+		ret = f(__VA_ARGS__);					\
+	} else {							\
+		/* Prepare and send request */				\
+		req = (struct ena_mp_body *)&mp_req.param;		\
+		mp_msg_init(&mp_req, mp_type_ ## f, _a->edev_data->port_id); \
+		mp_prep_ ## f(_a, req, ## __VA_ARGS__);			\
+									\
+		ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);	\
+		if (likely(!ret)) {					\
+			RTE_ASSERT(mp_rsp.nb_received == 1);		\
+			rsp = (struct ena_mp_body *)&mp_rep.msgs[0].param; \
+			ret = rsp->result;				\
+			if (ret == 0) {					\
+				mp_proc_##f(_a, rsp, ## __VA_ARGS__);	\
+			} else {					\
+				PMD_DRV_LOG(ERR,			\
+					    "%s returned error: %d\n",	\
+					    mp_name_ ## f, rsp->result);\
+			}						\
+			free(mp_rep.msgs);				\
+		} else if (rte_errno == ENOTSUP) {			\
+			PMD_DRV_LOG(ERR,				\
+				    "No IPC, can't proxy to primary\n");\
+			ret = -rte_errno;				\
+		} else {						\
+			PMD_DRV_LOG(ERR, "Request %s failed: %s\n",	\
+				    mp_name_ ## f,			\
+				    rte_strerror(rte_errno));		\
+			ret = -ECOMM;					\
+		}							\
+	}								\
+	ret;								\
+})
+
+/*********************************************************************
+ *  Multi-Process communication request descriptors
+ *********************************************************************/
+
+ENA_PROXY_DESC(ena_com_get_dev_basic_stats, ENA_MP_DEV_STATS_GET,
+({
+	ENA_TOUCH(adapter);
+	ENA_TOUCH(req);
+	ENA_TOUCH(ena_dev);
+	ENA_TOUCH(stats);
+}),
+({
+	ENA_TOUCH(rsp);
+	ENA_TOUCH(ena_dev);
+	if (stats != &adapter->basic_stats)
+		rte_memcpy(stats, &adapter->basic_stats, sizeof(*stats));
+}),
+	struct ena_com_dev *ena_dev, struct ena_admin_basic_stats *stats);
+
+ENA_PROXY_DESC(ena_com_get_eni_stats, ENA_MP_ENI_STATS_GET,
+({
+	ENA_TOUCH(adapter);
+	ENA_TOUCH(req);
+	ENA_TOUCH(ena_dev);
+	ENA_TOUCH(stats);
+}),
+({
+	ENA_TOUCH(rsp);
+	ENA_TOUCH(ena_dev);
+	if (stats != (struct ena_admin_eni_stats *)&adapter->eni_stats)
+		rte_memcpy(stats, &adapter->eni_stats, sizeof(*stats));
+}),
+	struct ena_com_dev *ena_dev, struct ena_admin_eni_stats *stats);
+
+ENA_PROXY_DESC(ena_com_set_dev_mtu, ENA_MP_MTU_SET,
+({
+	ENA_TOUCH(adapter);
+	ENA_TOUCH(ena_dev);
+	req->args.mtu = mtu;
+}),
+({
+	ENA_TOUCH(adapter);
+	ENA_TOUCH(rsp);
+	ENA_TOUCH(ena_dev);
+	ENA_TOUCH(mtu);
+}),
+	struct ena_com_dev *ena_dev, int mtu);
+
+ENA_PROXY_DESC(ena_com_indirect_table_set, ENA_MP_IND_TBL_SET,
+({
+	ENA_TOUCH(adapter);
+	ENA_TOUCH(req);
+	ENA_TOUCH(ena_dev);
+}),
+({
+	ENA_TOUCH(adapter);
+	ENA_TOUCH(rsp);
+	ENA_TOUCH(ena_dev);
+}),
+	struct ena_com_dev *ena_dev);
+
+ENA_PROXY_DESC(ena_com_indirect_table_get, ENA_MP_IND_TBL_GET,
+({
+	ENA_TOUCH(adapter);
+	ENA_TOUCH(req);
+	ENA_TOUCH(ena_dev);
+	ENA_TOUCH(ind_tbl);
+}),
+({
+	ENA_TOUCH(rsp);
+	ENA_TOUCH(ena_dev);
+	if (ind_tbl != adapter->indirect_table)
+		rte_memcpy(ind_tbl, adapter->indirect_table,
+			   sizeof(adapter->indirect_table));
+}),
+	struct ena_com_dev *ena_dev, u32 *ind_tbl);
+
 static inline void ena_rx_mbuf_prepare(struct ena_ring *rx_ring,
 				       struct rte_mbuf *mbuf,
 				       struct ena_com_rx_ctx *ena_rx_ctx,
@@ -816,7 +1074,8 @@  static int ena_stats_get(struct rte_eth_dev *dev,
 	memset(&ena_stats, 0, sizeof(ena_stats));
 
 	rte_spinlock_lock(&adapter->admin_lock);
-	rc = ena_com_get_dev_basic_stats(ena_dev, &ena_stats);
+	rc = ENA_PROXY(adapter, ena_com_get_dev_basic_stats, ena_dev,
+		       &ena_stats);
 	rte_spinlock_unlock(&adapter->admin_lock);
 	if (unlikely(rc)) {
 		PMD_DRV_LOG(ERR, "Could not retrieve statistics from ENA\n");
@@ -882,7 +1141,7 @@  static int ena_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 		return -EINVAL;
 	}
 
-	rc = ena_com_set_dev_mtu(ena_dev, mtu);
+	rc = ENA_PROXY(adapter, ena_com_set_dev_mtu, ena_dev, mtu);
 	if (rc)
 		PMD_DRV_LOG(ERR, "Could not set MTU: %d\n", mtu);
 	else
@@ -1782,6 +2041,24 @@  ena_set_offloads(struct ena_offloads *offloads,
 		offloads->rx_offloads |= ENA_RX_RSS_HASH;
 }
 
+static int ena_init_once(void)
+{
+	static bool init_done;
+
+	if (init_done)
+		return 0;
+
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		/* Init timer subsystem for the ENA timer service. */
+		rte_timer_subsystem_init();
+		/* Register handler for requests from secondary processes. */
+		rte_mp_action_register(ENA_MP_NAME, ena_mp_primary_handle);
+	}
+
+	init_done = true;
+	return 0;
+}
+
 static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
 {
 	struct ena_calc_queue_size_ctx calc_queue_ctx = { 0 };
@@ -1802,6 +2079,10 @@  static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
 	eth_dev->tx_pkt_burst = &eth_ena_xmit_pkts;
 	eth_dev->tx_pkt_prepare = &eth_ena_prep_pkts;
 
+	rc = ena_init_once();
+	if (rc != 0)
+		return rc;
+
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
@@ -1938,8 +2219,6 @@  static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
 	ena_com_set_admin_polling_mode(ena_dev, false);
 	ena_com_admin_aenq_enable(ena_dev);
 
-	if (adapters_found == 0)
-		rte_timer_subsystem_init();
 	rte_timer_init(&adapter->timer_wd);
 
 	adapters_found++;
@@ -2803,13 +3082,16 @@  static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 	return sent_idx;
 }
 
-int ena_copy_eni_stats(struct ena_adapter *adapter)
+int ena_copy_eni_stats(struct ena_adapter *adapter, struct ena_stats_eni *stats)
 {
-	struct ena_admin_eni_stats admin_eni_stats;
 	int rc;
 
 	rte_spinlock_lock(&adapter->admin_lock);
-	rc = ena_com_get_eni_stats(&adapter->ena_dev, &admin_eni_stats);
+	/* Retrieve and store the latest statistics from the AQ. This ensures
+	 * that previous value is returned in case of a com error.
+	 */
+	rc = ENA_PROXY(adapter, ena_com_get_eni_stats, &adapter->ena_dev,
+		(struct ena_admin_eni_stats *)stats);
 	rte_spinlock_unlock(&adapter->admin_lock);
 	if (rc != 0) {
 		if (rc == ENA_COM_UNSUPPORTED) {
@@ -2822,9 +3104,6 @@  int ena_copy_eni_stats(struct ena_adapter *adapter)
 		return rc;
 	}
 
-	rte_memcpy(&adapter->eni_stats, &admin_eni_stats,
-		sizeof(struct ena_stats_eni));
-
 	return 0;
 }
 
@@ -2895,6 +3174,7 @@  static int ena_xstats_get(struct rte_eth_dev *dev,
 {
 	struct ena_adapter *adapter = dev->data->dev_private;
 	unsigned int xstats_count = ena_xstats_calc_num(dev->data);
+	struct ena_stats_eni eni_stats;
 	unsigned int stat, i, count = 0;
 	int stat_offset;
 	void *stats_begin;
@@ -2917,10 +3197,10 @@  static int ena_xstats_get(struct rte_eth_dev *dev,
 	/* Even if the function below fails, we should copy previous (or initial
 	 * values) to keep structure of rte_eth_xstat consistent.
 	 */
-	ena_copy_eni_stats(adapter);
+	ena_copy_eni_stats(adapter, &eni_stats);
 	for (stat = 0; stat < ENA_STATS_ARRAY_ENI; stat++, count++) {
 		stat_offset = ena_stats_eni_strings[stat].stat_offset;
-		stats_begin = &adapter->eni_stats;
+		stats_begin = &eni_stats;
 
 		xstats[count].id = count;
 		xstats[count].value = *((uint64_t *)
@@ -2958,6 +3238,7 @@  static int ena_xstats_get_by_id(struct rte_eth_dev *dev,
 				unsigned int n)
 {
 	struct ena_adapter *adapter = dev->data->dev_private;
+	struct ena_stats_eni eni_stats;
 	uint64_t id;
 	uint64_t rx_entries, tx_entries;
 	unsigned int i;
@@ -2983,9 +3264,9 @@  static int ena_xstats_get_by_id(struct rte_eth_dev *dev,
 			 */
 			if (!was_eni_copied) {
 				was_eni_copied = true;
-				ena_copy_eni_stats(adapter);
+				ena_copy_eni_stats(adapter, &eni_stats);
 			}
-			values[i] = *((uint64_t *)&adapter->eni_stats + id);
+			values[i] = *((uint64_t *)&eni_stats + id);
 			++valid;
 			continue;
 		}
@@ -3198,6 +3479,18 @@  static int ena_configure_aenq(struct ena_adapter *adapter)
 	return 0;
 }
 
+int ena_mp_indirect_table_set(struct ena_adapter *adapter)
+{
+	return ENA_PROXY(adapter, ena_com_indirect_table_set, &adapter->ena_dev);
+}
+
+int ena_mp_indirect_table_get(struct ena_adapter *adapter,
+			      uint32_t *indirect_table)
+{
+	return ENA_PROXY(adapter, ena_com_indirect_table_get, &adapter->ena_dev,
+		indirect_table);
+}
+
 /*********************************************************************
  *  PMD configuration
  *********************************************************************/
@@ -3316,3 +3609,64 @@  static struct ena_aenq_handlers aenq_handlers = {
 	},
 	.unimplemented_handler = unimplemented_aenq_handler
 };
+
+/*********************************************************************
+ *  Multi-Process communication request handling (in primary)
+ *********************************************************************/
+static int
+ena_mp_primary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
+{
+	const struct ena_mp_body *req =
+		(const struct ena_mp_body *)mp_msg->param;
+	struct ena_adapter *adapter;
+	struct ena_com_dev *ena_dev;
+	struct ena_mp_body *rsp;
+	struct rte_mp_msg mp_rsp;
+	struct rte_eth_dev *dev;
+	int res = 0;
+
+	rsp = (struct ena_mp_body *)&mp_rsp.param;
+	mp_msg_init(&mp_rsp, req->type, req->port_id);
+
+	if (!rte_eth_dev_is_valid_port(req->port_id)) {
+		rte_errno = ENODEV;
+		res = -rte_errno;
+		PMD_DRV_LOG(ERR, "Unknown port %d in request %d\n",
+			    req->port_id, req->type);
+		goto end;
+	}
+	dev = &rte_eth_devices[req->port_id];
+	adapter = dev->data->dev_private;
+	ena_dev = &adapter->ena_dev;
+
+	switch (req->type) {
+	case ENA_MP_DEV_STATS_GET:
+		res = ena_com_get_dev_basic_stats(ena_dev,
+						  &adapter->basic_stats);
+		break;
+	case ENA_MP_ENI_STATS_GET:
+		res = ena_com_get_eni_stats(ena_dev,
+			(struct ena_admin_eni_stats *)&adapter->eni_stats);
+		break;
+	case ENA_MP_MTU_SET:
+		res = ena_com_set_dev_mtu(ena_dev, req->args.mtu);
+		break;
+	case ENA_MP_IND_TBL_GET:
+		res = ena_com_indirect_table_get(ena_dev,
+						 adapter->indirect_table);
+		break;
+	case ENA_MP_IND_TBL_SET:
+		res = ena_com_indirect_table_set(ena_dev);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Unknown request type %d\n", req->type);
+		res = -EINVAL;
+		break;
+	}
+
+end:
+	/* Save processing result in the reply */
+	rsp->result = res;
+	/* Return just IPC processing status */
+	return rte_mp_reply(&mp_rsp, peer);
+}
diff --git a/drivers/net/ena/ena_ethdev.h b/drivers/net/ena/ena_ethdev.h
index f660b6a7cb..01cf0ef5db 100644
--- a/drivers/net/ena/ena_ethdev.h
+++ b/drivers/net/ena/ena_ethdev.h
@@ -29,6 +29,9 @@ 
 #define ENA_RX_BUF_MIN_SIZE	1400
 #define ENA_DEFAULT_RING_SIZE	1024
 
+#define ENA_RX_RSS_TABLE_LOG_SIZE	7
+#define ENA_RX_RSS_TABLE_SIZE		(1 << ENA_RX_RSS_TABLE_LOG_SIZE)
+
 #define ENA_MIN_MTU		128
 
 #define ENA_MMIO_DISABLE_REG_READ	BIT(0)
@@ -290,6 +293,9 @@  struct ena_adapter {
 
 	struct ena_stats_dev dev_stats;
 	struct ena_stats_eni eni_stats;
+	struct ena_admin_basic_stats basic_stats;
+
+	u32 indirect_table[ENA_RX_RSS_TABLE_SIZE];
 
 	uint32_t all_aenq_groups;
 	uint32_t active_aenq_groups;
@@ -304,6 +310,9 @@  struct ena_adapter {
 	uint64_t tx_cleanup_stall_delay;
 };
 
+int ena_mp_indirect_table_set(struct ena_adapter *adapter);
+int ena_mp_indirect_table_get(struct ena_adapter *adapter,
+			      uint32_t *indirect_table);
 int ena_rss_reta_update(struct rte_eth_dev *dev,
 			struct rte_eth_rss_reta_entry64 *reta_conf,
 			uint16_t reta_size);
diff --git a/drivers/net/ena/ena_rss.c b/drivers/net/ena/ena_rss.c
index be4007e3f3..b6c4f76e38 100644
--- a/drivers/net/ena/ena_rss.c
+++ b/drivers/net/ena/ena_rss.c
@@ -89,6 +89,8 @@  int ena_rss_reta_update(struct rte_eth_dev *dev,
 		return -EINVAL;
 	}
 
+	/* Prevent RETA table structure update races */
+	rte_spinlock_lock(&adapter->admin_lock);
 	for (i = 0 ; i < reta_size ; i++) {
 		/* Each reta_conf is for 64 entries.
 		 * To support 128 we use 2 conf of 64.
@@ -109,8 +111,7 @@  int ena_rss_reta_update(struct rte_eth_dev *dev,
 		}
 	}
 
-	rte_spinlock_lock(&adapter->admin_lock);
-	rc = ena_com_indirect_table_set(ena_dev);
+	rc = ena_mp_indirect_table_set(adapter);
 	rte_spinlock_unlock(&adapter->admin_lock);
 	if (unlikely(rc != 0)) {
 		PMD_DRV_LOG(ERR, "Cannot set the indirection table\n");
@@ -128,9 +129,8 @@  int ena_rss_reta_query(struct rte_eth_dev *dev,
 		       struct rte_eth_rss_reta_entry64 *reta_conf,
 		       uint16_t reta_size)
 {
-	uint32_t indirect_table[ENA_RX_RSS_TABLE_SIZE] = { 0 };
+	uint32_t indirect_table[ENA_RX_RSS_TABLE_SIZE];
 	struct ena_adapter *adapter = dev->data->dev_private;
-	struct ena_com_dev *ena_dev = &adapter->ena_dev;
 	int rc;
 	int i;
 	int reta_conf_idx;
@@ -146,7 +146,7 @@  int ena_rss_reta_query(struct rte_eth_dev *dev,
 	}
 
 	rte_spinlock_lock(&adapter->admin_lock);
-	rc = ena_com_indirect_table_get(ena_dev, indirect_table);
+	rc = ena_mp_indirect_table_get(adapter, indirect_table);
 	rte_spinlock_unlock(&adapter->admin_lock);
 	if (unlikely(rc != 0)) {
 		PMD_DRV_LOG(ERR, "Cannot get indirection table\n");