<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div style="direction: ltr; font-family: Aptos, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Acked-by: Nithin Dabilpuram <ndabilpuram@marvell.com></div>
<div id="ms-outlook-mobile-body-separator-line" dir="ltr"><br>
</div>
<div id="ms-outlook-mobile-signature" dir="ltr">
<div>-- </div>
<div style="direction: ltr;"><br>
</div>
</div>
<div style="direction: ltr; font-family: Aptos, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div id="mail-editor-reference-message-container">
<div>On 11/10/26, 7:45 PM, "Mohit Kumar Parjapat" <mprajapat@marvell.com> wrote:</div>
<br>
<div id="mail-editor-reference-message-body">
<div class="ms-outlook-mobile-reference-message skipProofing">
<meta name="Generator" content="Microsoft Exchange Server">
</div>
<div class="PlainText" style="font-size: 11pt;">All MSI-X vectors were registered on pci_dev->intr_handle, rewriting<br>
its fd before each rte_intr_callback_register(). Since EAL references<br>
the caller's handle instead of a copy, all vectors share one interrupt<br>
source whose fd is read live, so only the last vector is polled.<br>
Mailbox replies are lost, probe times out, and the cleanup path leaves<br>
a closed fd in the source, making the interrupt thread panic in<br>
epoll_ctl().<br>
<br>
Register each vector on its own handle, tracked in a list so that<br>
unregister uses and frees the same handle. Reject duplicate vector<br>
registration, close the vector's own eventfd on unregister, and unwind<br>
all error paths of plt_irq_register().<br>
<br>
Fixes: c663018eb7f3 ("interrupts: do not duplicate interrupt handles")<br>
<br>
Signed-off-by: Mohit Kumar Parjapat <mprajapat@marvell.com><br>
Signed-off-by: Harman Kalra <hkalra@marvell.com><br>
---<br>
 .mailmap                           |   1 +<br>
 drivers/common/cnxk/roc_platform.c | 134 ++++++++++++++++++++++++-----<br>
 2 files changed, 115 insertions(+), 20 deletions(-)<br>
<br>
diff --git a/.mailmap b/.mailmap<br>
index 754dd9e760..8ca51f72d7 100644<br>
--- a/.mailmap<br>
+++ b/.mailmap<br>
@@ -1175,6 +1175,7 @@ Mohammad Iqbal Ahmad <mahmad@marvell.com><br>
 Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com><br>
 Mohammed Gamal <mgamal@redhat.com><br>
 Mohand Alrasheed <mrasheed@wirefilter.com><br>
+Mohit Kumar Parjapat <mprajapat@marvell.com><br>
 Mohsin Kazmi <mohsin.kazmi14@gmail.com><br>
 Mohsin Mazhar Shaikh <mohsinmazhar_shaikh@trendmicro.com><br>
 Mohsin Shaikh <mohsinshaikh@niometrics.com><br>
diff --git a/drivers/common/cnxk/roc_platform.c b/drivers/common/cnxk/roc_platform.c<br>
index 59d662fab4..0a1b96092b 100644<br>
--- a/drivers/common/cnxk/roc_platform.c<br>
+++ b/drivers/common/cnxk/roc_platform.c<br>
@@ -16,8 +16,49 @@<br>
 #include <stdlib.h><br>
 #include <sys/eventfd.h><br>
 #include <sys/ioctl.h><br>
+#include <sys/queue.h><br>
 #include <unistd.h><br>
 <br>
