[RFC,3/3] eventdev: add SW event prefetch hint

Message ID 20240910083117.4281-4-pbhagavatula@marvell.com (mailing list archive)
State RFC
Delegated to: Jerin Jacob
Headers
Series Introduce event prefetching |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/github-robot: build success github build: passed
ci/iol-unit-amd64-testing success Testing PASS
ci/iol-compile-amd64-testing success Testing PASS
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/intel-Functional success Functional PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-sample-apps-testing success Testing PASS
ci/iol-marvell-Functional success Functional Testing PASS
ci/iol-intel-Functional success Functional Testing PASS

Commit Message

Pavan Nikhilesh Bhagavatula Sept. 10, 2024, 8:31 a.m. UTC
From: Pavan Nikhilesh <pbhagavatula@marvell.com>

Add a new eventdev API to provide a hint to the eventdev PMD to
prefetch the next event into the event port, without releasing
the current flow context.
Event device that support this feature advertises the capability
using the RTE_EVENT_DEV_CAP_SW_PREFETCH capability flag.

Application can invoke `rte_event_port_prefetch` to hint the PMD.

Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
---
 doc/guides/prog_guide/eventdev/eventdev.rst |  8 ++++
 lib/eventdev/eventdev_pmd.h                 |  2 +
 lib/eventdev/eventdev_private.c             |  9 ++++
 lib/eventdev/eventdev_trace_points.c        |  3 ++
 lib/eventdev/rte_eventdev.h                 | 49 +++++++++++++++++++++
 lib/eventdev/rte_eventdev_core.h            |  4 ++
 lib/eventdev/rte_eventdev_trace_fp.h        |  8 ++++
 lib/eventdev/version.map                    |  2 +
 8 files changed, 85 insertions(+)
  

Patch

diff --git a/doc/guides/prog_guide/eventdev/eventdev.rst b/doc/guides/prog_guide/eventdev/eventdev.rst
index 8b6085512d..ea05de53f5 100644
--- a/doc/guides/prog_guide/eventdev/eventdev.rst
+++ b/doc/guides/prog_guide/eventdev/eventdev.rst
@@ -390,6 +390,14 @@  To enable or disable event prefetching at a given event port, the application ca
    // Disable prefetching if thread is about to be scheduled out and issue dequeue() to drain
    // pending events.
 
+Event Prefetch Hint can be used to provide a hint to the eventdev PMD to prefetch the next event
+without releasing the current flow context. Event device that support this feature advertises the
+capability using the ``RTE_EVENT_DEV_CAP_SW_PREFETCH`` capability flag.
+If prefetching is already enabled at a event device or event port level then the hint is ignored.
+
+.. code-block:: c
+
+   rte_event_port_prefetch(dev_id, port_id, RTE_EVENT_DEV_PREFETCH);
 
 Starting the EventDev
 ~~~~~~~~~~~~~~~~~~~~~
diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h
index d93c11e9f1..698bdcc14f 100644
--- a/lib/eventdev/eventdev_pmd.h
+++ b/lib/eventdev/eventdev_pmd.h
@@ -186,6 +186,8 @@  struct __rte_cache_aligned rte_eventdev {
 	/**< Pointer to PMD Event switch profile function. */
 	event_prefetch_modify_t prefetch_modify;
 	/**< Pointer to PMD Event port prefetch modify function.  */
+	event_prefetch_t prefetch;
+	/**< Pointer to PMD Event port prefetch function. */
 
 	uint64_t reserved_64s[3]; /**< Reserved for future fields */
 	void *reserved_ptrs[3];	  /**< Reserved for future fields */
diff --git a/lib/eventdev/eventdev_private.c b/lib/eventdev/eventdev_private.c
index 6e8beb29ad..39d5234551 100644
--- a/lib/eventdev/eventdev_private.c
+++ b/lib/eventdev/eventdev_private.c
@@ -104,6 +104,13 @@  dummy_event_port_prefetch_modify(__rte_unused void *port,
 	return -EINVAL;
 }
 
+static void
+dummy_event_port_prefetch(__rte_unused void *port,
+			  __rte_unused rte_event_dev_prefetch_type_t prefetch)
+{
+	RTE_EDEV_LOG_ERR("prefetch requested for unconfigured event device");
+}
+
 void
 event_dev_fp_ops_reset(struct rte_event_fp_ops *fp_op)
 {
@@ -123,6 +130,7 @@  event_dev_fp_ops_reset(struct rte_event_fp_ops *fp_op)
 		.dma_enqueue = dummy_event_dma_adapter_enqueue,
 		.profile_switch = dummy_event_port_profile_switch,
 		.prefetch_modify = dummy_event_port_prefetch_modify,
+		.prefetch = dummy_event_port_prefetch,
 		.data = dummy_data,
 	};
 
@@ -146,5 +154,6 @@  event_dev_fp_ops_set(struct rte_event_fp_ops *fp_op,
 	fp_op->dma_enqueue = dev->dma_enqueue;
 	fp_op->profile_switch = dev->profile_switch;
 	fp_op->prefetch_modify = dev->prefetch_modify;
+	fp_op->prefetch = dev->prefetch;
 	fp_op->data = dev->data->ports;
 }
diff --git a/lib/eventdev/eventdev_trace_points.c b/lib/eventdev/eventdev_trace_points.c
index e0547d18c6..199cfa742f 100644
--- a/lib/eventdev/eventdev_trace_points.c
+++ b/lib/eventdev/eventdev_trace_points.c
@@ -52,6 +52,9 @@  RTE_TRACE_POINT_REGISTER(rte_eventdev_trace_port_profile_switch,
 RTE_TRACE_POINT_REGISTER(rte_eventdev_trace_port_prefetch_modify,
 	lib.eventdev.port.prefetch.modify)
 
+RTE_TRACE_POINT_REGISTER(rte_eventdev_trace_port_prefetch,
+	lib.eventdev.port.prefetch)
+
 /* Eventdev Rx adapter trace points */
 RTE_TRACE_POINT_REGISTER(rte_eventdev_trace_eth_rx_adapter_create,
 	lib.eventdev.rx.adapter.create)
diff --git a/lib/eventdev/rte_eventdev.h b/lib/eventdev/rte_eventdev.h
index 1bc6c48dd3..d487389a2c 100644
--- a/lib/eventdev/rte_eventdev.h
+++ b/lib/eventdev/rte_eventdev.h
@@ -480,6 +480,15 @@  struct rte_event;
  * @see rte_event_port_prefetch_modify()
  */
 
+#define RTE_EVENT_DEV_CAP_SW_PREFETCH (1ULL << 19)
+/**< Event device supports software prefetching.
+ *
+ * When this flag is set, the application can issue prefetch request on
+ * a event port.
+ *
+ * @see rte_event_port_prefetch()
+ */
+
 /* Event device priority levels */
 #define RTE_EVENT_DEV_PRIORITY_HIGHEST   0
 /**< Highest priority level for events and queues.
@@ -2977,6 +2986,46 @@  rte_event_port_prefetch_modify(uint8_t dev_id, uint8_t port_id, rte_event_dev_pr
 	return fp_ops->prefetch_modify(port, type);
 }
 
+/**
+ * Provide a hint to the event device to prefetch events to event port .
+ *
+ * Hint the event device to prefetch events to the event port.
+ * The call doesn't not guarantee that the events will be prefetched.
+ * The call doesn't release the flow context currently held by the event port.
+ * The event device should support RTE_EVENT_DEV_CAP_SW_PREFETCH capability.
+ *
+ * When prefetching is enabled at an event device or event port level, the hint
+ * is ignored.
+ *
+ * Subsequent calls to rte_event_dequeue_burst() will dequeue the prefetch events
+ * but prefetch operation is not issued again.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param port_id
+ *   The identifier of the event port.
+ * @param type
+ *   The prefetch type to use on the event port.
+ */
+static inline void
+rte_event_port_prefetch(uint8_t dev_id, uint8_t port_id, rte_event_dev_prefetch_type_t type)
+{
+	const struct rte_event_fp_ops *fp_ops;
+	void *port;
+
+	fp_ops = &rte_event_fp_ops[dev_id];
+	port = fp_ops->data[port_id];
+
+#ifdef RTE_LIBRTE_EVENTDEV_DEBUG
+	if (dev_id >= RTE_EVENT_MAX_DEVS || port_id >= RTE_EVENT_MAX_PORTS_PER_DEV)
+		return;
+	if (port == NULL)
+		return;
+#endif
+	rte_eventdev_trace_port_prefetch(dev_id, port_id, type);
+
+	fp_ops->prefetch(port, type);
+}
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/eventdev/rte_eventdev_core.h b/lib/eventdev/rte_eventdev_core.h
index b185fe3654..66edb75649 100644
--- a/lib/eventdev/rte_eventdev_core.h
+++ b/lib/eventdev/rte_eventdev_core.h
@@ -52,6 +52,9 @@  typedef int (*event_profile_switch_t)(void *port, uint8_t profile);
 typedef int (*event_prefetch_modify_t)(void *port, rte_event_dev_prefetch_type_t prefetch_type);
 /**< @internal Modify prefetch type on the event port. */
 
+typedef void (*event_prefetch_t)(void *port, rte_event_dev_prefetch_type_t prefetch_type);
+/**< @internal Issue prefetch on an event port. */
+
 struct __rte_cache_aligned rte_event_fp_ops {
 	void **data;
 	/**< points to array of internal port data pointers */
@@ -81,6 +84,7 @@  struct __rte_cache_aligned rte_event_fp_ops {
 	/**< PMD Event switch profile function. */
 	event_prefetch_modify_t prefetch_modify;
 	/**< PMD Event port prefetch switch. */
+	event_prefetch_t prefetch;
 	uintptr_t reserved[4];
 };
 
diff --git a/lib/eventdev/rte_eventdev_trace_fp.h b/lib/eventdev/rte_eventdev_trace_fp.h
index 06bfd48011..01fa5cba7c 100644
--- a/lib/eventdev/rte_eventdev_trace_fp.h
+++ b/lib/eventdev/rte_eventdev_trace_fp.h
@@ -63,6 +63,14 @@  RTE_TRACE_POINT_FP(
 	rte_trace_point_emit_int(type);
 )
 
+RTE_TRACE_POINT_FP(
+	rte_eventdev_trace_port_prefetch,
+	RTE_TRACE_POINT_ARGS(uint8_t dev_id, uint8_t port_id, int type),
+	rte_trace_point_emit_u8(dev_id);
+	rte_trace_point_emit_u8(port_id);
+	rte_trace_point_emit_int(type);
+)
+
 RTE_TRACE_POINT_FP(
 	rte_eventdev_trace_eth_tx_adapter_enqueue,
 	RTE_TRACE_POINT_ARGS(uint8_t dev_id, uint8_t port_id, void *ev_table,
diff --git a/lib/eventdev/version.map b/lib/eventdev/version.map
index 62c0563fb1..bb291f23e3 100644
--- a/lib/eventdev/version.map
+++ b/lib/eventdev/version.map
@@ -151,6 +151,8 @@  EXPERIMENTAL {
 	# added in 24.11
 	rte_event_port_prefetch_modify;
 	__rte_eventdev_trace_port_prefetch_modify;
+	rte_event_port_prefetch;
+	__rte_eventdev_trace_port_prefetch;
 };
 
 INTERNAL {