NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
cache_invalidate_sample.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024 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 <stdio.h>
27 #include <stdlib.h>
28 #include <stdint.h>
29 #include <stdbool.h>
30 
31 #include <doca_mmap.h>
32 #include <doca_buf.h>
33 #include <doca_buf_inventory.h>
34 #include <doca_ctx.h>
35 #include <doca_dma.h>
36 #include <doca_types.h>
37 #include <doca_log.h>
38 #include <doca_pe.h>
39 #include <doca_mmap_advise.h>
40 
41 #include <samples/common.h>
42 
43 DOCA_LOG_REGISTER(CACHE_INVALIDATE::SAMPLE);
44 
53 #define EXIT_ON_FAILURE(_expression_) \
54  { \
55  doca_error_t _status_ = _expression_; \
56 \
57  if (_status_ != DOCA_SUCCESS) { \
58  DOCA_LOG_ERR("%s failed with status %s", __func__, doca_error_get_descr(_status_)); \
59  return _status_; \
60  } \
61  }
62 
63 #define NUM_TASKS (1)
64 #define DMA_BUFFER_SIZE (1024)
65 #define BUFFER_SIZE (DMA_BUFFER_SIZE * 2 * NUM_TASKS)
66 #define BUF_INVENTORY_SIZE (NUM_TASKS * 2)
67 
72  struct doca_dev *device;
73  struct doca_mmap *mmap;
74  struct doca_buf_inventory *inventory;
75  struct doca_pe *pe;
76 
82  uint8_t *buffer;
83 
84  struct doca_dma *dma;
85  struct doca_ctx *dma_ctx;
86  struct doca_buf *dma_source;
87  struct doca_buf *dma_destination;
88  struct doca_dma_task_memcpy *dma_task;
89 
90  struct doca_mmap_advise *mmap_advise;
91  struct doca_ctx *mmap_advise_ctx;
92  struct doca_mmap_advise_task_invalidate_cache *cache_invalidate_task;
93 
94  bool run_pe;
95 };
96 
104 {
105  DOCA_LOG_INFO("Allocating buffer");
106 
107  state->buffer = (uint8_t *)malloc(BUFFER_SIZE);
108  if (state->buffer == NULL)
109  return DOCA_ERROR_NO_MEMORY;
110 
111  return DOCA_SUCCESS;
112 }
113 
114 /*
115  * Check if DOCA device is DMA and cache invalidate capable
116  *
117  * @devinfo [in]: Device to check
118  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
119  */
120 static doca_error_t check_dev_capable(struct doca_devinfo *devinfo)
121 {
123 
124  if (status != DOCA_SUCCESS)
125  return status;
126 
128  if (status != DOCA_SUCCESS)
129  return status;
130 
131  return DOCA_SUCCESS;
132 }
133 
141 {
142  DOCA_LOG_INFO("Opening device");
143 
145 
146  return DOCA_SUCCESS;
147 }
148 
156 {
157  DOCA_LOG_INFO("Creating MMAP");
158 
161  EXIT_ON_FAILURE(doca_mmap_add_dev(state->mmap, state->device));
164 
165  return DOCA_SUCCESS;
166 }
167 
175 {
176  DOCA_LOG_INFO("Creating buf inventory");
177 
180 
181  return DOCA_SUCCESS;
182 }
183 
191 {
192  DOCA_LOG_INFO("Creating PE");
193 
195 
196  return DOCA_SUCCESS;
197 }
198 
199 /*
200  * DMA Memcpy task completed callback
201  *
202  * @dma_task [in]: Completed task
203  * @task_user_data [in]: doca_data from the task
204  * @ctx_user_data [in]: doca_data from the context
205  */
206 static void dma_memcpy_completed_callback(struct doca_dma_task_memcpy *dma_task,
207  union doca_data task_user_data,
208  union doca_data ctx_user_data)
209 {
210  struct cache_invalidate_sample_state *state = (struct cache_invalidate_sample_state *)ctx_user_data.ptr;
211 
212  (void)dma_task;
213  (void)task_user_data;
214 
215  DOCA_LOG_INFO("DMA completed, Submitting cache invalidate task");
217 }
218 
219 /*
220  * Memcpy task error callback
221  *
222  * @dma_task [in]: failed task
223  * @task_user_data [in]: doca_data from the task
224  * @ctx_user_data [in]: doca_data from the context
225  */
226 static void dma_memcpy_error_callback(struct doca_dma_task_memcpy *dma_task,
227  union doca_data task_user_data,
228  union doca_data ctx_user_data)
229 {
230  struct cache_invalidate_sample_state *state = (struct cache_invalidate_sample_state *)ctx_user_data.ptr;
231  struct doca_task *task = doca_dma_task_memcpy_as_task(dma_task);
232 
233  (void)task_user_data;
234 
235  DOCA_LOG_ERR("DMA Task failed with status %s", doca_error_get_descr(doca_task_get_status(task)));
236 
237  state->run_pe = false;
238 }
239 
247 {
248  union doca_data ctx_user_data = {0};
249 
250  DOCA_LOG_INFO("Creating DMA");
251 
252  EXIT_ON_FAILURE(doca_dma_create(state->device, &state->dma));
253  state->dma_ctx = doca_dma_as_ctx(state->dma);
254 
255  /* A context can only be connected to one PE (PE can run multiple contexts) */
257 
263  ctx_user_data.ptr = state;
264  EXIT_ON_FAILURE(doca_ctx_set_user_data(state->dma_ctx, ctx_user_data));
265 
269  NUM_TASKS));
270 
271  return DOCA_SUCCESS;
272 }
273 
274 /*
275  * Cache invalidate task completed callback
276  *
277  * @cache_invalidate_task [in]: Completed task
278  * @task_user_data [in]: doca_data from the task
279  * @ctx_user_data [in]: doca_data from the context
280  */
281 static void cache_invalidate_completed_callback(struct doca_mmap_advise_task_invalidate_cache *cache_invalidate_task,
282  union doca_data task_user_data,
283  union doca_data ctx_user_data)
284 {
285  struct cache_invalidate_sample_state *state = (struct cache_invalidate_sample_state *)ctx_user_data.ptr;
286 
287  (void)cache_invalidate_task;
288  (void)task_user_data;
289 
290  DOCA_LOG_INFO("Cache invalidate completed");
291 
292  state->run_pe = false;
293 }
294 
295 /*
296  * Cache invalidate task error callback
297  *
298  * @cache_invalidate_task [in]: failed task
299  * @task_user_data [in]: doca_data from the task
300  * @ctx_user_data [in]: doca_data from the context
301  */
302 static void cache_invalidate_error_callback(struct doca_mmap_advise_task_invalidate_cache *cache_invalidate_task,
303  union doca_data task_user_data,
304  union doca_data ctx_user_data)
305 {
306  struct cache_invalidate_sample_state *state = (struct cache_invalidate_sample_state *)ctx_user_data.ptr;
308 
309  (void)task_user_data;
310 
311  DOCA_LOG_ERR("Cache invalidate Task failed with status %s", doca_error_get_descr(doca_task_get_status(task)));
312 
313  state->run_pe = false;
314 }
315 
323 {
324  union doca_data ctx_user_data = {0};
325 
326  DOCA_LOG_INFO("Creating MMAP advise");
327 
330 
331  /* A context can only be connected to one PE (PE can run multiple contexts) */
333 
339  ctx_user_data.ptr = state;
341 
345  NUM_TASKS));
346 
347  return DOCA_SUCCESS;
348 }
349 
358 {
359  union doca_data user_data = {0};
360  DOCA_LOG_INFO("Allocating DMA task");
361 
362  /* Use doca_buf_inventory_buf_get_by_data to initialize the source buffer */
364  state->mmap,
365  state->buffer,
367  &state->dma_source));
368 
374  state->mmap,
375  state->buffer + DMA_BUFFER_SIZE,
377  &state->dma_destination));
378 
380  state->dma_source,
381  state->dma_destination,
382  user_data,
383  &state->dma_task));
384 
385  return DOCA_SUCCESS;
386 }
387 
396 {
397  union doca_data user_data = {0};
398  DOCA_LOG_INFO("Allocating cache invalidate task");
399 
400  /* Using DMA source buffer */
402  state->dma_source,
403  user_data,
404  &state->cache_invalidate_task));
405 
406  return DOCA_SUCCESS;
407 }
408 
416 {
417  DOCA_LOG_INFO("Submitting DMA task");
418 
420 
421  return DOCA_SUCCESS;
422 }
423 
431 {
432  DOCA_LOG_INFO("Polling until all tasks are completed");
433 
434  state->run_pe = true;
435 
436  /* This loop ticks the progress engine */
437  while (state->run_pe == true) {
442  (void)doca_pe_progress(state->pe);
443  }
444 
445  DOCA_LOG_INFO("All tasks are completed");
446 
447  return DOCA_SUCCESS;
448 }
449 
458 static void cleanup(struct cache_invalidate_sample_state *state)
459 {
460  if (state->dma_task != NULL)
462 
463  if (state->cache_invalidate_task != NULL)
465 
466  /* A context must be stopped before it is destroyed */
467  if (state->dma_ctx != NULL)
468  (void)doca_ctx_stop(state->dma_ctx);
469 
470  if (state->mmap_advise_ctx != NULL)
471  (void)doca_ctx_stop(state->mmap_advise_ctx);
472 
473  /* All contexts must be destroyed before PE is destroyed. Context destroy disconnects it from the PE */
474  if (state->dma != NULL)
475  (void)doca_dma_destroy(state->dma);
476 
477  if (state->mmap_advise != NULL)
479 
480  if (state->pe != NULL)
481  (void)doca_pe_destroy(state->pe);
482 
483  if (state->dma_source != NULL)
484  (void)doca_buf_dec_refcount(state->dma_source, NULL);
485 
486  if (state->dma_destination != NULL)
488 
489  if (state->inventory != NULL) {
490  (void)doca_buf_inventory_stop(state->inventory);
492  }
493 
494  if (state->mmap != NULL) {
495  (void)doca_mmap_stop(state->mmap);
496  (void)doca_mmap_destroy(state->mmap);
497  }
498 
499  if (state->device != NULL)
500  (void)doca_dev_close(state->device);
501 
502  if (state->buffer != NULL)
503  free(state->buffer);
504 }
505 
515 {
516  memset(state, 0, sizeof(*state));
517 
522  EXIT_ON_FAILURE(create_pe(state));
523  EXIT_ON_FAILURE(create_dma(state));
531 
532  return DOCA_SUCCESS;
533 }
534 
541 {
542  struct cache_invalidate_sample_state state;
543  doca_error_t status = run(&state);
544 
545  cleanup(&state);
546 
547  return status;
548 }
#define NULL
Definition: __stddef_null.h:26
static doca_error_t allocate_buffer(struct cache_invalidate_sample_state *state)
#define EXIT_ON_FAILURE(_expression_)
static void cleanup(struct cache_invalidate_sample_state *state)
#define BUF_INVENTORY_SIZE
static doca_error_t submit_dma_task(struct cache_invalidate_sample_state *state)
DOCA_LOG_REGISTER(CACHE_INVALIDATE::SAMPLE)
static doca_error_t run(struct cache_invalidate_sample_state *state)
static doca_error_t create_buf_inventory(struct cache_invalidate_sample_state *state)
doca_error_t run_cache_invalidate_sample(void)
static doca_error_t allocate_cache_invalidate_task(struct cache_invalidate_sample_state *state)
#define BUFFER_SIZE
static doca_error_t create_mmap(struct cache_invalidate_sample_state *state)
static doca_error_t check_dev_capable(struct doca_devinfo *devinfo)
static doca_error_t create_mmap_advise(struct cache_invalidate_sample_state *state)
static doca_error_t poll_for_completion(struct cache_invalidate_sample_state *state)
static doca_error_t create_dma(struct cache_invalidate_sample_state *state)
static void dma_memcpy_completed_callback(struct doca_dma_task_memcpy *dma_task, union doca_data task_user_data, union doca_data ctx_user_data)
#define NUM_TASKS
static void dma_memcpy_error_callback(struct doca_dma_task_memcpy *dma_task, union doca_data task_user_data, union doca_data ctx_user_data)
static doca_error_t create_pe(struct cache_invalidate_sample_state *state)
#define DMA_BUFFER_SIZE
static void cache_invalidate_completed_callback(struct doca_mmap_advise_task_invalidate_cache *cache_invalidate_task, union doca_data task_user_data, union doca_data ctx_user_data)
static void cache_invalidate_error_callback(struct doca_mmap_advise_task_invalidate_cache *cache_invalidate_task, union doca_data task_user_data, union doca_data ctx_user_data)
static doca_error_t open_device(struct cache_invalidate_sample_state *state)
static doca_error_t allocate_dma_task(struct cache_invalidate_sample_state *state)
doca_error_t open_doca_device_with_capabilities(tasks_check func, struct doca_dev **retval)
Definition: common.c:188
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_ctx_start(struct doca_ctx *ctx)
Finalizes all configurations, and starts the DOCA CTX.
DOCA_STABLE doca_error_t doca_ctx_set_user_data(struct doca_ctx *ctx, union doca_data user_data)
set user data to context
DOCA_STABLE doca_error_t doca_ctx_stop(struct doca_ctx *ctx)
Stops the context allowing reconfiguration.
DOCA_STABLE doca_error_t doca_dev_close(struct doca_dev *dev)
Destroy allocated local device instance.
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_ctx * doca_dma_as_ctx(struct doca_dma *dma)
DOCA_STABLE doca_error_t doca_dma_task_memcpy_set_conf(struct doca_dma *dma, doca_dma_task_memcpy_completion_cb_t task_completion_cb, doca_dma_task_memcpy_completion_cb_t task_error_cb, uint32_t num_memcpy_tasks)
This method sets the DMA memcpy tasks configuration.
DOCA_STABLE doca_error_t doca_dma_cap_task_memcpy_is_supported(const struct doca_devinfo *devinfo)
DOCA_STABLE doca_error_t doca_dma_create(struct doca_dev *dev, struct doca_dma **dma)
DOCA_STABLE doca_error_t doca_dma_destroy(struct doca_dma *dma)
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_descr(doca_error_t error)
Returns the description string of an error code.
@ 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_EXPERIMENTAL struct doca_task * doca_mmap_advise_task_invalidate_cache_as_doca_task(struct doca_mmap_advise_task_invalidate_cache *task)
Convert a DOCA MMAP advise invalidate cache task to a DOCA Task.
DOCA_EXPERIMENTAL doca_error_t doca_mmap_advise_cap_task_cache_invalidate_is_supported(const struct doca_devinfo *devinfo)
Check if a given device supports submitting a DOCA MMAP advise cache invalidate task.
DOCA_EXPERIMENTAL doca_error_t doca_mmap_advise_destroy(struct doca_mmap_advise *mmap_advise)
Destroy an mmap advise instance.
DOCA_EXPERIMENTAL doca_error_t doca_mmap_advise_task_invalidate_cache_set_conf(struct doca_mmap_advise *mmap_advise, doca_mmap_advise_task_invalidate_cache_completion_cb_t completion_cb, doca_mmap_advise_task_invalidate_cache_completion_cb_t error_cb, uint32_t num_tasks)
Set the DOCA MMAP advise cache invalidate task configuration.
DOCA_EXPERIMENTAL struct doca_ctx * doca_mmap_advise_as_ctx(struct doca_mmap_advise *mmap_advise)
Convert a MMAP advise to a DOCA context.
DOCA_EXPERIMENTAL doca_error_t doca_mmap_advise_task_invalidate_cache_alloc_init(struct doca_mmap_advise *mmap_advise, struct doca_buf *buf, union doca_data user_data, struct doca_mmap_advise_task_invalidate_cache **task)
Allocate a DOCA MMAP advise cache invalidate task.
DOCA_EXPERIMENTAL doca_error_t doca_mmap_advise_create(struct doca_dev *dev, struct doca_mmap_advise **mmap_advise)
Create an mmap advise instance.
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_get_status(const struct doca_task *task)
Get task status.
DOCA_STABLE doca_error_t doca_pe_connect_ctx(struct doca_pe *pe, struct doca_ctx *ctx)
This method connects a context to a 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
struct doca_dma_task_memcpy * dma_task
struct doca_buf_inventory * inventory
struct doca_mmap_advise * mmap_advise
struct doca_mmap_advise_task_invalidate_cache * cache_invalidate_task
Convenience type for representing opaque data.
Definition: doca_types.h:56
void * ptr
Definition: doca_types.h:57