diff mbox series

[v5,1/6] eal/interrupts: implement get set APIs

Message ID 20211022204934.132186-2-hkalra@marvell.com (mailing list archive)
State Superseded, archived
Delegated to: David Marchand
Headers show
Series make rte_intr_handle internal | expand

Checks

Context Check Description
ci/iol-testing warning apply patch failure
ci/checkpatch warning coding style issues

Commit Message

Harman Kalra Oct. 22, 2021, 8:49 p.m. UTC
Prototype/Implement get set APIs for interrupt handle fields.
User wont be able to access any of the interrupt handle fields
directly while should use these get/set APIs to access/manipulate
them.

Internal interrupt header i.e. rte_eal_interrupt.h is rearranged,
as APIs defined are moved to rte_interrupts.h and epoll specific
definitions are moved to a new header rte_epoll.h.
Later in the series rte_eal_interrupt.h will be removed.

Signed-off-by: Harman Kalra <hkalra@marvell.com>
Acked-by: Ray Kinsella <mdr@ashroe.eu>
---
 MAINTAINERS                            |   1 +
 lib/eal/common/eal_common_interrupts.c | 421 ++++++++++++++++
 lib/eal/common/meson.build             |   1 +
 lib/eal/include/meson.build            |   1 +
 lib/eal/include/rte_eal_interrupts.h   | 209 +-------
 lib/eal/include/rte_epoll.h            | 118 +++++
 lib/eal/include/rte_interrupts.h       | 648 ++++++++++++++++++++++++-
 lib/eal/version.map                    |  46 +-
 8 files changed, 1232 insertions(+), 213 deletions(-)
 create mode 100644 lib/eal/common/eal_common_interrupts.c
 create mode 100644 lib/eal/include/rte_epoll.h

Comments

Dmitry Kozlyuk Oct. 22, 2021, 11:33 p.m. UTC | #1
2021-10-23 02:19 (UTC+0530), Harman Kalra:
> Prototype/Implement get set APIs for interrupt handle fields.
> User wont be able to access any of the interrupt handle fields
> directly while should use these get/set APIs to access/manipulate
> them.
> 
> Internal interrupt header i.e. rte_eal_interrupt.h is rearranged,
> as APIs defined are moved to rte_interrupts.h and epoll specific
> definitions are moved to a new header rte_epoll.h.
> Later in the series rte_eal_interrupt.h will be removed.
> 
> Signed-off-by: Harman Kalra <hkalra@marvell.com>
> Acked-by: Ray Kinsella <mdr@ashroe.eu>

Hi Harman,

After fixing some comment below feel free to add:
Acked-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>

> ---
>  MAINTAINERS                            |   1 +
>  lib/eal/common/eal_common_interrupts.c | 421 ++++++++++++++++
>  lib/eal/common/meson.build             |   1 +
>  lib/eal/include/meson.build            |   1 +
>  lib/eal/include/rte_eal_interrupts.h   | 209 +-------
>  lib/eal/include/rte_epoll.h            | 118 +++++
>  lib/eal/include/rte_interrupts.h       | 648 ++++++++++++++++++++++++-
>  lib/eal/version.map                    |  46 +-
>  8 files changed, 1232 insertions(+), 213 deletions(-)
>  create mode 100644 lib/eal/common/eal_common_interrupts.c
>  create mode 100644 lib/eal/include/rte_epoll.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 04ea23a04a..d2950400d2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -211,6 +211,7 @@ F: app/test/test_memzone.c
>  
>  Interrupt Subsystem
>  M: Harman Kalra <hkalra@marvell.com>
> +F: lib/eal/include/rte_epoll.h
>  F: lib/eal/*/*interrupts.*
>  F: app/test/test_interrupts.c
>  
> diff --git a/lib/eal/common/eal_common_interrupts.c b/lib/eal/common/eal_common_interrupts.c
> [...]
> +int rte_intr_efds_index_get(const struct rte_intr_handle *intr_handle,
> +			    int index)
> +{
> +	CHECK_VALID_INTR_HANDLE(intr_handle);
> +
> +	if (index >= intr_handle->nb_intr) {
> +		RTE_LOG(ERR, EAL, "Invalid size %d, max limit %d\n", index,

"size" -> "index"

> +			intr_handle->nb_intr);
> +		rte_errno = EINVAL;
> +		goto fail;
> +	}
> +
> +	return intr_handle->efds[index];
> +fail:
> +	return -rte_errno;
> +}

> [...]
> +int rte_intr_vec_list_alloc(struct rte_intr_handle *intr_handle,
> +				   const char *name, int size)
> +{
> +	CHECK_VALID_INTR_HANDLE(intr_handle);
> +
> +	/* Vector list already allocated */
> +	if (intr_handle->intr_vec != NULL)
> +		return 0;

What if `size > intr_handle->vec_list_size`?

> +
> +	if (size > intr_handle->nb_intr) {
> +		RTE_LOG(ERR, EAL, "Invalid size %d, max limit %d\n", size,
> +		       intr_handle->nb_intr);
> +		rte_errno = ERANGE;
> +		goto fail;
> +	}
> +
> +	intr_handle->intr_vec = rte_zmalloc(name, size * sizeof(int), 0);
> +	if (intr_handle->intr_vec == NULL) {
> +		RTE_LOG(ERR, EAL, "Failed to allocate %d intr_vec", size);
> +			rte_errno = ENOMEM;
> +			goto fail;
> +	}
> +
> +	intr_handle->vec_list_size = size;
> +
> +	return 0;
> +fail:
> +	return -rte_errno;
> +}

