[PATCH v4-S3 42/65] event/dpaa2: report available DPIO count and fix create cleanup

Prashant Gupta prashant.gupta_3 at nxp.com
Fri Oct 23 15:43:22 CEST 2026


From: Jun Yang <jun.yang at nxp.com>

max_event_ports was reported as the total number of DPAA2_IO devices,
including DPIOs already claimed by other users(affine portals).
Add an internal helper rte_dpaa2_available_dpio_device() that counts
only DPIOs with a zero reference count, and use it so the eventdev
advertises the number of ports it can actually acquire.

Rework dpaa2_eventdev_create() error handling. The device creation
loop now iterates over a fixed range and, on any DPCI attach failure,
frees the DPCON and DPCI acquired for the current event queue and
breaks out instead of returning with resources leaked. A single done
path releases the DPCON/DPCI of all event queues set up so far when an
error occurred, and the function returns a meaningful error code
rather than a fixed -EFAULT.

Signed-off-by: Jun Yang <jun.yang at nxp.com>
---
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 15 +++++++
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.h |  4 ++
 drivers/event/dpaa2/dpaa2_eventdev.c     | 52 +++++++++++++++---------
 drivers/event/dpaa2/dpaa2_eventdev.h     | 23 ++++++++++-
 4 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index 55dcef41d1..654472b284 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -465,6 +465,21 @@ void rte_dpaa2_free_dpio_device(struct dpaa2_dpio_dev *dpio_dev)
 	dpaa2_put_qbman_swp(dpio_dev);
 }
 
+RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_available_dpio_device)
+uint16_t
+rte_dpaa2_available_dpio_device(void)
+{
+	struct dpaa2_dpio_dev *dpio_dev = NULL;
+	uint16_t available_num = 0;
+
+	TAILQ_FOREACH(dpio_dev, &dpio_dev_list, next) {
+		if (dpio_dev && !rte_atomic16_read(&dpio_dev->ref_count))
+			available_num++;
+	}
+
+	return available_num;
+}
+
 static void
 dpaa2_close_dpio_device(int object_id)
 {
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h
index ae0f5993d6..d28fdb03b7 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h
@@ -78,4 +78,8 @@ __rte_internal
 void
 rte_dpaa2_free_dpio_device(struct dpaa2_dpio_dev *dpio_dev);
 
+__rte_internal
+uint16_t
+rte_dpaa2_available_dpio_device(void);
+
 #endif /* _DPAA2_HW_DPIO_H_ */
diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c
index 4c20e26870..5badc17af7 100644
--- a/drivers/event/dpaa2/dpaa2_eventdev.c
+++ b/drivers/event/dpaa2/dpaa2_eventdev.c
@@ -401,7 +401,7 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev,
 		DPAA2_EVENT_MAX_QUEUE_PRIORITY_LEVELS;
 	dev_info->max_event_priority_levels =
 		DPAA2_EVENT_MAX_EVENT_PRIORITY_LEVELS;
-	dev_info->max_event_ports = rte_fslmc_get_device_count(DPAA2_IO);
+	dev_info->max_event_ports = rte_dpaa2_available_dpio_device();
 	if (dev_info->max_event_ports > dev_info->max_event_queues)
 		dev_info->max_event_ports = dev_info->max_event_queues;
 	/* we only support dpio up to number of cores */
@@ -1209,17 +1209,18 @@ static int
 dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev)
 {
 	struct rte_eventdev *eventdev;
-	struct dpaa2_eventdev *priv;
+	struct dpaa2_eventdev *priv = NULL;
 	struct dpaa2_dpcon_dev *dpcon_dev = NULL;
 	struct dpaa2_dpci_dev *dpci_dev = NULL;
 	struct dpaa2_eventq *evq_info;
-	int ret;
+	int ret = 0, i;
 
 	eventdev = rte_event_pmd_vdev_init(name,
 		sizeof(struct dpaa2_eventdev), rte_socket_id(), vdev);
 	if (!eventdev) {
+		ret = -ENOMEM;
 		DPAA2_EVENTDEV_ERR("Failed to create Event device %s", name);
-		goto fail;
+		goto done;
 	}
 
 	eventdev->dev_ops = &dpaa2_eventdev_ops;
@@ -1237,8 +1238,8 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev)
 	priv = eventdev->data->dev_private;
 	memset(priv, 0, sizeof(struct dpaa2_eventdev));
 
-	do {
-		evq_info = &priv->evq_info[priv->max_event_queues];
+	for (i = 0; i < DPAA2_EVENT_MAX_QUEUES; i++) {
+		evq_info = &priv->evq_info[i];
 		dpcon_dev = rte_dpaa2_alloc_dpcon_dev();
 		if (!dpcon_dev)
 			break;
@@ -1256,10 +1257,8 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev)
 			dpaa2_eventdev_process_parallel,
 			&evq_info->dpci_txqs[RTE_SCHED_TYPE_PARALLEL]);
 		if (ret) {
-			rte_dpaa2_free_dpcon_dev(evq_info->dpcon);
-			rte_dpaa2_free_dpci_dev(evq_info->dpci);
 			DPAA2_EVENTDEV_ERR("DPCI attach parallel RX failed: err(%d)", ret);
-			break;
+			goto err_break;
 		}
 
 		ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON,
