NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
gpunetio_dma_memcpy_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 <unistd.h>
27 #include <time.h>
28 #include <stdbool.h>
29 
30 #include <doca_log.h>
31 #include <doca_buf.h>
32 #include <doca_buf_inventory.h>
33 #include <doca_mmap.h>
34 #include <doca_pe.h>
35 
36 #include "gpunetio_dma_common.h"
37 
38 #define SLEEP_IN_NANOS (10 * 1000)
39 #define GPU_PAGE_SIZE (1UL << 16)
40 #define NUM_TASKS 1
41 #define NUM_BUFS 2
42 #define DEFAULT_VALUE 0
43 
44 /* Global flag indicating the task status */
45 static uint8_t is_task_done = 0;
46 
47 DOCA_LOG_REGISTER(GPU_DMA_MEMCPY::SAMPLE);
48 
49 /*
50  * Sample objects
51  */
53  struct program_core_objects core_objs; /* Core objects */
54  struct doca_dma *dma; /* DOCA DMA instance */
55  struct doca_gpu_dma *dma_gpu; /* DOCA DMA GPU instance */
56  struct doca_gpu *gpu_dev; /* DOCA GPU device */
57  struct doca_buf *src_doca_buf; /* src doca buffer - CPU memory */
58  struct doca_buf *dst_doca_buf; /* dst doca buffer - GPU memory */
59  struct doca_buf_arr *src_doca_buf_arr; /* src doca buffer - GPU memory */
60  struct doca_buf_arr *dst_doca_buf_arr; /* dst doca buffer - CPU memory */
61  struct doca_gpu_buf_arr *src_doca_gpu_buf_arr; /* src GPU doca buffer - GPU memory */
62  struct doca_gpu_buf_arr *dst_doca_gpu_buf_arr; /* dst GPU doca buffer - CPU memory */
63  char *src_buffer; /* src buffer address - CPU memory */
64  char *dst_buffer; /* dst buffer address - GPU memory */
65  bool gpu_datapath; /* Enable GPU datapath */
66 };
67 
68 /*
69  * DMA memcpy task common callback
70  *
71  * @dma_task [in]: DMA task
72  * @task_user_data [in]: Task user data
73  * @ctx_user_data [in]: Context user data
74  */
75 static void memcpy_task_common_callback(struct doca_dma_task_memcpy *dma_task,
76  union doca_data task_user_data,
77  union doca_data ctx_user_data)
78 {
79  (void)dma_task;
80  (void)task_user_data;
81  (void)ctx_user_data;
82 
83  /* Set a flag to notify upon completion of a task */
84  is_task_done = 1;
85 }
86 
87 /*
88  * Initialize DOCA device
89  *
90  * @nic_pcie_addr [in]: Network card PCIe address
91  * @ddev [out]: DOCA device
92  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
93  */
94 static doca_error_t init_doca_device(char *nic_pcie_addr, struct doca_dev **ddev)
95 {
96  doca_error_t status;
97 
98  if (nic_pcie_addr == NULL || ddev == NULL)
100 
101  status = open_doca_device_with_pci(nic_pcie_addr, NULL, ddev);
102  if (status != DOCA_SUCCESS) {
103  DOCA_LOG_ERR("Failed to open DOCA device based on NIC PCI address");
104  return status;
105  }
106 
107  return DOCA_SUCCESS;
108 }
109 
110 /*
111  * Initialize sample memory objects
112  *
113  * @state [in]: Sample objects
114  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
115  */
117 {
118  doca_error_t status;
119  char *tmp_cpu;
120 
121  if (state->gpu_datapath) {
122  /* Allocate GPU src buffer */
123  status = doca_gpu_mem_alloc(state->gpu_dev,
126  DOCA_GPU_MEM_TYPE_GPU_CPU, // GDRCopy
127  (void **)&state->src_buffer,
128  (void **)&tmp_cpu);
129  if (status != DOCA_SUCCESS) {
130  DOCA_LOG_ERR("Failed to initialize memory objects: Unable to allocate gpu memory: %s",
131  doca_error_get_descr(status));
132  return status;
133  }
134 
135  /* Copy data to src buffer */
136  strcpy(tmp_cpu, "This is a sample piece of text from GPU");
137 
138  DOCA_LOG_INFO("The GPU source buffer value to be copied to CPU memory: %s", tmp_cpu);
139 
140  status = doca_mmap_create(&state->core_objs.src_mmap);
141  if (status != DOCA_SUCCESS) {
142  DOCA_LOG_ERR("Unable to create source mmap: %s", doca_error_get_descr(status));
143  return status;
144  }
145  status = doca_mmap_add_dev(state->core_objs.src_mmap, state->core_objs.dev);
146  if (status != DOCA_SUCCESS) {
147  DOCA_LOG_ERR("Unable to add device to source mmap: %s", doca_error_get_descr(status));
148  return status;
149  }
150 
151  /* Allocate CPU dst buffer */
152  state->dst_buffer = (char *)malloc(DMA_MEMCPY_SIZE);
153  if (state->dst_buffer == NULL) {
154  DOCA_LOG_ERR("Failed to initialize memory objects: Unable to allocate cpu memory");
155  return DOCA_ERROR_NO_MEMORY;
156  }
157 
158  memset(state->dst_buffer, DEFAULT_VALUE, DMA_MEMCPY_SIZE);
159 
160  status = doca_mmap_create(&state->core_objs.dst_mmap);
161  if (status != DOCA_SUCCESS) {
162  DOCA_LOG_ERR("Unable to create destination mmap: %s", doca_error_get_descr(status));
163  return status;
164  }
165  status = doca_mmap_add_dev(state->core_objs.dst_mmap, state->core_objs.dev);
166  if (status != DOCA_SUCCESS) {
167  DOCA_LOG_ERR("Unable to add device to destination mmap: %s", doca_error_get_descr(status));
168  return status;
169  }
170 
171  } else {
172  /* Create DOCA Core objects */
173  status = create_core_objects(&(state->core_objs), NUM_BUFS);
174  if (status != DOCA_SUCCESS) {
175  DOCA_LOG_ERR("Failed to initialize memory objects: Failed to create core objects: %s",
176  doca_error_get_descr(status));
177  return status;
178  }
179 
180  /* Allocate CPU src buffer */
181  state->src_buffer = (char *)malloc(DMA_MEMCPY_SIZE);
182  if (state->src_buffer == NULL) {
183  DOCA_LOG_ERR("Failed to initialize memory objects: Unable to allocate cpu memory");
184  return DOCA_ERROR_NO_MEMORY;
185  }
186 
187  /* Copy data to src buffer */
188  strcpy(state->src_buffer, "This is a sample piece of text from CPU");
189 
190  /* Print the source buffer */
191  DOCA_LOG_INFO("The CPU source buffer value to be copied to GPU memory: %s", state->src_buffer);
192 
193  /* Allocate GPU dst buffer */
194  status = doca_gpu_mem_alloc(state->gpu_dev,
198  (void **)&state->dst_buffer,
199  NULL);
200  if (status != DOCA_SUCCESS) {
201  DOCA_LOG_ERR("Failed to initialize memory objects: Unable to allocate gpu memory: %s",
202  doca_error_get_descr(status));
203  return status;
204  }
205  }
206 
207  /* Set memory range in dst mmap with GPU memory address */
209  if (status != DOCA_SUCCESS) {
210  DOCA_LOG_ERR("Failed to initialize memory objects: Unable to set memrange to dst mmap: %s",
211  doca_error_get_descr(status));
212  return status;
213  }
214 
215  /* Set memory range in src mmap with CPU memory address */
217  if (status != DOCA_SUCCESS) {
218  DOCA_LOG_ERR("Failed to initialize memory objects: Unable to set memrange to src mmap: %s",
219  doca_error_get_descr(status));
220  return status;
221  }
222 
223  /* Start src mmap */
224  status = doca_mmap_start(state->core_objs.src_mmap);
225  if (status != DOCA_SUCCESS) {
226  DOCA_LOG_ERR("Failed to initialize memory objects: Unable to start src mmap: %s",
227  doca_error_get_descr(status));
228  return status;
229  }
230 
231  /* Start dst mmap */
232  status = doca_mmap_start(state->core_objs.dst_mmap);
233  if (status != DOCA_SUCCESS) {
234  DOCA_LOG_ERR("Failed to initialize memory objects: Unable to start dst mmap: %s",
235  doca_error_get_descr(status));
236  return status;
237  }
238 
239  if (state->gpu_datapath) {
240  /* Create src GPU buffer array */
241  status = doca_buf_arr_create(1, &state->src_doca_buf_arr);
242  if (status != DOCA_SUCCESS) {
243  DOCA_LOG_ERR("Unable to start buf: doca src_doca_buf_arr internal error");
244  return status;
245  }
246 
247  status = doca_buf_arr_set_target_gpu(state->src_doca_buf_arr, state->gpu_dev);
248  if (status != DOCA_SUCCESS) {
249  DOCA_LOG_ERR("Unable to start buf: doca src_doca_buf_arr internal error");
250  return status;
251  }
252 
253  status =
255  if (status != DOCA_SUCCESS) {
256  DOCA_LOG_ERR("Unable to start buf: doca src_doca_buf_arr internal error");
257  return status;
258  }
259 
260  status = doca_buf_arr_start(state->src_doca_buf_arr);
261  if (status != DOCA_SUCCESS) {
262  DOCA_LOG_ERR("Unable to start buf: doca src_doca_buf_arr internal error");
263  return status;
264  }
265 
267  if (status != DOCA_SUCCESS) {
268  DOCA_LOG_ERR("Unable to get buff_arr GPU handle: %s", doca_error_get_descr(status));
269  return status;
270  }
271 
272  /* Create dst GPU buffer array */
273  status = doca_buf_arr_create(1, &state->dst_doca_buf_arr);
274  if (status != DOCA_SUCCESS) {
275  DOCA_LOG_ERR("Unable to start buf: doca dst_doca_buf_arr internal error");
276  return status;
277  }
278 
279  status = doca_buf_arr_set_target_gpu(state->dst_doca_buf_arr, state->gpu_dev);
280  if (status != DOCA_SUCCESS) {
281  DOCA_LOG_ERR("Unable to start buf: doca dst_doca_buf_arr internal error");
282  return status;
283  }
284 
285  status =
287  if (status != DOCA_SUCCESS) {
288  DOCA_LOG_ERR("Unable to start buf: doca dst_doca_buf_arr internal error");
289  return status;
290  }
291 
292  status = doca_buf_arr_start(state->dst_doca_buf_arr);
293  if (status != DOCA_SUCCESS) {
294  DOCA_LOG_ERR("Unable to start buf: doca dst_doca_buf_arr internal error");
295  return status;
296  }
297 
299  if (status != DOCA_SUCCESS) {
300  DOCA_LOG_ERR("Unable to get buff_arr GPU handle: %s", doca_error_get_descr(status));
301  return status;
302  }
303  } else {
304  /* Get a DOCA buffer from src mmap (CPU) */
306  state->core_objs.src_mmap,
307  state->src_buffer,
309  &state->src_doca_buf);
310  if (status != DOCA_SUCCESS) {
311  DOCA_LOG_ERR(
312  "Failed to initialize memory objects: Unable to acquire DOCA buffer representing src buffer: %s",
313  doca_error_get_descr(status));
314  return status;
315  }
316 
317  /* Get a DOCA buffer from dst mmap (GPU) */
319  state->core_objs.dst_mmap,
320  state->dst_buffer,
322  &state->dst_doca_buf);
323  if (status != DOCA_SUCCESS) {
324  DOCA_LOG_ERR(
325  "Failed to initialize memory objects: Unable to acquire DOCA buffer representing dst buffer: %s",
326  doca_error_get_descr(status));
327  return status;
328  }
329  }
330 
331  return DOCA_SUCCESS;
332 }
333 
334 /*
335  * Clean sample resources
336  *
337  * @state [in]: Sample objects to be destroyed
338  */
339 static void gpu_dma_cleanup(struct gpu_dma_sample_objects *state)
340 {
341  doca_error_t status;
342 
343  if (state->gpu_datapath) {
344  DOCA_LOG_INFO("Cleanup DMA ctx with GPU data path");
345 
346  if (state->core_objs.ctx != NULL) {
347  status = doca_ctx_stop(state->core_objs.ctx);
348  if (status != DOCA_SUCCESS)
349  DOCA_LOG_ERR("Failed to clean sample objects: Failed to stop dma ctx: %s",
350  doca_error_get_descr(status));
351  }
352 
353  if (state->dma != NULL) {
354  status = doca_dma_destroy(state->dma);
355  if (status != DOCA_SUCCESS)
356  DOCA_LOG_ERR("Failed to clean sample objects: Failed to destroy dma: %s",
357  doca_error_get_descr(status));
358  }
359 
360  if (state->core_objs.src_mmap != NULL) {
361  status = doca_mmap_destroy(state->core_objs.src_mmap);
362  if (status != DOCA_SUCCESS)
363  DOCA_LOG_ERR("Failed to clean sample objects: Failed to destroy src_mmap: %s",
364  doca_error_get_descr(status));
365  }
366 
367  if (state->core_objs.dst_mmap != NULL) {
368  status = doca_mmap_destroy(state->core_objs.dst_mmap);
369  if (status != DOCA_SUCCESS)
370  DOCA_LOG_ERR("Failed to clean sample objects: Failed to destroy dst_mmap: %s",
371  doca_error_get_descr(status));
372  }
373 
374  if (state->dst_buffer != NULL) {
375  free(state->dst_buffer);
376  state->dst_buffer = NULL;
377  }
378 
379  if (state->src_buffer != NULL) {
380  doca_gpu_mem_free(state->gpu_dev, (void *)state->src_buffer);
381  state->src_buffer = NULL;
382  }
383  } else {
384  DOCA_LOG_INFO("Cleanup DMA ctx with CPU data path");
385  if (state->core_objs.ctx != NULL) {
386  status = doca_ctx_stop(state->core_objs.ctx);
387  if (status != DOCA_SUCCESS)
388  DOCA_LOG_ERR("Failed to clean sample objects: Failed to stop dma ctx: %s",
389  doca_error_get_descr(status));
390  }
391 
392  if (state->dma != NULL) {
393  status = doca_dma_destroy(state->dma);
394  if (status != DOCA_SUCCESS)
395  DOCA_LOG_ERR("Failed to clean sample objects: Failed to destroy dma: %s",
396  doca_error_get_descr(status));
397  }
398 
399  if (state->dst_doca_buf != NULL) {
400  status = doca_buf_dec_refcount(state->dst_doca_buf, NULL);
401  if (status != DOCA_SUCCESS)
402  DOCA_LOG_ERR(
403  "Failed to clean sample objects: Failed to decrease DOCA dst buffer reference count: %s",
404  doca_error_get_descr(status));
405  }
406 
407  if (state->src_doca_buf != NULL) {
408  status = doca_buf_dec_refcount(state->src_doca_buf, NULL);
409  if (status != DOCA_SUCCESS)
410  DOCA_LOG_ERR(
411  "Failed to clean sample objects: Failed to decrease DOCA src buffer reference count: %s",
412  doca_error_get_descr(status));
413  }
414 
415  status = destroy_core_objects(&(state->core_objs));
416  if (status != DOCA_SUCCESS)
417  DOCA_LOG_ERR("Failed to clean sample objects: Failed to destroy core objects: %s",
418  doca_error_get_descr(status));
419 
420  if (state->dst_buffer != NULL) {
421  doca_gpu_mem_free(state->gpu_dev, (void *)state->dst_buffer);
422  state->dst_buffer = NULL;
423  }
424 
425  if (state->src_buffer != NULL) {
426  free(state->src_buffer);
427  state->src_buffer = NULL;
428  }
429 
430  if (state->gpu_dev != NULL) {
431  status = doca_gpu_destroy(state->gpu_dev);
432  if (status != DOCA_SUCCESS)
433  DOCA_LOG_ERR("Failed to clean sample objects: Failed to destroy doca gpu: %s",
434  doca_error_get_descr(status));
435  }
436  }
437 }
438 
439 /*
440  * Initialize dma context
441  *
442  * @state [in]: Sample objects
443  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
444  */
446 {
447  doca_error_t status;
448 
449  /* Create dma ctx */
450  status = doca_dma_create(state->core_objs.dev, &state->dma);
451  if (status != DOCA_SUCCESS) {
452  DOCA_LOG_ERR("Failed to initialize dma ctx: Unable to create DMA engine: %s",
453  doca_error_get_descr(status));
454  return status;
455  }
456 
457  state->core_objs.ctx = doca_dma_as_ctx(state->dma);
458 
459  if (state->gpu_datapath) {
460  status = doca_ctx_set_datapath_on_gpu(state->core_objs.ctx, state->gpu_dev);
461  if (status != DOCA_SUCCESS) {
462  DOCA_LOG_ERR("Failed to set datapath on GPU: %s", doca_error_get_descr(status));
463  return status;
464  }
465  } else {
466  /* Connect context to progress engine */
467  status = doca_pe_connect_ctx(state->core_objs.pe, state->core_objs.ctx);
468  if (status != DOCA_SUCCESS) {
469  DOCA_LOG_ERR("Failed to initialize dma ctx: Failed to connect PE to DMA: %s",
470  doca_error_get_descr(status));
471  return status;
472  }
473 
474  status = doca_dma_task_memcpy_set_conf(state->dma,
477  NUM_TASKS);
478  if (status != DOCA_SUCCESS) {
479  DOCA_LOG_ERR("Failed to initialize dma ctx: Unable to config DMA task %s",
480  doca_error_get_descr(status));
481  return status;
482  }
483  }
484 
485  /* Start doca ctx */
486  status = doca_ctx_start(state->core_objs.ctx);
487  if (status != DOCA_SUCCESS) {
488  DOCA_LOG_ERR("Failed to initialize dma ctx: Unable to start dma context: %s",
489  doca_error_get_descr(status));
490  return status;
491  }
492 
493  return DOCA_SUCCESS;
494 }
495 
496 /*
497  * Submit DMA Memcpy task
498  *
499  * @state [in]: Sample objects
500  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
501  */
503 {
504  doca_error_t status;
505  struct doca_dma_task_memcpy *memcpy_task;
506  struct doca_task *task;
507  union doca_data memcpy_task_user_data = {0};
508  struct timespec ts = {
509  .tv_sec = 0,
510  .tv_nsec = SLEEP_IN_NANOS,
511  };
512 
513  /* Construct DMA task */
514  status = doca_dma_task_memcpy_alloc_init(state->dma,
515  state->src_doca_buf,
516  state->dst_doca_buf,
517  memcpy_task_user_data,
518  &memcpy_task);
519  if (status != DOCA_SUCCESS) {
520  DOCA_LOG_ERR("Failed to submit dma memcpy task: Failed to allocate task: %s",
521  doca_error_get_descr(status));
522  return status;
523  }
524 
525  /* Submit DMA task */
526  task = doca_dma_task_memcpy_as_task(memcpy_task);
527  status = doca_task_submit(task);
528  if (status != DOCA_SUCCESS) {
529  DOCA_LOG_ERR("Failed to submit dma memcpy task: %s", doca_error_get_descr(status));
530  return status;
531  }
532 
533  while (!is_task_done) {
534  (void)doca_pe_progress(state->core_objs.pe);
535  nanosleep(&ts, &ts);
536  }
537 
538  /* Get task status */
539  status = doca_task_get_status(task);
540 
541  /* Free task */
542  doca_task_free(task);
543 
544  /* Check task status */
545  if (status != DOCA_SUCCESS) {
546  DOCA_LOG_ERR("DMA task event returned unsuccessfully: %s", doca_error_get_descr(status));
547  return status;
548  }
549 
550  DOCA_LOG_INFO("Success, DMA memcpy job done successfully");
551 
552  return DOCA_SUCCESS;
553 }
554 
555 /*
556  * Launch a CUDA kernel to read from the GPU destination buffer
557  *
558  * @gpu_dst_buffer [in]: The GPU destination buffer address
559  * @dma_gpu [in]: The GPU DMA object
560  * @src_gpu_buf_arr [in]: The GPU buff array src
561  * @dst_gpu_buf_arr [in]: The GPU buff array dest
562  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
563  */
565  struct doca_gpu_dma *dma_gpu,
566  struct doca_gpu_buf_arr *src_gpu_buf_arr,
567  struct doca_gpu_buf_arr *dst_gpu_buf_arr)
568 {
569  doca_error_t status;
570  cudaStream_t cuda_stream;
571  cudaError_t res_rt = cudaSuccess;
572 
573  res_rt = cudaStreamCreateWithFlags(&cuda_stream, cudaStreamNonBlocking);
574  if (res_rt != cudaSuccess) {
575  DOCA_LOG_ERR("Function cudaStreamCreateWithFlags error %d", res_rt);
576  return DOCA_ERROR_DRIVER;
577  }
578 
579  status = gpunetio_dma_memcpy_common_launch_kernel(cuda_stream,
580  gpu_dst_buffer,
581  dma_gpu,
582  src_gpu_buf_arr,
583  dst_gpu_buf_arr);
584  if (status != DOCA_SUCCESS) {
585  DOCA_LOG_ERR("Function dma_gpu_copy_common_launch_kernel returned %s", doca_error_get_descr(status));
586  return status;
587  }
588 
589  res_rt = cudaDeviceSynchronize();
590  if (res_rt != cudaSuccess) {
591  DOCA_LOG_ERR("Function cudaDeviceSynchronize error %d", res_rt);
592  return DOCA_ERROR_DRIVER;
593  }
594 
595  return DOCA_SUCCESS;
596 }
597 
598 /*
599  * GPU DMA Memcpy sample
600  *
601  * @cfg [in]: Sample config parameters
602  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
603  */
605 {
606  doca_error_t status;
607  struct gpu_dma_sample_objects state_cpu_gpu = {0};
608  struct gpu_dma_sample_objects state_gpu_cpu = {0};
609 
610 #if 0
611  struct doca_log_backend *stdout_logger = NULL;
612 
614  if (status != DOCA_SUCCESS)
615  return status;
616 
618  if (status != DOCA_SUCCESS)
619  return status;
620 
621  if (cfg == NULL) {
622  DOCA_LOG_ERR("Invalid sample configuration input value");
624  }
625 #endif
626  status = init_doca_device(cfg->nic_pcie_addr, &state_cpu_gpu.core_objs.dev);
627  if (status != DOCA_SUCCESS) {
628  DOCA_LOG_ERR("Function init_doca_device returned %s", doca_error_get_descr(status));
629  return status;
630  }
631 
632  status = doca_gpu_create(cfg->gpu_pcie_addr, &state_cpu_gpu.gpu_dev);
633  if (status != DOCA_SUCCESS) {
634  DOCA_LOG_ERR("Function doca_gpu_create returned %s", doca_error_get_descr(status));
635  goto gpu_dma_cleanup;
636  }
637 
638  state_cpu_gpu.gpu_datapath = false;
639  state_gpu_cpu.core_objs.dev = state_cpu_gpu.core_objs.dev;
640  state_gpu_cpu.gpu_datapath = true;
641  state_gpu_cpu.gpu_dev = state_cpu_gpu.gpu_dev;
642 
643  status = init_sample_mem_objs(&state_cpu_gpu);
644  if (status != DOCA_SUCCESS) {
645  DOCA_LOG_ERR("Function init_sample_mem_objs returned %s", doca_error_get_descr(status));
646  goto gpu_dma_cleanup;
647  }
648 
649  status = init_sample_mem_objs(&state_gpu_cpu);
650  if (status != DOCA_SUCCESS) {
651  DOCA_LOG_ERR("Function init_sample_mem_objs returned %s", doca_error_get_descr(status));
652  goto gpu_dma_cleanup;
653  }
654 
655  status = init_dma_ctx(&state_cpu_gpu);
656  if (status != DOCA_SUCCESS) {
657  DOCA_LOG_ERR("Function init_dma_ctx returned %s", doca_error_get_descr(status));
658  goto gpu_dma_cleanup;
659  }
660 
661  status = init_dma_ctx(&state_gpu_cpu);
662  if (status != DOCA_SUCCESS) {
663  DOCA_LOG_ERR("Function init_dma_ctx returned %s", doca_error_get_descr(status));
664  goto gpu_dma_cleanup;
665  }
666 
667  status = submit_dma_memcpy_task(&state_cpu_gpu);
668  if (status != DOCA_SUCCESS) {
669  DOCA_LOG_ERR("Function submit_dma_memcpy_task returned %s", doca_error_get_descr(status));
670  goto gpu_dma_cleanup;
671  }
672 
673  status = doca_dma_get_gpu_handle(state_gpu_cpu.dma, &state_gpu_cpu.dma_gpu);
674  if (status != DOCA_SUCCESS) {
675  DOCA_LOG_ERR("Function submit_dma_memcpy_task returned %s", doca_error_get_descr(status));
676  goto gpu_dma_cleanup;
677  }
678 
679  status = launch_cuda_kernel((uintptr_t)state_cpu_gpu.dst_buffer,
680  state_gpu_cpu.dma_gpu,
681  state_gpu_cpu.src_doca_gpu_buf_arr,
682  state_gpu_cpu.dst_doca_gpu_buf_arr);
683  if (status != DOCA_SUCCESS) {
684  DOCA_LOG_ERR("Function launch_cuda_kernel returned %s", doca_error_get_descr(status));
685  goto gpu_dma_cleanup;
686  }
687 
688  while (state_gpu_cpu.dst_buffer[0] == DEFAULT_VALUE)
689  ;
690 
691  printf("CPU received message from GPU: %s\n", state_gpu_cpu.dst_buffer);
692 
694  gpu_dma_cleanup(&state_gpu_cpu);
695  gpu_dma_cleanup(&state_cpu_gpu);
696 
697  return status;
698 }
#define NULL
Definition: __stddef_null.h:26
doca_error_t destroy_core_objects(struct program_core_objects *state)
Definition: common.c:392
doca_error_t create_core_objects(struct program_core_objects *state, uint32_t max_bufs)
Definition: common.c:302
static doca_error_t open_doca_device_with_pci(const char *pcie_value, struct doca_dev **retval)
Definition: device.c:43
struct doca_log_backend * stdout_logger
static struct doca_dev * ddev
doca_error_t gpunetio_dma_memcpy_common_launch_kernel(cudaStream_t stream, uintptr_t gpu_buffer_addr, struct doca_gpu_dma *dma_gpu, struct doca_gpu_buf_arr *src_gpu_buf_arr, struct doca_gpu_buf_arr *dst_gpu_buf_arr)
#define DMA_MEMCPY_SIZE
static doca_error_t launch_cuda_kernel(uintptr_t gpu_dst_buffer, struct doca_gpu_dma *dma_gpu, struct doca_gpu_buf_arr *src_gpu_buf_arr, struct doca_gpu_buf_arr *dst_gpu_buf_arr)
static void memcpy_task_common_callback(struct doca_dma_task_memcpy *dma_task, union doca_data task_user_data, union doca_data ctx_user_data)
#define DEFAULT_VALUE
static doca_error_t init_doca_device(char *nic_pcie_addr, struct doca_dev **ddev)
DOCA_LOG_REGISTER(GPU_DMA_MEMCPY::SAMPLE)
static doca_error_t init_dma_ctx(struct gpu_dma_sample_objects *state)
static void gpu_dma_cleanup(struct gpu_dma_sample_objects *state)
static uint8_t is_task_done
doca_error_t gpunetio_dma_memcpy(struct gpu_dma_config *cfg)
#define GPU_PAGE_SIZE
#define NUM_TASKS
#define NUM_BUFS
static doca_error_t submit_dma_memcpy_task(struct gpu_dma_sample_objects *state)
static doca_error_t init_sample_mem_objs(struct gpu_dma_sample_objects *state)
#define SLEEP_IN_NANOS
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_set_params(struct doca_buf_arr *buf_arr, struct doca_mmap *mmap, size_t elem_size, uint64_t start_offset)
Sets the buf array params.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_set_target_gpu(struct doca_buf_arr *buf_arr, struct doca_gpu *gpu_handler)
Configures the buf array to be created on the gpu device.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_get_gpu_handle(const struct doca_buf_arr *buf_arr, struct doca_gpu_buf_arr **gpu_buf_arr)
Retrieves the handle in the gpu memory space of a doca_buf_arr.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_create(size_t num_elem, struct doca_buf_arr **buf_arr)
Allocates a doca_buf_arr.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_start(struct doca_buf_arr *buf_arr)
This method enables the allocation of doca_bufs.
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_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_EXPERIMENTAL doca_error_t doca_ctx_set_datapath_on_gpu(struct doca_ctx *ctx, struct doca_gpu *gpu_dev)
This function binds the DOCA context to a gpu device.
DOCA_STABLE doca_error_t doca_ctx_stop(struct doca_ctx *ctx)
Stops the context allowing reconfiguration.
DOCA_EXPERIMENTAL doca_error_t doca_dma_get_gpu_handle(struct doca_dma *dma, struct doca_gpu_dma **gpu_dma)
Retrieve the handle in the GPU memory space of a doca_dma.
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_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_ERROR_INVALID_VALUE
Definition: doca_error.h:44
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_NO_MEMORY
Definition: doca_error.h:45
@ DOCA_ERROR_DRIVER
Definition: doca_error.h:59
#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 doca_error_t doca_log_backend_create_with_file_sdk(FILE *fptr, struct doca_log_backend **backend)
Create a logging backend with a FILE* stream for SDK messages.
DOCA_EXPERIMENTAL doca_error_t doca_log_backend_set_sdk_level(struct doca_log_backend *backend, uint32_t level)
Set the log level limit for SDK logging backends.
@ DOCA_LOG_LEVEL_TRACE
Definition: doca_log.h:50
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_start(struct doca_mmap *mmap)
Start 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_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 void doca_task_free(struct doca_task *task)
Free a task back to where it was allocated from.
@ DOCA_GPU_MEM_TYPE_GPU_CPU
Definition: doca_types.h:133
@ DOCA_GPU_MEM_TYPE_GPU
Definition: doca_types.h:131
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
__UINTPTR_TYPE__ uintptr_t
Definition: stdint.h:298
struct doca_gpu_buf_arr * src_doca_gpu_buf_arr
struct doca_gpu_buf_arr * dst_doca_gpu_buf_arr
struct doca_buf_arr * src_doca_buf_arr
struct program_core_objects core_objs
struct doca_buf_arr * dst_doca_buf_arr
struct doca_pe * pe
Definition: common.h:51
struct doca_mmap * src_mmap
Definition: common.h:47
struct doca_buf_inventory * buf_inv
Definition: common.h:49
struct doca_dev * dev
Definition: common.h:46
struct doca_mmap * dst_mmap
Definition: common.h:48
struct doca_ctx * ctx
Definition: common.h:50
Convenience type for representing opaque data.
Definition: doca_types.h:56