gpudev: add memory API
[dpdk.git] / lib / gpudev / rte_gpudev.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2021 NVIDIA Corporation & Affiliates
3  */
4
5 #ifndef RTE_GPUDEV_H
6 #define RTE_GPUDEV_H
7
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <stdbool.h>
11
12 #include <rte_bitops.h>
13 #include <rte_compat.h>
14
15 /**
16  * @file
17  * Generic library to interact with GPU computing device.
18  *
19  * The API is not thread-safe.
20  * Device management must be done by a single thread.
21  *
22  * @warning
23  * @b EXPERIMENTAL: this API may change without prior notice.
24  */
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29
30 /** Maximum number of devices if rte_gpu_init() is not called. */
31 #define RTE_GPU_DEFAULT_MAX 32
32
33 /** Empty device ID. */
34 #define RTE_GPU_ID_NONE -1
35 /** Catch-all device ID. */
36 #define RTE_GPU_ID_ANY INT16_MIN
37
38 /** Catch-all callback data. */
39 #define RTE_GPU_CALLBACK_ANY_DATA ((void *)-1)
40
41 /** Store device info. */
42 struct rte_gpu_info {
43         /** Unique identifier name. */
44         const char *name;
45         /** Opaque handler of the device context. */
46         uint64_t context;
47         /** Device ID. */
48         int16_t dev_id;
49         /** ID of the parent device, RTE_GPU_ID_NONE if no parent */
50         int16_t parent;
51         /** Total processors available on device. */
52         uint32_t processor_count;
53         /** Total memory available on device. */
54         size_t total_memory;
55         /* Local NUMA memory ID. -1 if unknown. */
56         int16_t numa_node;
57 };
58
59 /** Flags passed in notification callback. */
60 enum rte_gpu_event {
61         /** Device is just initialized. */
62         RTE_GPU_EVENT_NEW,
63         /** Device is going to be released. */
64         RTE_GPU_EVENT_DEL,
65 };
66
67 /** Prototype of event callback function. */
68 typedef void (rte_gpu_callback_t)(int16_t dev_id,
69                 enum rte_gpu_event event, void *user_data);
70
71 /**
72  * @warning
73  * @b EXPERIMENTAL: this API may change without prior notice.
74  *
75  * Initialize the device array before probing devices.
76  * If not called, the maximum of probed devices is RTE_GPU_DEFAULT_MAX.
77  *
78  * @param dev_max
79  *   Maximum number of devices.
80  *
81  * @return
82  *   0 on success, -rte_errno otherwise:
83  *   - ENOMEM if out of memory
84  *   - EINVAL if 0 size
85  *   - EBUSY if already initialized
86  */
87 __rte_experimental
88 int rte_gpu_init(size_t dev_max);
89
90 /**
91  * @warning
92  * @b EXPERIMENTAL: this API may change without prior notice.
93  *
94  * Return the number of GPU detected and associated to DPDK.
95  *
96  * @return
97  *   The number of available computing devices.
98  */
99 __rte_experimental
100 uint16_t rte_gpu_count_avail(void);
101
102 /**
103  * @warning
104  * @b EXPERIMENTAL: this API may change without prior notice.
105  *
106  * Check if the device is valid and initialized in DPDK.
107  *
108  * @param dev_id
109  *   The input device ID.
110  *
111  * @return
112  *   - True if dev_id is a valid and initialized computing device.
113  *   - False otherwise.
114  */
115 __rte_experimental
116 bool rte_gpu_is_valid(int16_t dev_id);
117
118 /**
119  * @warning
120  * @b EXPERIMENTAL: this API may change without prior notice.
121  *
122  * Create a virtual device representing a context in the parent device.
123  *
124  * @param name
125  *   Unique string to identify the device.
126  * @param parent
127  *   Device ID of the parent.
128  * @param child_context
129  *   Opaque context handler.
130  *
131  * @return
132  *   Device ID of the new created child, -rte_errno otherwise:
133  *   - EINVAL if empty name
134  *   - ENAMETOOLONG if long name
135  *   - EEXIST if existing device name
136  *   - ENODEV if invalid parent
137  *   - EPERM if secondary process
138  *   - ENOENT if too many devices
139  *   - ENOMEM if out of space
140  */
141 __rte_experimental
142 int16_t rte_gpu_add_child(const char *name,
143                 int16_t parent, uint64_t child_context);
144
145 /**
146  * @warning
147  * @b EXPERIMENTAL: this API may change without prior notice.
148  *
149  * Get the ID of the next valid GPU initialized in DPDK.
150  *
151  * @param dev_id
152  *   The initial device ID to start the research.
153  * @param parent
154  *   The device ID of the parent.
155  *   RTE_GPU_ID_NONE means no parent.
156  *   RTE_GPU_ID_ANY means no or any parent.
157  *
158  * @return
159  *   Next device ID corresponding to a valid and initialized computing device,
160  *   RTE_GPU_ID_NONE if there is none.
161  */
162 __rte_experimental
163 int16_t rte_gpu_find_next(int16_t dev_id, int16_t parent);
164
165 /**
166  * @warning
167  * @b EXPERIMENTAL: this API may change without prior notice.
168  *
169  * Macro to iterate over all valid GPU devices.
170  *
171  * @param dev_id
172  *   The ID of the next possible valid device, usually 0 to iterate all.
173  */
174 #define RTE_GPU_FOREACH(dev_id) \
175         RTE_GPU_FOREACH_CHILD(dev_id, RTE_GPU_ID_ANY)
176
177 /**
178  * @warning
179  * @b EXPERIMENTAL: this API may change without prior notice.
180  *
181  * Macro to iterate over all valid computing devices having no parent.
182  *
183  * @param dev_id
184  *   The ID of the next possible valid device, usually 0 to iterate all.
185  */
186 #define RTE_GPU_FOREACH_PARENT(dev_id) \
187         RTE_GPU_FOREACH_CHILD(dev_id, RTE_GPU_ID_NONE)
188
189 /**
190  * @warning
191  * @b EXPERIMENTAL: this API may change without prior notice.
192  *
193  * Macro to iterate over all valid children of a computing device parent.
194  *
195  * @param dev_id
196  *   The ID of the next possible valid device, usually 0 to iterate all.
197  * @param parent
198  *   The device ID of the parent.
199  */
200 #define RTE_GPU_FOREACH_CHILD(dev_id, parent) \
201         for (dev_id = rte_gpu_find_next(0, parent); \
202              dev_id >= 0; \
203              dev_id = rte_gpu_find_next(dev_id + 1, parent))
204
205 /**
206  * @warning
207  * @b EXPERIMENTAL: this API may change without prior notice.
208  *
209  * Close device or child context.
210  * All resources are released.
211  *
212  * @param dev_id
213  *   Device ID to close.
214  *
215  * @return
216  *   0 on success, -rte_errno otherwise:
217  *   - ENODEV if invalid dev_id
218  *   - EPERM if driver error
219  */
220 __rte_experimental
221 int rte_gpu_close(int16_t dev_id);
222
223 /**
224  * @warning
225  * @b EXPERIMENTAL: this API may change without prior notice.
226  *
227  * Register a function as event callback.
228  * A function may be registered multiple times for different events.
229  *
230  * @param dev_id
231  *   Device ID to get notified about.
232  *   RTE_GPU_ID_ANY means all devices.
233  * @param event
234  *   Device event to be registered for.
235  * @param function
236  *   Callback function to be called on event.
237  * @param user_data
238  *   Optional parameter passed in the callback.
239  *
240  * @return
241  *   0 on success, -rte_errno otherwise:
242  *   - ENODEV if invalid dev_id
243  *   - EINVAL if NULL function
244  *   - ENOMEM if out of memory
245  */
246 __rte_experimental
247 int rte_gpu_callback_register(int16_t dev_id, enum rte_gpu_event event,
248                 rte_gpu_callback_t *function, void *user_data);
249
250 /**
251  * @warning
252  * @b EXPERIMENTAL: this API may change without prior notice.
253  *
254  * Unregister for an event.
255  *
256  * @param dev_id
257  *   Device ID to be silenced.
258  *   RTE_GPU_ID_ANY means all devices.
259  * @param event
260  *   Registered event.
261  * @param function
262  *   Registered function.
263  * @param user_data
264  *   Optional parameter as registered.
265  *   RTE_GPU_CALLBACK_ANY_DATA is a catch-all.
266  *
267  * @return
268  *   0 on success, -rte_errno otherwise:
269  *   - ENODEV if invalid dev_id
270  *   - EINVAL if NULL function
271  */
272 __rte_experimental
273 int rte_gpu_callback_unregister(int16_t dev_id, enum rte_gpu_event event,
274                 rte_gpu_callback_t *function, void *user_data);
275
276 /**
277  * @warning
278  * @b EXPERIMENTAL: this API may change without prior notice.
279  *
280  * Return device specific info.
281  *
282  * @param dev_id
283  *   Device ID to get info.
284  * @param info
285  *   Memory structure to fill with the info.
286  *
287  * @return
288  *   0 on success, -rte_errno otherwise:
289  *   - ENODEV if invalid dev_id
290  *   - EINVAL if NULL info
291  *   - EPERM if driver error
292  */
293 __rte_experimental
294 int rte_gpu_info_get(int16_t dev_id, struct rte_gpu_info *info);
295
296 /**
297  * @warning
298  * @b EXPERIMENTAL: this API may change without prior notice.
299  *
300  * Allocate a chunk of memory in the device.
301  *
302  * @param dev_id
303  *   Device ID requiring allocated memory.
304  * @param size
305  *   Number of bytes to allocate.
306  *   Requesting 0 will do nothing.
307  *
308  * @return
309  *   A pointer to the allocated memory, otherwise NULL and rte_errno is set:
310  *   - ENODEV if invalid dev_id
311  *   - EINVAL if reserved flags
312  *   - ENOTSUP if operation not supported by the driver
313  *   - E2BIG if size is higher than limit
314  *   - ENOMEM if out of space
315  *   - EPERM if driver error
316  */
317 __rte_experimental
318 void *rte_gpu_mem_alloc(int16_t dev_id, size_t size)
319 __rte_alloc_size(2);
320
321 /**
322  * @warning
323  * @b EXPERIMENTAL: this API may change without prior notice.
324  *
325  * Deallocate a chunk of memory allocated with rte_gpu_mem_alloc().
326  *
327  * @param dev_id
328  *   Reference device ID.
329  * @param ptr
330  *   Pointer to the memory area to be deallocated.
331  *   NULL is a no-op accepted value.
332  *
333  * @return
334  *   0 on success, -rte_errno otherwise:
335  *   - ENODEV if invalid dev_id
336  *   - ENOTSUP if operation not supported by the driver
337  *   - EPERM if driver error
338  */
339 __rte_experimental
340 int rte_gpu_mem_free(int16_t dev_id, void *ptr);
341
342 /**
343  * @warning
344  * @b EXPERIMENTAL: this API may change without prior notice.
345  *
346  * Register a chunk of memory on the CPU usable by the device.
347  *
348  * @param dev_id
349  *   Device ID requiring allocated memory.
350  * @param size
351  *   Number of bytes to allocate.
352  *   Requesting 0 will do nothing.
353  * @param ptr
354  *   Pointer to the memory area to be registered.
355  *   NULL is a no-op accepted value.
356
357  * @return
358  *   A pointer to the allocated memory, otherwise NULL and rte_errno is set:
359  *   - ENODEV if invalid dev_id
360  *   - EINVAL if reserved flags
361  *   - ENOTSUP if operation not supported by the driver
362  *   - E2BIG if size is higher than limit
363  *   - ENOMEM if out of space
364  *   - EPERM if driver error
365  */
366 __rte_experimental
367 int rte_gpu_mem_register(int16_t dev_id, size_t size, void *ptr);
368
369 /**
370  * @warning
371  * @b EXPERIMENTAL: this API may change without prior notice.
372  *
373  * Deregister a chunk of memory previously registered with rte_gpu_mem_register()
374  *
375  * @param dev_id
376  *   Reference device ID.
377  * @param ptr
378  *   Pointer to the memory area to be unregistered.
379  *   NULL is a no-op accepted value.
380  *
381  * @return
382  *   0 on success, -rte_errno otherwise:
383  *   - ENODEV if invalid dev_id
384  *   - ENOTSUP if operation not supported by the driver
385  *   - EPERM if driver error
386  */
387 __rte_experimental
388 int rte_gpu_mem_unregister(int16_t dev_id, void *ptr);
389
390 #ifdef __cplusplus
391 }
392 #endif
393
394 #endif /* RTE_GPUDEV_H */