[dpdk-dev] [RFC PATCH v2 6/7] hcdev: add communication flag

Thomas Monjalon thomas at monjalon.net
Fri Jul 30 15:55:32 CEST 2021


From: Elena Agostini <eagostini at nvidia.com>

In heterogeneous computing system, processing is not only in the CPU.
Some tasks can be delegated to devices working in parallel.
When mixing network activity with task processing there may be the need
to put in communication the CPU with the device in order to synchronize
operations.

The purpose of this flag is to allow the CPU and the device to
exchange ACKs. A possible use-case is described below.

CPU:
- Trigger some task on the device
- Prepare some data
- Signal to the device the data is ready updating the communication flag

Device:
- Do some pre-processing
- Wait for more data from the CPU polling on the communication flag
- Consume the data prepared by the CPU

Signed-off-by: Elena Agostini <eagostini at nvidia.com>
---
 lib/hcdev/hcdev.c     |  71 ++++++++++++++++++++++++++++
 lib/hcdev/rte_hcdev.h | 107 ++++++++++++++++++++++++++++++++++++++++++
 lib/hcdev/version.map |   4 ++
 3 files changed, 182 insertions(+)

diff --git a/lib/hcdev/hcdev.c b/lib/hcdev/hcdev.c
index 621e0b99bd..e391988e73 100644
--- a/lib/hcdev/hcdev.c
+++ b/lib/hcdev/hcdev.c
@@ -589,3 +589,74 @@ rte_hcdev_free(int16_t dev_id, void *ptr)
 	/* TODO unregister callback */
 	/* TODO rte_free CPU memory */
 }