+/*<br>
+ * EAL interrupt sources are keyed by interrupt handle pointer and read the<br>
+ * handle FD at epoll/dispatch time, so each MSI-X vector needs its own<br>
+ * handle holding that vector's eventfd.<br>
+ */<br>
+struct plt_irq_vec {<br>
+       TAILQ_ENTRY(plt_irq_vec) next;<br>
+       const struct plt_intr_handle *dev_handle;<br>
+       struct plt_intr_handle *handle;<br>
+       plt_intr_callback_fn cb;<br>
+       void *data;<br>
+       unsigned int vec;<br>
+};<br>
+<br>
+static TAILQ_HEAD(, plt_irq_vec) plt_irq_vec_list = TAILQ_HEAD_INITIALIZER(plt_irq_vec_list);<br>
+static plt_spinlock_t plt_irq_vec_lock = RTE_SPINLOCK_INITIALIZER;<br>
+<br>
+static struct plt_irq_vec *<br>
+irq_vec_find(const struct plt_intr_handle *dev_handle, unsigned int vec)<br>
+{<br>
+       struct plt_irq_vec *irq_vec;<br>
+<br>
+       TAILQ_FOREACH(irq_vec, &plt_irq_vec_list, next) {<br>
+               if (irq_vec->dev_handle == dev_handle && irq_vec->vec == vec)<br>
+                       return irq_vec;<br>
+       }<br>
+<br>
+       return NULL;<br>
+}<br>
+<br>
+static void<br>
+irq_vec_free(struct plt_irq_vec *irq_vec)<br>
+{<br>
+       if (irq_vec->handle != NULL) {<br>
+               plt_intr_fd_close(irq_vec->handle);<br>
+               plt_intr_instance_free(irq_vec->handle);<br>
+       }<br>
+       free(irq_vec);<br>
+}<br>
+<br>
 static int<br>
 irq_get_info(struct plt_intr_handle *intr_handle)<br>
 {<br>
@@ -150,7 +191,7 @@ int<br>
 plt_irq_register(struct plt_intr_handle *intr_handle, plt_intr_callback_fn cb, void *data,<br>
                  unsigned int vec)<br>
 {<br>
-       struct plt_intr_handle *tmp_handle;<br>
+       struct plt_irq_vec *irq_vec;<br>
         uint32_t nb_efd, tmp_nb_efd;<br>
         int rc, fd;<br>
 <br>
@@ -166,25 +207,61 @@ plt_irq_register(struct plt_intr_handle *intr_handle, plt_intr_callback_fn cb, v<br>
                 return -EINVAL;<br>
         }<br>
 <br>
-       tmp_handle = intr_handle;<br>
+       irq_vec = calloc(1, sizeof(*irq_vec));<br>
+       if (irq_vec == NULL)<br>
+               return -ENOMEM;<br>
+       irq_vec->dev_handle = intr_handle;<br>
+       irq_vec->cb = cb;<br>
+       irq_vec->data = data;<br>
+       irq_vec->vec = vec;<br>
+<br>
+       irq_vec->handle = plt_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);<br>
+       if (irq_vec->handle == NULL) {<br>
+               rc = -ENOMEM;<br>
+               goto free_vec;<br>
+       }<br>
+<br>
         /* Create new eventfd for interrupt vector */<br>
         fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);<br>
-       if (fd == -1)<br>
-               return -ENODEV;<br>
+       if (fd == -1) {<br>
+               rc = -ENODEV;<br>
+               goto free_vec;<br>
+       }<br>
 <br>
-       if (plt_intr_fd_set(tmp_handle, fd))<br>
-               return -errno;<br>
+       if (plt_intr_fd_set(irq_vec->handle, fd)) {<br>
+               close(fd);<br>
+               rc = -EINVAL;<br>
+               goto free_vec;<br>
+       }<br>
+<br>
+       /* EAL reads the 8 byte eventfd counter only for VFIO handle types */<br>
+       if (plt_intr_type_set(irq_vec->handle, plt_intr_type_get(intr_handle))) {<br>
+               rc = -EINVAL;<br>
+               goto free_vec;<br>
+       }<br>
+<br>
+       plt_spinlock_lock(&plt_irq_vec_lock);<br>
+       if (irq_vec_find(intr_handle, vec) != NULL) {<br>
+               plt_spinlock_unlock(&plt_irq_vec_lock);<br>
+               plt_err("Vector:0x%x irq already registered", vec);<br>
+               rc = -EEXIST;<br>
+               goto free_vec;<br>
+       }<br>
+       TAILQ_INSERT_TAIL(&plt_irq_vec_list, irq_vec, next);<br>
+       plt_spinlock_unlock(&plt_irq_vec_lock);<br>
 <br>
         /* Register vector interrupt callback */<br>
-       rc = plt_intr_callback_register(tmp_handle, cb, data);<br>
+       rc = plt_intr_callback_register(irq_vec->handle, cb, data);<br>
         if (rc) {<br>
                 plt_err("Failed to register vector:0x%x irq callback.", vec);<br>
-               return rc;<br>
+               goto remove_vec;<br>
         }<br>
 <br>
         rc = plt_intr_efds_index_set(intr_handle, vec, fd);<br>