> [...]
> diff --git a/lib/eal/include/rte_interrupts.h b/lib/eal/include/rte_interrupts.h
> index cc3bf45d8c..a29232e16a 100644
> --- a/lib/eal/include/rte_interrupts.h
> +++ b/lib/eal/include/rte_interrupts.h
> @@ -5,8 +5,11 @@
>  #ifndef _RTE_INTERRUPTS_H_
>  #define _RTE_INTERRUPTS_H_
>  
> +#include <stdbool.h>
> +
>  #include <rte_common.h>
>  #include <rte_compat.h>
> +#include <rte_epoll.h>
>  
>  /**
>   * @file
> @@ -22,6 +25,16 @@ extern "C" {
>  /** Interrupt handle */
>  struct rte_intr_handle;
>  
> +/** Interrupt instance allocation flags
> + * @see rte_intr_instance_alloc
> + */
> +/** Interrupt instance would not be shared within primary secondary process. */
> +#define RTE_INTR_INSTANCE_F_UNSHARED	0x00000001
> +/** Interrupt instance could be shared within primary secondary process. */
> +#define RTE_INTR_INSTANCE_F_SHARED	0x00000002

Nits:

"would not" -> "will not"

"could" -> "will be"

"within primary secondary process" ->
"between primary and secondary processes"

You previously suggested PRIVATE instead of UNSHARED,
it sounded better, but no strog opinion.

> [...]
> +/**
> + * @internal
> + * This API is used to populate interrupt handle with src handler fields.

"handler" -> "handle"

> + *
> + * @param intr_handle
> + *  Interrupt handle pointer.
> + * @param src
> + *  Source interrupt handle to be cloned.
> + *
> + * @return
> + *   - On success, zero.
> + *   - On failure, a negative value and rte_errno is set.
> + */
> +__rte_internal
> +int
> +rte_intr_instance_copy(struct rte_intr_handle *intr_handle,
> +		       const struct rte_intr_handle *src);
> [...]

> +/**
> + * @internal
> + * This API returns the sources from where memory is allocated for interrupt
> + * instance.
> + *
> + * @param intr_handle
> + *  pointer to the interrupt handle.
> + *
> + * @return
> + *  - On success, 1 corresponds to memory allocated via DPDK allocator APIs
> + *  - On success, 0 corresponds to memory allocated from traditional heap.
> + *  - On failure, negative value.
> + */
> +__rte_internal
> +int
> +rte_intr_instance_alloc_flag_get(const struct rte_intr_handle *intr_handle);

It returns flags passed on allow,
so return value type and description is inaccurate.
Should be uint32_t and a reference to the flag constants.
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 04ea23a04a..d2950400d2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -211,6 +211,7 @@  F: app/test/test_memzone.c
 
 Interrupt Subsystem
 M: Harman Kalra <hkalra@marvell.com>