+
+int
+rte_hcdev_comm_create_flag(uint16_t dev_id, struct rte_hcdev_comm_flag *hcflag,
+		enum rte_hcdev_comm_flag_type mtype)
+{
+	size_t flag_size;
+
+	if (hcflag == NULL) {
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
+	if (mtype != RTE_HCDEV_COMM_FLAG_CPU) {
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
+
+	flag_size = sizeof(uint32_t);
+
+	hcflag->ptr = rte_hcdev_malloc(dev_id, flag_size,
+			RTE_HCDEV_MALLOC_REGISTER_FROM_CPU);
+	if (hcflag->ptr == NULL)
+		return -rte_errno;
+
+	hcflag->mtype = mtype;
+	return 0;
+}
+
+int
+rte_hcdev_comm_destroy_flag(uint16_t dev_id, struct rte_hcdev_comm_flag *hcflag)
+{
+	if (hcflag == NULL) {
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
+
+	return rte_hcdev_free(dev_id, hcflag->ptr);
+}
+
+int
+rte_hcdev_comm_set_flag(struct rte_hcdev_comm_flag *hcflag, uint32_t val)
+{
+	if (hcflag == NULL) {
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
+	if (hcflag->mtype != RTE_HCDEV_COMM_FLAG_CPU) {
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
+
+	RTE_HCDEV_VOLATILE(*hcflag->ptr) = val;
+
+	return 0;
+}
+
+int
+rte_hcdev_comm_get_flag_value(struct rte_hcdev_comm_flag *hcflag, uint32_t *val)
+{
+	if (hcflag == NULL) {
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
+	if (hcflag->mtype != RTE_HCDEV_COMM_FLAG_CPU) {
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
+
+	*val = RTE_HCDEV_VOLATILE(*hcflag->ptr);
+
+	return 0;
+}
diff --git a/lib/hcdev/rte_hcdev.h b/lib/hcdev/rte_hcdev.h
index 11895d9486..7b58041b3c 100644
--- a/lib/hcdev/rte_hcdev.h
+++ b/lib/hcdev/rte_hcdev.h
@@ -38,6 +38,9 @@ extern "C" {
 /** Catch-all callback data. */
 #define RTE_HCDEV_CALLBACK_ANY_DATA ((void *)-1)
 
+/** Access variable as volatile. */
+#define RTE_HCDEV_VOLATILE(x) (*(volatile typeof(x)*)&(x))
+
 /** Store device info. */
 struct rte_hcdev_info {
 	/** Unique identifier name. */
@@ -68,6 +71,18 @@ enum rte_hcdev_event {
 typedef void (rte_hcdev_callback_t)(int16_t dev_id,
 		enum rte_hcdev_event event, void *user_data);
 
+/** Memory where communication flag is allocated. */
+enum rte_hcdev_comm_flag_type {
+	/** Allocate flag on CPU memory visible from device. */
+	RTE_HCDEV_COMM_FLAG_CPU = 0,
+};
+
+/** Communication flag to coordinate CPU with the device. */
+struct rte_hcdev_comm_flag {
+	uint32_t *ptr;
+	enum rte_hcdev_comm_flag_type mtype;
+};
+
 /**
  * @warning
  * @b EXPERIMENTAL: this API may change without prior notice.
@@ -346,6 +361,98 @@ __rte_alloc_size(2);
 __rte_experimental
 int rte_hcdev_free(int16_t dev_id, void *ptr);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create a communication flag that can be shared
+ * between CPU threads and device workload to exchange some status info
+ * (e.g. work is done, processing can start, etc..).
+ *
+ * @param dev_id
+ *   Reference device ID.
+ * @param hcflag
+ *   Pointer to the memory area of the hcflag structure.
+ * @param mtype
+ *   Type of memory to allocate the communication flag.
+ *
+ * @return
+ *   0 on success, -rte_errno otherwise:
+ *   - ENODEV if invalid dev_id
+ *   - EINVAL if invalid inputs
+ *   - ENOTSUP if operation not supported by the driver
+ *   - ENOMEM if out of space
+ *   - EPERM if driver error
+ */
+__rte_experimental
+int rte_hcdev_comm_create_flag(uint16_t dev_id,
+		struct rte_hcdev_comm_flag *hcflag,
+		enum rte_hcdev_comm_flag_type mtype);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Deallocate a communication flag.
+ *
+ * @param dev_id
+ *   Reference device ID.
+ * @param hcflag
+ *   Pointer to the memory area of the hcflag structure.
+ *
+ * @return
+ *   0 on success, -rte_errno otherwise:
+ *   - ENODEV if invalid dev_id
+ *   - EINVAL if NULL hcflag
+ *   - ENOTSUP if operation not supported by the driver
+ *   - EPERM if driver error
+ */
+__rte_experimental
+int rte_hcdev_comm_destroy_flag(uint16_t dev_id,
+		struct rte_hcdev_comm_flag *hcflag);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Set the value of a communication flag as the input value.
+ * Flag memory area is treated as volatile.
+ * The flag must have been allocated with RTE_HCDEV_COMM_FLAG_CPU.
+ *
+ * @param hcflag
+ *   Pointer to the memory area of the hcflag structure.
+ * @param val
+ *   Value to set in the flag.
+ *
+ * @return
+ *   0 on success, -rte_errno otherwise:
+ *   - EINVAL if invalid input params
+ */
+__rte_experimental
+int rte_hcdev_comm_set_flag(struct rte_hcdev_comm_flag *hcflag,
+		uint32_t val);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Get the value of the communication flag.
+ * Flag memory area is treated as volatile.
+ * The flag must have been allocated with RTE_HCDEV_COMM_FLAG_CPU.
+ *
+ * @param hcflag
+ *   Pointer to the memory area of the hcflag structure.
+ * @param val
+ *   Flag output value.
+ *
+ * @return
+ *   0 on success, -rte_errno otherwise:
+ *   - EINVAL if invalid input params
+ */
+__rte_experimental
+int rte_hcdev_comm_get_flag_value(struct rte_hcdev_comm_flag *hcflag,
+		uint32_t *val);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/hcdev/version.map b/lib/hcdev/version.map
index 9195f4f747..da969c7f1f 100644
--- a/lib/hcdev/version.map
+++ b/lib/hcdev/version.map
@@ -6,6 +6,10 @@ EXPERIMENTAL {
 	rte_hcdev_callback_register;
 	rte_hcdev_callback_unregister;
 	rte_hcdev_close;
+	rte_hcdev_comm_create_flag;
+	rte_hcdev_comm_destroy_flag;
+	rte_hcdev_comm_get_flag_value;
+	rte_hcdev_comm_set_flag;
 	rte_hcdev_count_avail;
 	rte_hcdev_find_next;
 	rte_hcdev_free;
-- 
2.31.1



More information about the dev mailing list