ethdev: fix typos
[dpdk.git] / app / test-gpudev / main.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2021 NVIDIA Corporation & Affiliates
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <stdint.h>
9 #include <inttypes.h>
10 #include <stdarg.h>
11 #include <errno.h>
12 #include <getopt.h>
13
14 #include <rte_common.h>
15 #include <rte_malloc.h>
16 #include <rte_memory.h>
17 #include <rte_eal.h>
18 #include <rte_ether.h>
19 #include <rte_ethdev.h>
20 #include <rte_mempool.h>
21 #include <rte_mbuf.h>
22
23 #include <rte_gpudev.h>
24
25 enum app_args {
26         ARG_HELP,
27         ARG_MEMPOOL
28 };
29
30 static void
31 usage(const char *prog_name)
32 {
33         printf("%s [EAL options] --\n",
34                 prog_name);
35 }
36
37 static void
38 args_parse(int argc, char **argv)
39 {
40         char **argvopt;
41         int opt;
42         int opt_idx;
43
44         static struct option lgopts[] = {
45                 { "help", 0, 0, ARG_HELP},
46                 /* End of options */
47                 { 0, 0, 0, 0 }
48         };
49
50         argvopt = argv;
51         while ((opt = getopt_long(argc, argvopt, "",
52                                 lgopts, &opt_idx)) != EOF) {
53                 switch (opt) {
54                 case ARG_HELP:
55                         usage(argv[0]);
56                         break;
57                 default:
58                         usage(argv[0]);
59                         rte_exit(EXIT_FAILURE, "Invalid option: %s\n", argv[optind]);
60                         break;
61                 }
62         }
63 }
64
65 static int
66 alloc_gpu_memory(uint16_t gpu_id)
67 {
68         void *ptr_1 = NULL;
69         void *ptr_2 = NULL;
70         size_t buf_bytes = 1024;
71         int ret;
72
73         printf("\n=======> TEST: Allocate GPU memory\n");
74
75         /* Alloc memory on GPU 0 */
76         ptr_1 = rte_gpu_mem_alloc(gpu_id, buf_bytes);
77         if (ptr_1 == NULL) {
78                 fprintf(stderr, "rte_gpu_mem_alloc GPU memory returned error\n");
79                 return -1;
80         }
81         printf("GPU memory allocated at 0x%p %zdB\n", ptr_1, buf_bytes);
82
83         ptr_2 = rte_gpu_mem_alloc(gpu_id, buf_bytes);
84         if (ptr_2 == NULL) {
85                 fprintf(stderr, "rte_gpu_mem_alloc GPU memory returned error\n");
86                 return -1;
87         }
88         printf("GPU memory allocated at 0x%p %zdB\n", ptr_2, buf_bytes);
89
90         ret = rte_gpu_mem_free(gpu_id, (uint8_t *)(ptr_1)+0x700);
91         if (ret < 0) {
92                 printf("GPU memory 0x%p + 0x700 NOT freed because of memory address not recognized by driver\n", ptr_1);
93         } else {
94                 fprintf(stderr, "rte_gpu_mem_free erroneously freed GPU memory 0x%p + 0x700\n", ptr_1);
95                 return -1;
96         }
97
98         ret = rte_gpu_mem_free(gpu_id, ptr_2);
99         if (ret < 0) {
100                 fprintf(stderr, "rte_gpu_mem_free returned error %d\n", ret);
101                 return -1;
102         }
103         printf("GPU memory 0x%p freed\n", ptr_2);
104
105         ret = rte_gpu_mem_free(gpu_id, ptr_1);
106         if (ret < 0) {
107                 fprintf(stderr, "rte_gpu_mem_free returned error %d\n", ret);
108                 return -1;
109         }
110         printf("GPU memory 0x%p freed\n", ptr_1);
111
112         return 0;
113 }
114
115 static int
116 register_cpu_memory(uint16_t gpu_id)
117 {
118         void *ptr = NULL;
119         size_t buf_bytes = 1024;
120         int ret;
121
122         printf("\n=======> TEST: Register CPU memory\n");
123
124         /* Alloc memory on CPU visible from GPU 0 */
125         ptr = rte_zmalloc(NULL, buf_bytes, 0);
126         if (ptr == NULL) {
127                 fprintf(stderr, "Failed to allocate CPU memory.\n");
128                 return -1;
129         }
130
131         ret = rte_gpu_mem_register(gpu_id, buf_bytes, ptr);
132         if (ret < 0) {
133                 fprintf(stderr, "rte_gpu_mem_register CPU memory returned error %d\n", ret);
134                 return -1;
135         }
136         printf("CPU memory registered at 0x%p %zdB\n", ptr, buf_bytes);
137
138         ret = rte_gpu_mem_unregister(gpu_id, (uint8_t *)(ptr)+0x700);
139         if (ret < 0) {
140                 printf("CPU memory 0x%p + 0x700 NOT unregistered because of memory address not recognized by driver\n", ptr);
141         } else {
142                 fprintf(stderr, "rte_gpu_mem_free erroneously freed GPU memory 0x%p + 0x700\n", ptr);
143                 return -1;
144         }
145         printf("CPU memory 0x%p unregistered\n", ptr);
146
147         ret = rte_gpu_mem_unregister(gpu_id, ptr);
148         if (ret < 0) {
149                 fprintf(stderr, "rte_gpu_mem_unregister returned error %d\n", ret);
150                 return -1;
151         }
152         printf("CPU memory 0x%p unregistered\n", ptr);
153
154         return 0;
155 }
156
157 static int
158 create_update_comm_flag(uint16_t gpu_id)
159 {
160         struct rte_gpu_comm_flag devflag;
161         int ret = 0;
162         uint32_t set_val;
163         uint32_t get_val;
164
165         printf("\n=======> TEST: Communication flag\n");
166
167         ret = rte_gpu_comm_create_flag(gpu_id, &devflag, RTE_GPU_COMM_FLAG_CPU);
168         if (ret < 0) {
169                 fprintf(stderr, "rte_gpu_comm_create_flag returned error %d\n", ret);
170                 return -1;
171         }
172
173         set_val = 25;
174         ret = rte_gpu_comm_set_flag(&devflag, set_val);
175         if (ret < 0) {
176                 fprintf(stderr, "rte_gpu_comm_set_flag returned error %d\n", ret);
177                 return -1;
178         }
179
180         ret = rte_gpu_comm_get_flag_value(&devflag, &get_val);
181         if (ret < 0) {
182                 fprintf(stderr, "rte_gpu_comm_get_flag_value returned error %d\n", ret);
183                 return -1;
184         }
185
186         printf("Communication flag value at 0x%p was set to %d and current value is %d\n", devflag.ptr, set_val, get_val);
187
188         set_val = 38;
189         ret = rte_gpu_comm_set_flag(&devflag, set_val);
190         if (ret < 0) {
191                 fprintf(stderr, "rte_gpu_comm_set_flag returned error %d\n", ret);
192                 return -1;
193         }
194
195         ret = rte_gpu_comm_get_flag_value(&devflag, &get_val);
196         if (ret < 0) {
197                 fprintf(stderr, "rte_gpu_comm_get_flag_value returned error %d\n", ret);
198                 return -1;
199         }
200
201         printf("Communication flag value at 0x%p was set to %d and current value is %d\n", devflag.ptr, set_val, get_val);
202
203         ret = rte_gpu_comm_destroy_flag(&devflag);
204         if (ret < 0) {
205                 fprintf(stderr, "rte_gpu_comm_destroy_flags returned error %d\n", ret);
206                 return -1;
207         }
208
209         return 0;
210 }
211
212 static int
213 simulate_gpu_task(struct rte_gpu_comm_list *comm_list_item, int num_pkts)
214 {
215         int idx;
216
217         if (comm_list_item == NULL)
218                 return -1;
219
220         for (idx = 0; idx < num_pkts; idx++) {
221                 /**
222                  * consume(comm_list_item->pkt_list[idx].addr);
223                  */
224         }
225         comm_list_item->status = RTE_GPU_COMM_LIST_DONE;
226
227         return 0;
228 }
229
230 static int
231 create_update_comm_list(uint16_t gpu_id)
232 {
233         int ret = 0;
234         int i = 0;
235         struct rte_gpu_comm_list *comm_list;
236         uint32_t num_comm_items = 1024;
237         struct rte_mbuf *mbufs[10];
238
239         printf("\n=======> TEST: Communication list\n");
240
241         comm_list = rte_gpu_comm_create_list(gpu_id, num_comm_items);
242         if (comm_list == NULL) {
243                 fprintf(stderr, "rte_gpu_comm_create_list returned error %d\n", ret);
244                 return -1;
245         }
246
247         /**
248          * Simulate DPDK receive functions like rte_eth_rx_burst()
249          */
250         for (i = 0; i < 10; i++) {
251                 mbufs[i] = rte_zmalloc(NULL, sizeof(struct rte_mbuf), 0);
252                 if (mbufs[i] == NULL) {
253                         fprintf(stderr, "Failed to allocate fake mbufs in CPU memory.\n");
254                         return -1;
255                 }
256
257                 memset(mbufs[i], 0, sizeof(struct rte_mbuf));
258         }
259
260         /**
261          * Populate just the first item of  the list
262          */
263         ret = rte_gpu_comm_populate_list_pkts(&(comm_list[0]), mbufs, 10);
264         if (ret < 0) {
265                 fprintf(stderr, "rte_gpu_comm_populate_list_pkts returned error %d\n", ret);
266                 return -1;
267         }
268
269         ret = rte_gpu_comm_cleanup_list(&(comm_list[0]));
270         if (ret == 0) {
271                 fprintf(stderr, "rte_gpu_comm_cleanup_list erroneously cleaned the list even if packets have not been consumed yet\n");
272                 return -1;
273         }
274         fprintf(stderr, "rte_gpu_comm_cleanup_list correctly didn't clean up the packets because they have not been consumed yet\n");
275
276         /**
277          * Simulate a GPU tasks going through the packet list to consume
278          * mbufs packets and release them
279          */
280         simulate_gpu_task(&(comm_list[0]), 10);
281
282         /**
283          * Packets have been consumed, now the communication item
284          * and the related mbufs can be all released
285          */
286         ret = rte_gpu_comm_cleanup_list(&(comm_list[0]));
287         if (ret < 0) {
288                 fprintf(stderr, "rte_gpu_comm_cleanup_list returned error %d\n", ret);
289                 return -1;
290         }
291
292         ret = rte_gpu_comm_destroy_list(comm_list, num_comm_items);
293         if (ret < 0) {
294                 fprintf(stderr, "rte_gpu_comm_destroy_list returned error %d\n", ret);
295                 return -1;
296         }
297
298         for (i = 0; i < 10; i++)
299                 rte_free(mbufs[i]);
300
301         printf("\nCommunication list test passed!\n");
302         return 0;
303 }
304
305 int
306 main(int argc, char **argv)
307 {
308         int ret;
309         int nb_gpus = 0;
310         int16_t gpu_id = 0;
311         struct rte_gpu_info ginfo;
312
313         /* Init EAL. */
314         ret = rte_eal_init(argc, argv);
315         if (ret < 0)
316                 rte_exit(EXIT_FAILURE, "EAL init failed\n");
317         argc -= ret;
318         argv += ret;
319         if (argc > 1)
320                 args_parse(argc, argv);
321         argc -= ret;
322         argv += ret;
323
324         nb_gpus = rte_gpu_count_avail();
325         printf("\n\nDPDK found %d GPUs:\n", nb_gpus);
326         RTE_GPU_FOREACH(gpu_id)
327         {
328                 if (rte_gpu_info_get(gpu_id, &ginfo))
329                         rte_exit(EXIT_FAILURE, "rte_gpu_info_get error - bye\n");
330
331                 printf("\tGPU ID %d\n\t\tparent ID %d GPU Bus ID %s NUMA node %d Tot memory %.02f MB, Tot processors %d\n",
332                                 ginfo.dev_id,
333                                 ginfo.parent,
334                                 ginfo.name,
335                                 ginfo.numa_node,
336                                 (((float)ginfo.total_memory)/(float)1024)/(float)1024,
337                                 ginfo.processor_count
338                         );
339         }
340         printf("\n\n");
341
342         if (nb_gpus == 0) {
343                 fprintf(stderr, "Need at least one GPU on the system to run the example\n");
344                 return EXIT_FAILURE;
345         }
346
347         gpu_id = 0;
348
349         /**
350          * Memory tests
351          */
352         alloc_gpu_memory(gpu_id);
353         register_cpu_memory(gpu_id);
354
355         /**
356          * Communication items test
357          */
358         create_update_comm_flag(gpu_id);
359         create_update_comm_list(gpu_id);
360
361         /* clean up the EAL */
362         rte_eal_cleanup();
363         printf("Bye...\n");
364
365         return EXIT_SUCCESS;
366 }