+F: lib/eal/include/rte_epoll.h
 F: lib/eal/*/*interrupts.*
 F: app/test/test_interrupts.c
 
diff --git a/lib/eal/common/eal_common_interrupts.c b/lib/eal/common/eal_common_interrupts.c
new file mode 100644
index 0000000000..618782e9cc
--- /dev/null
+++ b/lib/eal/common/eal_common_interrupts.c
@@ -0,0 +1,421 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_interrupts.h>
+
+/* Macros to check for valid port */
+#define CHECK_VALID_INTR_HANDLE(intr_handle) do { \
+	if (intr_handle == NULL) { \
+		RTE_LOG(ERR, EAL, "Interrupt instance unallocated\n"); \
+		rte_errno = EINVAL; \
+		goto fail; \
+	} \
+} while (0)
+
+#define RTE_INTR_INSTANCE_KNOWN_FLAGS (		\
+	RTE_INTR_INSTANCE_F_SHARED	|	\
+	RTE_INTR_INSTANCE_F_UNSHARED)
+
+#define IS_RTE_MEMORY(intr_handle)		\
+		!!(intr_handle->alloc_flag & RTE_INTR_INSTANCE_F_SHARED)
+
+struct rte_intr_handle *rte_intr_instance_alloc(uint32_t flags)
+{
+	struct rte_intr_handle *intr_handle;
+	bool is_rte_memory;
+
+	/* Check the flag passed by user, it should be part of the
+	 * defined flags.
+	 */
+	if ((flags & (flags - 1)) ||
+	    (flags & ~RTE_INTR_INSTANCE_KNOWN_FLAGS) != 0) {
+		RTE_LOG(ERR, EAL, "Invalid alloc flag passed %x\n", flags);
+		rte_errno = EINVAL;
+		return NULL;
+	}
+
+	is_rte_memory = (flags & RTE_INTR_INSTANCE_F_SHARED) != 0;
+	if (is_rte_memory == true)
+		intr_handle = rte_zmalloc(NULL, sizeof(*intr_handle), 0);
+	else
+		intr_handle = calloc(1, sizeof(*intr_handle));
+	if (intr_handle == NULL) {
+		RTE_LOG(ERR, EAL, "Fail to allocate intr_handle\n");
+		rte_errno = ENOMEM;
+		return NULL;
+	}
+
+	intr_handle->nb_intr = RTE_MAX_RXTX_INTR_VEC_ID;
+	intr_handle->alloc_flag = flags;
+
+	return intr_handle;
+}
+
+int rte_intr_instance_copy(struct rte_intr_handle *intr_handle,
+			   const struct rte_intr_handle *src)
+{
+	uint16_t nb_intr;
+
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	if (src == NULL) {
+		RTE_LOG(ERR, EAL, "Source interrupt instance unallocated\n");
+		rte_errno = EINVAL;
+		goto fail;
+	}
+
+	intr_handle->fd = src->fd;
+	intr_handle->vfio_dev_fd = src->vfio_dev_fd;
+	intr_handle->type = src->type;
+	intr_handle->max_intr = src->max_intr;
+	intr_handle->nb_efd = src->nb_efd;
+	intr_handle->efd_counter_size = src->efd_counter_size;
+
+	nb_intr = RTE_MIN(src->nb_intr, intr_handle->nb_intr);
+	memcpy(intr_handle->efds, src->efds, nb_intr);
+	memcpy(intr_handle->elist, src->elist, nb_intr);
+
+	return 0;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_instance_alloc_flag_get(const struct rte_intr_handle *intr_handle)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	return intr_handle->alloc_flag;
+fail:
+	return -rte_errno;
+}
+
+void rte_intr_instance_free(struct rte_intr_handle *intr_handle)
+{
+	if (intr_handle != NULL) {
+		if (IS_RTE_MEMORY(intr_handle) != 0)
+			rte_free(intr_handle);
+		else
+			free(intr_handle);
+	}
+}
+
+int rte_intr_fd_set(struct rte_intr_handle *intr_handle, int fd)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	intr_handle->fd = fd;
+
+	return 0;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_fd_get(const struct rte_intr_handle *intr_handle)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	return intr_handle->fd;
+fail:
+	return -1;
+}
+
+int rte_intr_type_set(struct rte_intr_handle *intr_handle,
+		      enum rte_intr_handle_type type)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	intr_handle->type = type;
+
+	return 0;
+fail:
+	return -rte_errno;
+}
+
+enum rte_intr_handle_type rte_intr_type_get(
+				const struct rte_intr_handle *intr_handle)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	return intr_handle->type;
+fail:
+	return RTE_INTR_HANDLE_UNKNOWN;
+}
+
+int rte_intr_dev_fd_set(struct rte_intr_handle *intr_handle, int fd)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	intr_handle->vfio_dev_fd = fd;
+
+	return 0;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_dev_fd_get(const struct rte_intr_handle *intr_handle)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	return intr_handle->vfio_dev_fd;
+fail:
+	return -1;
+}
+
+int rte_intr_max_intr_set(struct rte_intr_handle *intr_handle,
+				 int max_intr)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	if (max_intr > intr_handle->nb_intr) {
+		RTE_LOG(ERR, EAL, "Maximum interrupt vector ID (%d) exceeds "
+			"the number of available events (%d)\n", max_intr,
+			intr_handle->nb_intr);
+		rte_errno = ERANGE;
+		goto fail;
+	}
+
+	intr_handle->max_intr = max_intr;
+
+	return 0;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_max_intr_get(const struct rte_intr_handle *intr_handle)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	return intr_handle->max_intr;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_nb_efd_set(struct rte_intr_handle *intr_handle,
+				 int nb_efd)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	intr_handle->nb_efd = nb_efd;
+
+	return 0;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_nb_efd_get(const struct rte_intr_handle *intr_handle)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	return intr_handle->nb_efd;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_nb_intr_get(const struct rte_intr_handle *intr_handle)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	return intr_handle->nb_intr;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_efd_counter_size_set(struct rte_intr_handle *intr_handle,
+				 uint8_t efd_counter_size)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	intr_handle->efd_counter_size = efd_counter_size;
+
+	return 0;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_efd_counter_size_get(const struct rte_intr_handle *intr_handle)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	return intr_handle->efd_counter_size;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_efds_index_get(const struct rte_intr_handle *intr_handle,
+			    int index)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	if (index >= intr_handle->nb_intr) {
+		RTE_LOG(ERR, EAL, "Invalid size %d, max limit %d\n", index,
+			intr_handle->nb_intr);
+		rte_errno = EINVAL;
+		goto fail;
+	}
+
+	return intr_handle->efds[index];
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_efds_index_set(struct rte_intr_handle *intr_handle,
+			    int index, int fd)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	if (index >= intr_handle->nb_intr) {
+		RTE_LOG(ERR, EAL, "Invalid size %d, max limit %d\n", index,
+			intr_handle->nb_intr);
+		rte_errno = ERANGE;
+		goto fail;
+	}
+
+	intr_handle->efds[index] = fd;
+
+	return 0;
+fail:
+	return -rte_errno;
+}
+
+struct rte_epoll_event *rte_intr_elist_index_get(
+				struct rte_intr_handle *intr_handle, int index)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	if (index >= intr_handle->nb_intr) {
+		RTE_LOG(ERR, EAL, "Invalid index %d, max limit %d\n", index,
+			intr_handle->nb_intr);
+		rte_errno = ERANGE;
+		goto fail;
+	}
+
+	return &intr_handle->elist[index];
+fail:
+	return NULL;
+}
+
+int rte_intr_elist_index_set(struct rte_intr_handle *intr_handle,
+			     int index, struct rte_epoll_event elist)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	if (index >= intr_handle->nb_intr) {
+		RTE_LOG(ERR, EAL, "Invalid index %d, max limit %d\n", index,
+			intr_handle->nb_intr);
+		rte_errno = ERANGE;
+		goto fail;
+	}
+
+	intr_handle->elist[index] = elist;
+
+	return 0;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_vec_list_alloc(struct rte_intr_handle *intr_handle,
+				   const char *name, int size)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	/* Vector list already allocated */
+	if (intr_handle->intr_vec != NULL)
+		return 0;
+
+	if (size > intr_handle->nb_intr) {
+		RTE_LOG(ERR, EAL, "Invalid size %d, max limit %d\n", size,
+		       intr_handle->nb_intr);
+		rte_errno = ERANGE;
+		goto fail;
+	}
+
+	intr_handle->intr_vec = rte_zmalloc(name, size * sizeof(int), 0);
+	if (intr_handle->intr_vec == NULL) {
+		RTE_LOG(ERR, EAL, "Failed to allocate %d intr_vec", size);
+			rte_errno = ENOMEM;
+			goto fail;
+	}
+
+	intr_handle->vec_list_size = size;
+
+	return 0;
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_vec_list_index_get(const struct rte_intr_handle *intr_handle,
+				int index)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	RTE_ASSERT(intr_handle->vec_list_size != 0);
+
+	if (index > intr_handle->vec_list_size) {
+		RTE_LOG(ERR, EAL, "Index %d greater than vec list size %d\n",
+			index, intr_handle->vec_list_size);
+		rte_errno = ERANGE;
+		goto fail;
+	}
+
+	return intr_handle->intr_vec[index];
+fail:
+	return -rte_errno;
+}
+
+int rte_intr_vec_list_index_set(struct rte_intr_handle *intr_handle,
+				int index, int vec)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	RTE_ASSERT(intr_handle->vec_list_size != 0);
+
+	if (index > intr_handle->vec_list_size) {
+		RTE_LOG(ERR, EAL, "Index %d greater than vec list size %d\n",
+			index, intr_handle->vec_list_size);
+		rte_errno = ERANGE;
+		goto fail;
+	}
+
+	intr_handle->intr_vec[index] = vec;
+
+	return 0;
+fail:
+	return -rte_errno;
+}
+
+void rte_intr_vec_list_free(struct rte_intr_handle *intr_handle)
+{
+	if (intr_handle != NULL) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+		intr_handle->vec_list_size = 0;
+	}
+}
+
+void *rte_intr_instance_windows_handle_get(struct rte_intr_handle *intr_handle)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	return intr_handle->windows_handle;
+fail:
+	return NULL;
+}
+
+int rte_intr_instance_windows_handle_set(struct rte_intr_handle *intr_handle,
+					 void *windows_handle)
+{
+	CHECK_VALID_INTR_HANDLE(intr_handle);
+
+	intr_handle->windows_handle = windows_handle;
+
+	return 0;
+fail:
+	return -rte_errno;
+}
diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index 6d01b0f072..917758cc65 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -15,6 +15,7 @@  sources += files(
         'eal_common_errno.c',
         'eal_common_fbarray.c',
         'eal_common_hexdump.c',
+        'eal_common_interrupts.c',
         'eal_common_launch.c',
         'eal_common_lcore.c',
         'eal_common_log.c',
diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
index 88a9eba12f..8e258607b8 100644
--- a/lib/eal/include/meson.build
+++ b/lib/eal/include/meson.build
@@ -19,6 +19,7 @@  headers += files(
         'rte_eal_memconfig.h',
         'rte_eal_trace.h',
         'rte_errno.h',
+        'rte_epoll.h',
         'rte_fbarray.h',
         'rte_hexdump.h',
         'rte_hypervisor.h',
diff --git a/lib/eal/include/rte_eal_interrupts.h b/lib/eal/include/rte_eal_interrupts.h
index 00bcc19b6d..26c6300826 100644
--- a/lib/eal/include/rte_eal_interrupts.h
+++ b/lib/eal/include/rte_eal_interrupts.h
@@ -39,32 +39,6 @@  enum rte_intr_handle_type {
 	RTE_INTR_HANDLE_MAX           /**< count of elements */
 };
 
-#define RTE_INTR_EVENT_ADD            1UL
-#define RTE_INTR_EVENT_DEL            2UL
-
-typedef void (*rte_intr_event_cb_t)(int fd, void *arg);
-
-struct rte_epoll_data {
-	uint32_t event;               /**< event type */
-	void *data;                   /**< User data */
-	rte_intr_event_cb_t cb_fun;   /**< IN: callback fun */
-	void *cb_arg;	              /**< IN: callback arg */
-};
-
-enum {
-	RTE_EPOLL_INVALID = 0,
-	RTE_EPOLL_VALID,
-	RTE_EPOLL_EXEC,
-};
-
-/** interrupt epoll event obj, taken by epoll_event.ptr */
-struct rte_epoll_event {
-	uint32_t status;           /**< OUT: event status */
-	int fd;                    /**< OUT: event fd */
-	int epfd;       /**< OUT: epoll instance the ev associated with */
-	struct rte_epoll_data epdata;
-};
-
 /** Handle for interrupts. */
 struct rte_intr_handle {
 	RTE_STD_C11
@@ -79,191 +53,20 @@  struct rte_intr_handle {
 			};
 			int fd;	/**< interrupt event file descriptor */
 		};
-		void *handle; /**< device driver handle (Windows) */
+		void *windows_handle; /**< device driver handle */
 	};
+	uint32_t alloc_flag;	/** Interrupt Instance allocation flag */
 	enum rte_intr_handle_type type;  /**< handle type */
 	uint32_t max_intr;             /**< max interrupt requested */
 	uint32_t nb_efd;               /**< number of available efd(event fd) */
 	uint8_t efd_counter_size;      /**< size of efd counter, used for vdev */
+	uint16_t nb_intr;
+		/**< Max vector count, default RTE_MAX_RXTX_INTR_VEC_ID */
 	int efds[RTE_MAX_RXTX_INTR_VEC_ID];  /**< intr vectors/efds mapping */
 	struct rte_epoll_event elist[RTE_MAX_RXTX_INTR_VEC_ID];
-				       /**< intr vector epoll event */
+						/**< intr vector epoll event */
+	uint16_t vec_list_size;
 	int *intr_vec;                 /**< intr vector number array */
 };
 