-       if (rc)<br>
-               return rc;<br>
+       if (rc) {<br>
+               plt_intr_callback_unregister(irq_vec->handle, cb, data);<br>
+               goto remove_vec;<br>
+       }<br>
 <br>
         nb_efd = (vec > (uint32_t)plt_intr_nb_efd_get(intr_handle)) ?<br>
                          vec :<br>
@@ -199,15 +276,23 @@ plt_irq_register(struct plt_intr_handle *intr_handle, plt_intr_callback_fn cb, v<br>
 <br>
         /* Enable MSIX vectors to VFIO */<br>
         return irq_config(intr_handle, vec);<br>
+<br>
+remove_vec:<br>
+       plt_spinlock_lock(&plt_irq_vec_lock);<br>
+       TAILQ_REMOVE(&plt_irq_vec_list, irq_vec, next);<br>
+       plt_spinlock_unlock(&plt_irq_vec_lock);<br>
+free_vec:<br>
+       irq_vec_free(irq_vec);<br>
+       return rc;<br>
 }<br>
 <br>
 void<br>
 plt_irq_unregister(struct plt_intr_handle *intr_handle, plt_intr_callback_fn cb, void *data,<br>
                    unsigned int vec)<br>
 {<br>
-       struct plt_intr_handle *tmp_handle;<br>
+       struct plt_irq_vec *irq_vec;<br>
         uint8_t retries = 5; /* 5 ms */<br>
-       int rc, fd;<br>
+       int rc;<br>
 <br>
         if (vec > (uint32_t)plt_intr_max_intr_get(intr_handle)) {<br>
                 plt_err("Error unregistering MSI-X interrupts vec:%d > %d", vec,<br>
@@ -215,17 +300,23 @@ plt_irq_unregister(struct plt_intr_handle *intr_handle, plt_intr_callback_fn cb,<br>
                 return;<br>
         }<br>
 <br>
-       tmp_handle = intr_handle;<br>
-       fd = plt_intr_efds_index_get(intr_handle, vec);<br>
-       if (fd == -1)<br>
+       plt_spinlock_lock(&plt_irq_vec_lock);<br>
+       irq_vec = irq_vec_find(intr_handle, vec);<br>
+       plt_spinlock_unlock(&plt_irq_vec_lock);<br>
+       if (irq_vec == NULL) {<br>
+               if (plt_intr_efds_index_get(intr_handle, vec) != -1)<br>
+                       plt_err("Error unregistering MSI-X vec %d cb, not registered", vec);<br>
                 return;<br>
+       }<br>
 <br>
-       if (plt_intr_fd_set(tmp_handle, fd))<br>
+       if (irq_vec->cb != cb || irq_vec->data != data) {<br>
+               plt_err("MSI-X vec %d registered with a different callback", vec);<br>
                 return;<br>
+       }<br>
 <br>
         do {<br>
                 /* Un-register callback func from platform lib */<br>
-               rc = plt_intr_callback_unregister(tmp_handle, cb, data);<br>
+               rc = plt_intr_callback_unregister(irq_vec->handle, cb, data);<br>
                 /* Retry only if -EAGAIN */<br>
                 if (rc != -EAGAIN)<br>
                         break;<br>
@@ -238,15 +329,18 @@ plt_irq_unregister(struct plt_intr_handle *intr_handle, plt_intr_callback_fn cb,<br>
                 return;<br>
         }<br>
 <br>
+       plt_spinlock_lock(&plt_irq_vec_lock);<br>
+       TAILQ_REMOVE(&plt_irq_vec_list, irq_vec, next);<br>
+       plt_spinlock_unlock(&plt_irq_vec_lock);<br>
+<br>
         plt_base_dbg("Disable vector:0x%x for vfio (efds: %d, max:%d)", vec,<br>
                      plt_intr_nb_efd_get(intr_handle), plt_intr_max_intr_get(intr_handle));<br>
 <br>
-       if (plt_intr_efds_index_get(intr_handle, vec) != -1)<br>
-               close(plt_intr_efds_index_get(intr_handle, vec));<br>
         /* Disable MSIX vectors from VFIO */<br>
         plt_intr_efds_index_set(intr_handle, vec, -1);<br>
-<br>
         irq_config(intr_handle, vec);<br>
+<br>
+       irq_vec_free(irq_vec);<br>
 }<br>
 #endif<br>
 <br>
--<br>
2.43.0<br>
<br>
</div>
</div>
</div>
</body>
</html>