NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
pe_common.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <unistd.h>
27 #include <time.h>
28 
29 #include <doca_log.h>
30 #include <doca_mmap.h>
31 #include <doca_buf.h>
32 #include <doca_buf_inventory.h>
33 #include <doca_ctx.h>
34 #include <doca_types.h>
35 #include <doca_dma.h>
36 #include <doca_pe.h>
37 
38 #include <samples/common.h>
39 #include "pe_common.h"
40 
41 DOCA_LOG_REGISTER(PE::COMMON);
42 
47 #define EXIT_ON_FAILURE(_expression_) \
48  { \
49  doca_error_t _status_ = _expression_; \
50 \
51  if (_status_ != DOCA_SUCCESS) { \
52  DOCA_LOG_ERR("%s failed with status %s", __func__, doca_error_get_descr(_status_)); \
53  return _status_; \
54  } \
55  }
56 
57 /*
58  * Process completed task
59  *
60  * @details This function verifies that the destination buffer contains the expected value.
61  *
62  * @dma_task [in]: Completed task
63  * @expected_value [in]: Expected value in the destination.
64  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
65  */
66 doca_error_t process_completed_dma_memcpy_task(struct doca_dma_task_memcpy *dma_task, uint8_t expected_value)
67 {
68  const struct doca_buf *dest = doca_dma_task_memcpy_get_dst(dma_task);
69  uint8_t *dst = NULL;
70  size_t dst_len = 0;
71  size_t i = 0;
72 
73  EXIT_ON_FAILURE(doca_buf_get_data(dest, (void **)&dst));
74  EXIT_ON_FAILURE(doca_buf_get_len(dest, &dst_len));
75 
76  for (i = 0; i < dst_len; i++) {
77  if (dst[i] != expected_value) {
78  DOCA_LOG_ERR("Memcpy failed: Expected %d, received %d at index %zu", expected_value, dst[i], i);
80  }
81  }
82 
83  return DOCA_SUCCESS;
84 }
85 
86 /*
87  * Free task buffers
88  *
89  * @details This function releases source and destination buffers that are set to a DMA memcpy task.
90  *
91  * @dma_task [in]: task
92  */
93 doca_error_t free_dma_memcpy_task_buffers(struct doca_dma_task_memcpy *dma_task)
94 {
95  const struct doca_buf *src = doca_dma_task_memcpy_get_src(dma_task);
96  struct doca_buf *dst = doca_dma_task_memcpy_get_dst(dma_task);
97 
102  EXIT_ON_FAILURE(doca_buf_dec_refcount((struct doca_buf *)src, NULL));
104 
105  return DOCA_SUCCESS;
106 }
107 
108 doca_error_t dma_task_free(struct doca_dma_task_memcpy *dma_task)
109 {
119 
121 
122  return DOCA_SUCCESS;
123 }
124 
132 {
133  DOCA_LOG_INFO("Allocating buffer with size of %zu", state->buffer_size);
134 
135  state->buffer = (uint8_t *)malloc(state->buffer_size);
136  if (state->buffer == NULL)
137  return DOCA_ERROR_NO_MEMORY;
138 
139  state->available_buffer = state->buffer;
140 
141  return DOCA_SUCCESS;
142 }
143 
156  struct doca_dma *dma,
157  uint32_t num_tasks,
158  size_t dma_buffer_size,
159  struct doca_dma_task_memcpy **tasks)
160 {
161  uint32_t task_id = 0;
162 
163  DOCA_LOG_INFO("Allocating tasks");
164 
165  for (task_id = 0; task_id < num_tasks; task_id++) {
166  struct doca_buf *source = NULL;
167  struct doca_buf *destination = NULL;
168  union doca_data user_data = {0};
169 
170  /* User data will be used to verify copy content */
171  user_data.u64 = (task_id + 1);
172 
173  /* Use doca_buf_inventory_buf_get_by_data to initialize the source buffer */
175  state->mmap,
176  state->available_buffer,
177  dma_buffer_size,
178  &source));
179 
180  memset(state->available_buffer, (task_id + 1), dma_buffer_size);
181  state->available_buffer += dma_buffer_size;
182 
188  state->mmap,
189  state->available_buffer,
190  dma_buffer_size,
191  &destination));
192 
193  memset(state->available_buffer, 0, dma_buffer_size);
194  state->available_buffer += dma_buffer_size;
195 
196  EXIT_ON_FAILURE(doca_dma_task_memcpy_alloc_init(dma, source, destination, user_data, &tasks[task_id]));
197  }
198 
199  return DOCA_SUCCESS;
200 }
201 
211 doca_error_t submit_dma_tasks(uint32_t num_tasks, struct doca_dma_task_memcpy **tasks)
212 {
213  uint32_t task_id = 0;
214 
215  DOCA_LOG_INFO("Submitting tasks");
216 
217  for (task_id = 0; task_id < num_tasks; task_id++)
219 
220  return DOCA_SUCCESS;
221 }
222 
223 /*
224  * Check if DOCA device is DMA capable
225  *
226  * @devinfo [in]: Device to check
227  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
228  */
229 static doca_error_t check_dev_dma_capable(struct doca_devinfo *devinfo)
230 {
232 
233  if (status != DOCA_SUCCESS)
234  return status;
235 
236  return DOCA_SUCCESS;
237 }
238 
246 {
247  DOCA_LOG_INFO("Opening device");
248 
250 
251  return DOCA_SUCCESS;
252 }
253 
261 {
262  DOCA_LOG_INFO("Creating PE");
263 
265 
266  return DOCA_SUCCESS;
267 }
268 
276 {
277  DOCA_LOG_INFO("Creating MMAP");
278 
281  EXIT_ON_FAILURE(doca_mmap_add_dev(state->mmap, state->device));
284 
285  return DOCA_SUCCESS;
286 }
287 
295 {
296  DOCA_LOG_INFO("Creating buf inventory");
297 
300 
301  return DOCA_SUCCESS;
302 }
303 
312 {
313  if (state->pe != NULL)
314  (void)doca_pe_destroy(state->pe);
315 
316  if (state->inventory != NULL) {
317  (void)doca_buf_inventory_stop(state->inventory);
319  }
320 
321  if (state->mmap != NULL) {
322  (void)doca_mmap_stop(state->mmap);
323  (void)doca_mmap_destroy(state->mmap);
324  }
325 
326  if (state->device != NULL)
327  (void)doca_dev_close(state->device);
328 
329  if (state->buffer != NULL)
330  free(state->buffer);
331 }
332 
340 doca_error_t poll_for_completion(struct pe_sample_state_base *state, uint32_t num_tasks)
341 {
342  DOCA_LOG_INFO("Polling until all tasks are completed");
343 
344  /* This loop ticks the progress engine */
345  while (state->num_completed_tasks < num_tasks) {
350  (void)doca_pe_progress(state->pe);
351  }
352 
353  DOCA_LOG_INFO("All tasks are completed");
354 
355  return DOCA_SUCCESS;
356 }
#define NULL
Definition: __stddef_null.h:26
doca_error_t open_doca_device_with_capabilities(tasks_check func, struct doca_dev **retval)
Definition: common.c:188
static uint64_t *restrict src
Definition: dpaintrin.h:230
DOCA_STABLE doca_error_t doca_buf_inventory_destroy(struct doca_buf_inventory *inventory)
Destroy buffer inventory structure.
static doca_error_t doca_buf_inventory_buf_get_by_addr(struct doca_buf_inventory *inventory, struct doca_mmap *mmap, void *addr, size_t len, struct doca_buf **buf)
Allocate single element from buffer inventory and point it to the buffer defined by addr & len argume...
static doca_error_t doca_buf_inventory_buf_get_by_data(struct doca_buf_inventory *inventory, struct doca_mmap *mmap, void *data, size_t data_len, struct doca_buf **buf)
Allocate single element from buffer inventory and point it to the buffer defined by data & data_len a...
DOCA_STABLE doca_error_t doca_buf_inventory_start(struct doca_buf_inventory *inventory)
Start element retrieval from inventory.
DOCA_STABLE doca_error_t doca_buf_inventory_create(size_t num_elements, struct doca_buf_inventory **inventory)
Allocates buffer inventory with default/unset attributes.
DOCA_STABLE doca_error_t doca_buf_inventory_stop(struct doca_buf_inventory *inventory)
Stop element retrieval from inventory.
DOCA_STABLE doca_error_t doca_buf_dec_refcount(struct doca_buf *buf, uint16_t *refcount)
Decrease the object reference count by 1, if 0 reached, return the element back to the inventory.
DOCA_STABLE doca_error_t doca_buf_get_len(const struct doca_buf *buf, size_t *len)
Get the buffer's length.
DOCA_STABLE doca_error_t doca_buf_get_data(const struct doca_buf *buf, void **data)
Get the buffer's data.
DOCA_STABLE doca_error_t doca_dev_close(struct doca_dev *dev)
Destroy allocated local device instance.
DOCA_STABLE const struct doca_buf * doca_dma_task_memcpy_get_src(const struct doca_dma_task_memcpy *task)
This method gets source buffer from memcpy task.
DOCA_STABLE struct doca_task * doca_dma_task_memcpy_as_task(struct doca_dma_task_memcpy *task)
This method converts a memcpy task to doca_task.
DOCA_STABLE doca_error_t doca_dma_task_memcpy_alloc_init(struct doca_dma *dma, const struct doca_buf *src, struct doca_buf *dst, union doca_data user_data, struct doca_dma_task_memcpy **task)
This method allocates and initializes a DMA memcpy task.
DOCA_STABLE struct doca_buf * doca_dma_task_memcpy_get_dst(const struct doca_dma_task_memcpy *task)
This method gets destination buffer from memcpy task.
DOCA_STABLE doca_error_t doca_dma_cap_task_memcpy_is_supported(const struct doca_devinfo *devinfo)
enum doca_error doca_error_t
DOCA API return codes.
@ DOCA_ERROR_INVALID_VALUE
Definition: doca_error.h:44
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_NO_MEMORY
Definition: doca_error.h:45
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
Definition: doca_log.h:486
DOCA_STABLE doca_error_t doca_mmap_set_memrange(struct doca_mmap *mmap, void *addr, size_t len)
Set the memory range of DOCA memory map.
DOCA_STABLE doca_error_t doca_mmap_destroy(struct doca_mmap *mmap)
Destroy DOCA Memory Map structure.
DOCA_STABLE doca_error_t doca_mmap_create(struct doca_mmap **mmap)
Allocates zero size memory map object with default/unset attributes.
DOCA_STABLE doca_error_t doca_mmap_set_permissions(struct doca_mmap *mmap, uint32_t access_mask)
Set access flags of the registered memory.
DOCA_STABLE doca_error_t doca_mmap_start(struct doca_mmap *mmap)
Start DOCA Memory Map.
DOCA_STABLE doca_error_t doca_mmap_stop(struct doca_mmap *mmap)
Stop DOCA Memory Map.
DOCA_STABLE doca_error_t doca_mmap_add_dev(struct doca_mmap *mmap, struct doca_dev *dev)
Register DOCA memory map on a given device.
DOCA_STABLE doca_error_t doca_pe_destroy(struct doca_pe *pe)
Destroy doca progress engine.
DOCA_STABLE doca_error_t doca_task_submit(struct doca_task *task)
Submit a task to a progress engine.
DOCA_STABLE uint8_t doca_pe_progress(struct doca_pe *pe)
Run the progress engine.
DOCA_STABLE doca_error_t doca_pe_create(struct doca_pe **pe)
Creates DOCA progress engine.
DOCA_STABLE void doca_task_free(struct doca_task *task)
Free a task back to where it was allocated from.
@ DOCA_ACCESS_FLAG_LOCAL_READ_WRITE
Definition: doca_types.h:83
void pe_sample_base_cleanup(struct pe_sample_state_base *state)
Definition: pe_common.c:311
doca_error_t allocate_buffer(struct pe_sample_state_base *state)
Definition: pe_common.c:131
#define EXIT_ON_FAILURE(_expression_)
Definition: pe_common.c:47
doca_error_t create_buf_inventory(struct pe_sample_state_base *state)
Definition: pe_common.c:294
doca_error_t dma_task_free(struct doca_dma_task_memcpy *dma_task)
Definition: pe_common.c:108
doca_error_t create_mmap(struct pe_sample_state_base *state)
Definition: pe_common.c:275
doca_error_t free_dma_memcpy_task_buffers(struct doca_dma_task_memcpy *dma_task)
Definition: pe_common.c:93
doca_error_t submit_dma_tasks(uint32_t num_tasks, struct doca_dma_task_memcpy **tasks)
Definition: pe_common.c:211
DOCA_LOG_REGISTER(PE::COMMON)
doca_error_t poll_for_completion(struct pe_sample_state_base *state, uint32_t num_tasks)
Definition: pe_common.c:340
doca_error_t create_pe(struct pe_sample_state_base *state)
Definition: pe_common.c:260
doca_error_t open_device(struct pe_sample_state_base *state)
Definition: pe_common.c:245
doca_error_t allocate_dma_tasks(struct pe_sample_state_base *state, struct doca_dma *dma, uint32_t num_tasks, size_t dma_buffer_size, struct doca_dma_task_memcpy **tasks)
Definition: pe_common.c:155
static doca_error_t check_dev_dma_capable(struct doca_devinfo *devinfo)
Definition: pe_common.c:229
doca_error_t process_completed_dma_memcpy_task(struct doca_dma_task_memcpy *dma_task, uint8_t expected_value)
Definition: pe_common.c:66
uint8_t * available_buffer
Definition: pe_common.h:53
struct doca_dev * device
Definition: pe_common.h:39
size_t buf_inventory_size
Definition: pe_common.h:45
uint8_t * buffer
Definition: pe_common.h:52
struct doca_buf_inventory * inventory
Definition: pe_common.h:41
struct doca_mmap * mmap
Definition: pe_common.h:40
struct doca_pe * pe
Definition: pe_common.h:42
uint32_t num_completed_tasks
Definition: pe_common.h:56
Convenience type for representing opaque data.
Definition: doca_types.h:56
uint64_t u64
Definition: doca_types.h:58