-#define RTE_EPOLL_PER_THREAD        -1  /**< to hint using per thread epfd */
-
-/**
- * It waits for events on the epoll instance.
- * Retries if signal received.
- *
- * @param epfd
- *   Epoll instance fd on which the caller wait for events.
- * @param events
- *   Memory area contains the events that will be available for the caller.
- * @param maxevents
- *   Up to maxevents are returned, must greater than zero.
- * @param timeout
- *   Specifying a timeout of -1 causes a block indefinitely.
- *   Specifying a timeout equal to zero cause to return immediately.
- * @return
- *   - On success, returns the number of available event.
- *   - On failure, a negative value.
- */
-int
-rte_epoll_wait(int epfd, struct rte_epoll_event *events,
-	       int maxevents, int timeout);
-
-/**
- * It waits for events on the epoll instance.
- * Does not retry if signal received.
- *
- * @param epfd
- *   Epoll instance fd on which the caller wait for events.
- * @param events
- *   Memory area contains the events that will be available for the caller.
- * @param maxevents
- *   Up to maxevents are returned, must greater than zero.
- * @param timeout
- *   Specifying a timeout of -1 causes a block indefinitely.
- *   Specifying a timeout equal to zero cause to return immediately.
- * @return
- *   - On success, returns the number of available event.
- *   - On failure, a negative value.
- */
-__rte_experimental
-int
-rte_epoll_wait_interruptible(int epfd, struct rte_epoll_event *events,
-	       int maxevents, int timeout);
-
-/**
- * It performs control operations on epoll instance referred by the epfd.
- * It requests that the operation op be performed for the target fd.
- *
- * @param epfd
- *   Epoll instance fd on which the caller perform control operations.
- * @param op
- *   The operation be performed for the target fd.
- * @param fd
- *   The target fd on which the control ops perform.
- * @param event
- *   Describes the object linked to the fd.
- *   Note: The caller must take care the object deletion after CTL_DEL.
- * @return
- *   - On success, zero.
- *   - On failure, a negative value.
- */
-int
-rte_epoll_ctl(int epfd, int op, int fd,
-	      struct rte_epoll_event *event);
-
-/**
- * The function returns the per thread epoll instance.
- *
- * @return
- *   epfd the epoll instance referred to.
- */
-int
-rte_intr_tls_epfd(void);
-
-/**
- * @param intr_handle
- *   Pointer to the interrupt handle.
- * @param epfd
- *   Epoll instance fd which the intr vector associated to.
- * @param op
- *   The operation be performed for the vector.
- *   Operation type of {ADD, DEL}.
- * @param vec
- *   RX intr vector number added to the epoll instance wait list.
- * @param data
- *   User raw data.
- * @return
- *   - On success, zero.
- *   - On failure, a negative value.
- */
-int
-rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
-		int epfd, int op, unsigned int vec, void *data);
-
-/**
- * It deletes registered eventfds.
- *
- * @param intr_handle
- *   Pointer to the interrupt handle.
- */
-void
-rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle);
-
-/**
- * It enables the packet I/O interrupt event if it's necessary.
- * It creates event fd for each interrupt vector when MSIX is used,
- * otherwise it multiplexes a single event fd.
- *
- * @param intr_handle
- *   Pointer to the interrupt handle.
- * @param nb_efd
- *   Number of interrupt vector trying to enable.
- *   The value 0 is not allowed.
- * @return
- *   - On success, zero.
- *   - On failure, a negative value.
- */
-int
-rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd);
-
-/**
- * It disables the packet I/O interrupt event.
- * It deletes registered eventfds and closes the open fds.
- *
- * @param intr_handle
- *   Pointer to the interrupt handle.
- */
-void
-rte_intr_efd_disable(struct rte_intr_handle *intr_handle);
-
-/**
- * The packet I/O interrupt on datapath is enabled or not.
- *
- * @param intr_handle
- *   Pointer to the interrupt handle.
- */
-int
-rte_intr_dp_is_en(struct rte_intr_handle *intr_handle);
-
-/**
- * The interrupt handle instance allows other causes or not.
- * Other causes stand for any none packet I/O interrupts.
- *
- * @param intr_handle
- *   Pointer to the interrupt handle.
- */
-int
-rte_intr_allow_others(struct rte_intr_handle *intr_handle);
-
-/**
- * The multiple interrupt vector capability of interrupt handle instance.
- * It returns zero if no multiple interrupt vector support.
- *
- * @param intr_handle
- *   Pointer to the interrupt handle.
- */
-int
-rte_intr_cap_multiple(struct rte_intr_handle *intr_handle);
-
-/**
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
- *
- * @internal
- * Check if currently executing in interrupt context
- *
- * @return
- *  - non zero in case of interrupt context
- *  - zero in case of process context
- */
-__rte_experimental
-int
-rte_thread_is_intr(void);
-
 #endif /* _RTE_EAL_INTERRUPTS_H_ */