@@ -1267,10 +1266,8 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev)
 			dpaa2_eventdev_process_atomic,
 			&evq_info->dpci_txqs[RTE_SCHED_TYPE_ATOMIC]);
 		if (ret) {
-			rte_dpaa2_free_dpcon_dev(evq_info->dpcon);
-			rte_dpaa2_free_dpci_dev(evq_info->dpci);
 			DPAA2_EVENTDEV_ERR("DPCI attach atomic RX failed: err(%d)", ret);
-			break;
+			goto err_break;
 		}
 
 		/** TO DO: order schedule.*/
@@ -1279,17 +1276,32 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev)
 		evq_info->event_queue_id = priv->max_event_queues;
 
 		priv->max_event_queues++;
-		if (priv->max_event_queues >= DPAA2_EVENT_MAX_QUEUES)
-			break;
-	} while (dpcon_dev && dpci_dev);
-
-	DPAA2_EVENTDEV_INFO("%s eventdev created", name);
+		continue;
+err_break:
+		if (evq_info->dpcon)
+			rte_dpaa2_free_dpcon_dev(evq_info->dpcon);
+		if (evq_info->dpci)
+			rte_dpaa2_free_dpci_dev(evq_info->dpci);
+		break;
+	}
 
 done:
+	if (ret && priv) {
+		for (i = 0; i < priv->max_event_queues; i++) {
+			evq_info = &priv->evq_info[i];
+			if (evq_info->dpcon)
+				rte_dpaa2_free_dpcon_dev(evq_info->dpcon);
+			if (evq_info->dpci)
+				rte_dpaa2_free_dpci_dev(evq_info->dpci);
+		}
+	}
 	event_dev_probing_finish(eventdev);
-	return 0;
-fail:
-	return -EFAULT;
+	if (ret)
+		DPAA2_EVENTDEV_ERR("Failed(%d) to create event device(%s)", ret, name);
+	else
+		DPAA2_EVENTDEV_INFO("Create event device(%s)", name);
+
+	return ret;
 }
 
 static int
diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h
index c0ce42c83f..af1c831b92 100644
--- a/drivers/event/dpaa2/dpaa2_eventdev.h
+++ b/drivers/event/dpaa2/dpaa2_eventdev.h
@@ -8,6 +8,9 @@
 #include <eventdev_pmd.h>
 #include <eventdev_pmd_vdev.h>
 #include <rte_atomic.h>
+#include <rte_common.h>
+#include <rte_eventdev.h>
+
 #include <mc/fsl_dpcon.h>
 #include <mc/fsl_mc_sys.h>
 
@@ -15,6 +18,7 @@
 
 #define DPAA2_EVENT_DEFAULT_DPCI_PRIO 0
 
+#define DPAA2_EVENT_MAX_PORTS			16
 #define DPAA2_EVENT_MAX_QUEUES			16
 #define DPAA2_EVENT_MIN_DEQUEUE_TIMEOUT		1
 #define DPAA2_EVENT_MAX_DEQUEUE_TIMEOUT		(UINT32_MAX - 1)
@@ -51,7 +55,24 @@ enum {
  * the ethdev to eventdev with DPAA2 devices.
  */
 
-#define DPAA2_EVENTQ_LINK_CONF_MAX 4 /** Max schedule type + 1.*/
+/*
+ * Size of the per-eventq dpci_txqs[] array. It is indexed directly by
+ * event->sched_type, so it must be (largest sched-type value) + 1.
+ * RTE_SCHED_TYPE_{ORDERED,ATOMIC,PARALLEL} are plain macros (0, 1, 2) with
+ * no upstream MAX definition, so compute the maximum explicitly here rather
+ * than assuming PARALLEL is numerically largest. If the sched-type values are
+ * ever renumbered upstream, this expression still yields the correct bound.
+ *
+ * A plain ternary max is used (not RTE_MAX): RTE_MAX expands to a GCC
+ * statement-expression ({ ... }), which is not a constant expression and
+ * cannot size an array at file scope.
+ */
+#define DPAA2_EVENTQ_MAX2(a, b) ((a) > (b) ? (a) : (b))
+#define DPAA2_EVENTQ_LINK_CONF_MAX \
+	(DPAA2_EVENTQ_MAX2(RTE_SCHED_TYPE_ORDERED, \
+		DPAA2_EVENTQ_MAX2(RTE_SCHED_TYPE_ATOMIC, \
+			RTE_SCHED_TYPE_PARALLEL)) + 1)
+
 struct dpaa2_eventq {
 	int valid;
 	uint8_t link_num;
-- 
2.43.0



More information about the dev mailing list