<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;">
<span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); text-transform: none;">Acked-by: Nithin Dabilpuram <</span><span style="color: rgb(0, 0, 0); text-transform: none;"><a href="mailto:ndabilpuram@marvell.com" class="ms-outlook-linkify" data-ogsc="" style="text-align: left;" data-outlook-id="053b5f75-9e85-4776-b12c-bf0ceaa56a2e">ndabilpuram@marvell.com</a></span><span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); text-transform: none;">></span></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, 9:50 PM, "Harman Kalra" <hkalra@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;">From: Mohit Kumar Parjapat <mprajapat@marvell.com><br>
<br>
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 a4af517007..3fc374fd2e 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>