diff --git a/lib/eal/include/rte_epoll.h b/lib/eal/include/rte_epoll.h
new file mode 100644
index 0000000000..56b7b6bad6
--- /dev/null
+++ b/lib/eal/include/rte_epoll.h
@@ -0,0 +1,118 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell International Ltd.
+ */
+
+#ifndef __RTE_EPOLL_H__
+#define __RTE_EPOLL_H__
+
+/**
+ * @file
+ * The rte_epoll provides interfaces functions to add delete events,
+ * wait poll for an event.
+ */
+
+#include <stdint.h>
+
+#include <rte_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTE_INTR_EVENT_ADD            1UL
+#define RTE_INTR_EVENT_DEL            2UL
+
+typedef void (*rte_intr_event_cb_t)(int fd, void *arg);
+
+struct rte_epoll_data {
+	uint32_t event;               /**< event type */
+	void *data;                   /**< User data */
+	rte_intr_event_cb_t cb_fun;   /**< IN: callback fun */
+	void *cb_arg;	              /**< IN: callback arg */
+};
+
+enum {
+	RTE_EPOLL_INVALID = 0,
+	RTE_EPOLL_VALID,
+	RTE_EPOLL_EXEC,
+};
+
+/** interrupt epoll event obj, taken by epoll_event.ptr */
+struct rte_epoll_event {
+	uint32_t status;           /**< OUT: event status */
+	int fd;                    /**< OUT: event fd */
+	int epfd;       /**< OUT: epoll instance the ev associated with */
+	struct rte_epoll_data epdata;
+};
+
+#define RTE_EPOLL_PER_THREAD        -1  /**< to hint using per thread epfd */
+
+/**
+ * It waits for events on the epoll instance.
+ * Retries if signal received.
+ *
+ * @param epfd
+ *   Epoll instance fd on which the caller wait for events.
+ * @param events
+ *   Memory area contains the events that will be available for the caller.
+ * @param maxevents
+ *   Up to maxevents are returned, must greater than zero.
+ * @param timeout
+ *   Specifying a timeout of -1 causes a block indefinitely.
+ *   Specifying a timeout equal to zero cause to return immediately.
+ * @return
+ *   - On success, returns the number of available event.
+ *   - On failure, a negative value.
+ */
+int
+rte_epoll_wait(int epfd, struct rte_epoll_event *events,
+	       int maxevents, int timeout);
+
+/**
+ * It waits for events on the epoll instance.
+ * Does not retry if signal received.
+ *
+ * @param epfd
+ *   Epoll instance fd on which the caller wait for events.
+ * @param events
+ *   Memory area contains the events that will be available for the caller.
+ * @param maxevents
+ *   Up to maxevents are returned, must greater than zero.
+ * @param timeout
+ *   Specifying a timeout of -1 causes a block indefinitely.
+ *   Specifying a timeout equal to zero cause to return immediately.
+ * @return
+ *   - On success, returns the number of available event.
+ *   - On failure, a negative value.
+ */
+__rte_experimental
+int
+rte_epoll_wait_interruptible(int epfd, struct rte_epoll_event *events,
+	       int maxevents, int timeout);
+
+/**
+ * It performs control operations on epoll instance referred by the epfd.
+ * It requests that the operation op be performed for the target fd.
+ *
+ * @param epfd
+ *   Epoll instance fd on which the caller perform control operations.
+ * @param op
+ *   The operation be performed for the target fd.
+ * @param fd
+ *   The target fd on which the control ops perform.
+ * @param event
+ *   Describes the object linked to the fd.
+ *   Note: The caller must take care the object deletion after CTL_DEL.
+ * @return
+ *   - On success, zero.
+ *   - On failure, a negative value.
+ */
+int
+rte_epoll_ctl(int epfd, int op, int fd,
+	      struct rte_epoll_event *event);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __RTE_EPOLL_H__ */
diff --git a/lib/eal/include/rte_interrupts.h b/lib/eal/include/rte_interrupts.h
index cc3bf45d8c..a29232e16a 100644
--- a/lib/eal/include/rte_interrupts.h
+++ b/lib/eal/include/rte_interrupts.h
@@ -5,8 +5,11 @@ 
 #ifndef _RTE_INTERRUPTS_H_
 #define _RTE_INTERRUPTS_H_
 
+#include <stdbool.h>
+
 #include <rte_common.h>
 #include <rte_compat.h>
+#include <rte_epoll.h>
 
 /**
  * @file
@@ -22,6 +25,16 @@  extern "C" {
 /** Interrupt handle */
 struct rte_intr_handle;
 
+/** Interrupt instance allocation flags
+ * @see rte_intr_instance_alloc
+ */
+/** Interrupt instance would not be shared within primary secondary process. */
+#define RTE_INTR_INSTANCE_F_UNSHARED	0x00000001
+/** Interrupt instance could be shared within primary secondary process. */
+#define RTE_INTR_INSTANCE_F_SHARED	0x00000002
+
+#include "rte_eal_interrupts.h"
+
 /** Function to be registered for the specific interrupt */
 typedef void (*rte_intr_callback_fn)(void *cb_arg);
 
@@ -32,8 +45,6 @@  typedef void (*rte_intr_callback_fn)(void *cb_arg);
 typedef void (*rte_intr_unregister_callback_fn)(struct rte_intr_handle *intr_handle,
 						void *cb_arg);
 
-#include "rte_eal_interrupts.h"
-
 /**
  * It registers the callback for the specific interrupt. Multiple
  * callbacks can be registered at the same time.
@@ -163,6 +174,639 @@  int rte_intr_disable(const struct rte_intr_handle *intr_handle);
 __rte_experimental
 int rte_intr_ack(const struct rte_intr_handle *intr_handle);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Check if currently executing in interrupt context
+ *
+ * @return
+ *  - non zero in case of interrupt context
+ *  - zero in case of process context
+ */
+__rte_experimental
+int
+rte_thread_is_intr(void);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * It allocates memory for interrupt instance. API takes flag as an argument
+ * which define from where memory should be allocated i.e. using DPDK memory
+ * management library APIs or normal heap allocation.
+ * Default memory allocation for event fds and event list array is done which
+ * can be realloced later based on size of MSIX interrupts supported by a PCI
+ * device.
+ *
+ * This function should be called from application or driver, before calling any
+ * of the interrupt APIs.
+ *
+ * @param flags
+ *  Memory allocation from DPDK allocator or normal allocation
+ *
+ * @return
+ *  - On success, address of interrupt handle.
+ *  - On failure, NULL.
+ */
+__rte_experimental
+struct rte_intr_handle *
+rte_intr_instance_alloc(uint32_t flags);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * This API is used to free the memory allocated for interrupt handle resources.
+ *
+ * @param intr_handle
+ *  Interrupt handle address.
+ *
+ */
+__rte_experimental
+void
+rte_intr_instance_free(struct rte_intr_handle *intr_handle);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * This API is used to set the fd field of interrupt handle with user provided
+ * file descriptor.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param fd
+ *  file descriptor value provided by user.
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_experimental
+int
+rte_intr_fd_set(struct rte_intr_handle *intr_handle, int fd);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Returns the fd field of the given interrupt handle instance.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ *
+ * @return
+ *  - On success, fd field.
+ *  - On failure, a negative value.
+ */
+__rte_experimental
+int
+rte_intr_fd_get(const struct rte_intr_handle *intr_handle);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * This API is used to set the type field of interrupt handle with user provided
+ * interrupt type.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param type
+ *  interrupt type
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_experimental
+int
+rte_intr_type_set(struct rte_intr_handle *intr_handle,
+		  enum rte_intr_handle_type type);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Returns the type field of the given interrupt handle instance.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ *
+ * @return
+ *  - On success, interrupt type
+ *  - On failure, RTE_INTR_HANDLE_UNKNOWN.
+ */
+__rte_experimental
+enum rte_intr_handle_type
+rte_intr_type_get(const struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * The function returns the per thread epoll instance.
+ *
+ * @return
+ *   epfd the epoll instance referred to.
+ */
+__rte_internal
+int
+rte_intr_tls_epfd(void);
+
+/**
+ * @internal
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ * @param epfd
+ *   Epoll instance fd which the intr vector associated to.
+ * @param op
+ *   The operation be performed for the vector.
+ *   Operation type of {ADD, DEL}.
+ * @param vec
+ *   RX intr vector number added to the epoll instance wait list.
+ * @param data
+ *   User raw data.
+ * @return
+ *   - On success, zero.
+ *   - On failure, a negative value.
+ */
+__rte_internal
+int
+rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
+		int epfd, int op, unsigned int vec, void *data);
+
+/**
+ * @internal
+ * It deletes registered eventfds.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ */
+__rte_internal
+void
+rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * It enables the packet I/O interrupt event if it's necessary.
+ * It creates event fd for each interrupt vector when MSIX is used,
+ * otherwise it multiplexes a single event fd.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ * @param nb_efd
+ *   Number of interrupt vector trying to enable.
+ *   The value 0 is not allowed.
+ * @return
+ *   - On success, zero.
+ *   - On failure, a negative value.
+ */
+__rte_internal
+int
+rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd);
+
+/**
+ * @internal
+ * It disables the packet I/O interrupt event.
+ * It deletes registered eventfds and closes the open fds.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ */
+__rte_internal
+void
+rte_intr_efd_disable(struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * The packet I/O interrupt on datapath is enabled or not.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ */
+__rte_internal
+int
+rte_intr_dp_is_en(struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * The interrupt handle instance allows other causes or not.
+ * Other causes stand for any none packet I/O interrupts.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ */
+__rte_internal
+int
+rte_intr_allow_others(struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * The multiple interrupt vector capability of interrupt handle instance.
+ * It returns zero if no multiple interrupt vector support.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ */
+__rte_internal
+int
+rte_intr_cap_multiple(struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * This API is used to populate interrupt handle with src handler fields.
+ *
+ * @param intr_handle
+ *  Interrupt handle pointer.
+ * @param src
+ *  Source interrupt handle to be cloned.
+ *
+ * @return
+ *   - On success, zero.
+ *   - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_instance_copy(struct rte_intr_handle *intr_handle,
+		       const struct rte_intr_handle *src);
+
+/**
+ * @internal
+ * This API is used to set the device fd field of interrupt handle with user
+ * provided dev fd. Device fd corresponds to VFIO device fd or UIO config fd.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param fd
+ *  interrupt type
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_dev_fd_set(struct rte_intr_handle *intr_handle, int fd);
+
+/**
+ * @internal
+ * Returns the device fd field of the given interrupt handle instance.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ *
+ * @return
+ *  - On success, dev fd.
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_dev_fd_get(const struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * This API is used to set the max intr field of interrupt handle with user
+ * provided max intr value.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param max_intr
+ *  interrupt type
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_max_intr_set(struct rte_intr_handle *intr_handle, int max_intr);
+
+/**
+ * @internal
+ * Returns the max intr field of the given interrupt handle instance.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ *
+ * @return
+ *  - On success, max intr.
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_max_intr_get(const struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * This API is used to set the number of event fd field of interrupt handle
+ * with user provided available event file descriptor value.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param nb_efd
+ *  Available event fd
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_nb_efd_set(struct rte_intr_handle *intr_handle, int nb_efd);
+
+/**
+ * @internal
+ * Returns the number of available event fd field of the given interrupt handle
+ * instance.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ *
+ * @return
+ *  - On success, nb_efd
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_nb_efd_get(const struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * Returns the number of interrupt vector field of the given interrupt handle
+ * instance. This field is to configured on device probe time, and based on
+ * this value efds and elist arrays are dynamically allocated. By default
+ * this value is set to RTE_MAX_RXTX_INTR_VEC_ID.
+ * For eg. in case of PCI device, its msix size is queried and efds/elist
+ * arrays are allocated accordingly.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ *
+ * @return
+ *  - On success, nb_intr
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_nb_intr_get(const struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * This API is used to set the event fd counter size field of interrupt handle
+ * with user provided efd counter size.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param efd_counter_size
+ *  size of efd counter.
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_efd_counter_size_set(struct rte_intr_handle *intr_handle,
+			      uint8_t efd_counter_size);
+
+/**
+ * @internal
+ * Returns the event fd counter size field of the given interrupt handle
+ * instance.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ *
+ * @return
+ *  - On success, efd_counter_size
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_efd_counter_size_get(const struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * This API is used to set the event fd array index with the given fd.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param index
+ *  efds array index to be set
+ * @param fd
+ *  event fd
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_efds_index_set(struct rte_intr_handle *intr_handle, int index, int fd);
+
+/**
+ * @internal
+ * Returns the fd value of event fds array at a given index.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param index
+ *  efds array index to be returned
+ *
+ * @return
+ *  - On success, fd
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_efds_index_get(const struct rte_intr_handle *intr_handle, int index);
+
+/**
+ * @internal
+ * This API is used to set the epoll event object array index with the given
+ * elist instance.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param index
+ *  elist array index to be set
+ * @param elist
+ *  epoll event instance of struct rte_epoll_event
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_elist_index_set(struct rte_intr_handle *intr_handle, int index,
+			 struct rte_epoll_event elist);
+
+/**
+ * @internal
+ * Returns the address of epoll event instance from elist array at a given
+ * index.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param index
+ *  elist array index to be returned
+ *
+ * @return
+ *  - On success, elist
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+struct rte_epoll_event *
+rte_intr_elist_index_get(struct rte_intr_handle *intr_handle, int index);
+
+/**
+ * @internal
+ * Allocates the memory of interrupt vector list array, with size defining the
+ * number of elements required in the array.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param name
+ *  Name assigned to the allocation, or NULL.
+ * @param size
+ *  Number of element required in the array.
+ *
+ * @return
+ *  - On success, zero
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_vec_list_alloc(struct rte_intr_handle *intr_handle, const char *name,
+			int size);
+
+/**
+ * @internal
+ * Sets the vector value at given index of interrupt vector list field of given
+ * interrupt handle.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param index
+ *  intr_vec array index to be set
+ * @param vec
+ *  Interrupt vector value.
+ *
+ * @return
+ *  - On success, zero
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_vec_list_index_set(struct rte_intr_handle *intr_handle, int index,
+			    int vec);
+
+/**
+ * @internal
+ * Returns the vector value at the given index of interrupt vector list array.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param index
+ *  intr_vec array index to be returned
+ *
+ * @return
+ *  - On success, interrupt vector
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_vec_list_index_get(const struct rte_intr_handle *intr_handle,
+			    int index);
+
+/**
+ * @internal
+ * Frees the memory allocated for interrupt vector list array.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ *
+ * @return
+ *  - On success, zero
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+void
+rte_intr_vec_list_free(struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * Reallocates the size efds and elist array based on size provided by user.
+ * By default efds and elist array are allocated with default size
+ * RTE_MAX_RXTX_INTR_VEC_ID on interrupt handle array creation. Later on device
+ * probe, device may have capability of more interrupts than
+ * RTE_MAX_RXTX_INTR_VEC_ID. Using this API, PMDs can reallocate the arrays as
+ * per the max interrupts capability of device.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param size
+ *  efds and elist array size.
+ *
+ * @return
+ *  - On success, zero
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_event_list_update(struct rte_intr_handle *intr_handle, int size);
+
+/**
+ * @internal
+ * This API returns the sources from where memory is allocated for interrupt
+ * instance.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ *
+ * @return
+ *  - On success, 1 corresponds to memory allocated via DPDK allocator APIs
+ *  - On success, 0 corresponds to memory allocated from traditional heap.
+ *  - On failure, negative value.
+ */
+__rte_internal
+int
+rte_intr_instance_alloc_flag_get(const struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * This API returns the Windows handle of the given interrupt instance.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ *
+ * @return
+ *  - On success, Windows handle.
+ *  - On failure, NULL.
+ */
+__rte_internal
+void *
+rte_intr_instance_windows_handle_get(struct rte_intr_handle *intr_handle);
+
+/**
+ * @internal
+ * This API set the Windows handle for the given interrupt instance.
+ *
+ * @param intr_handle
+ *  pointer to the interrupt handle.
+ * @param windows_handle
+ *  Windows handle to be set.
+ *
+ * @return
+ *  - On success, zero
+ *  - On failure, a negative value and rte_errno is set.
+ */
+__rte_internal
+int
+rte_intr_instance_windows_handle_set(struct rte_intr_handle *intr_handle,
+				     void *windows_handle);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 38f7de83e1..a506f476a9 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -109,18 +109,10 @@  DPDK_22 {
 	rte_hexdump;
 	rte_hypervisor_get;
 	rte_hypervisor_get_name; # WINDOWS_NO_EXPORT
-	rte_intr_allow_others;
 	rte_intr_callback_register;
 	rte_intr_callback_unregister;
-	rte_intr_cap_multiple;
 	rte_intr_disable;
-	rte_intr_dp_is_en;
-	rte_intr_efd_disable;
-	rte_intr_efd_enable;
 	rte_intr_enable;
-	rte_intr_free_epoll_fd;
-	rte_intr_rx_ctl;
-	rte_intr_tls_epfd;
 	rte_keepalive_create; # WINDOWS_NO_EXPORT
 	rte_keepalive_dispatch_pings; # WINDOWS_NO_EXPORT
 	rte_keepalive_mark_alive; # WINDOWS_NO_EXPORT
@@ -420,12 +412,50 @@  EXPERIMENTAL {
 
 	# added in 21.08
 	rte_power_monitor_multi; # WINDOWS_NO_EXPORT
+
+	# added in 21.11
+	rte_intr_fd_get; # WINDOWS_NO_EXPORT
+	rte_intr_fd_set; # WINDOWS_NO_EXPORT
+	rte_intr_instance_alloc;
+	rte_intr_instance_free;
+	rte_intr_type_get;
+	rte_intr_type_set;
 };
 
 INTERNAL {
 	global:
 
 	rte_firmware_read;
+	rte_intr_allow_others;
+	rte_intr_cap_multiple;
+	rte_intr_dev_fd_get; # WINDOWS_NO_EXPORT
+	rte_intr_dev_fd_set; # WINDOWS_NO_EXPORT
+	rte_intr_dp_is_en;
+	rte_intr_efd_counter_size_set; # WINDOWS_NO_EXPORT
+	rte_intr_efd_counter_size_get; # WINDOWS_NO_EXPORT
+	rte_intr_efd_disable;
+	rte_intr_efd_enable;
+	rte_intr_efds_index_get;
+	rte_intr_efds_index_set;
+	rte_intr_elist_index_get;
+	rte_intr_elist_index_set;
+	rte_intr_event_list_update;
+	rte_intr_free_epoll_fd;
+	rte_intr_instance_alloc_flag_get;
+	rte_intr_instance_copy;
+	rte_intr_instance_windows_handle_get;
+	rte_intr_instance_windows_handle_set;
+	rte_intr_max_intr_get;
+	rte_intr_max_intr_set;
+	rte_intr_nb_efd_get; # WINDOWS_NO_EXPORT
+	rte_intr_nb_efd_set; # WINDOWS_NO_EXPORT
+	rte_intr_nb_intr_get; # WINDOWS_NO_EXPORT
+	rte_intr_rx_ctl;
+	rte_intr_tls_epfd;
+	rte_intr_vec_list_alloc;
+	rte_intr_vec_list_free;
+	rte_intr_vec_list_index_get;
+	rte_intr_vec_list_index_set;
 	rte_mem_lock;
 	rte_mem_map;
 	rte_mem_page_size;