aeb021f2ccfb3ad27f0fdd6f7d8c3e61d5b268b4
[dpdk.git] / lib / gpudev / gpudev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2021 NVIDIA Corporation & Affiliates
3  */
4
5 #include <rte_eal.h>
6 #include <rte_string_fns.h>
7 #include <rte_errno.h>
8 #include <rte_log.h>
9
10 #include "rte_gpudev.h"
11 #include "gpudev_driver.h"
12
13 /* Logging */
14 RTE_LOG_REGISTER_DEFAULT(gpu_logtype, NOTICE);
15 #define GPU_LOG(level, ...) \
16         rte_log(RTE_LOG_ ## level, gpu_logtype, RTE_FMT("gpu: " \
17                 RTE_FMT_HEAD(__VA_ARGS__, ) "\n", RTE_FMT_TAIL(__VA_ARGS__, )))
18
19 /* Set any driver error as EPERM */
20 #define GPU_DRV_RET(function) \
21         ((function != 0) ? -(rte_errno = EPERM) : (rte_errno = 0))
22
23 /* Array of devices */
24 static struct rte_gpu *gpus;
25 /* Number of currently valid devices */
26 static int16_t gpu_max;
27 /* Number of currently valid devices */
28 static int16_t gpu_count;
29
30 int
31 rte_gpu_init(size_t dev_max)
32 {
33         if (dev_max == 0 || dev_max > INT16_MAX) {
34                 GPU_LOG(ERR, "invalid array size");
35                 rte_errno = EINVAL;
36                 return -rte_errno;
37         }
38
39         /* No lock, it must be called before or during first probing. */
40         if (gpus != NULL) {
41                 GPU_LOG(ERR, "already initialized");
42                 rte_errno = EBUSY;
43                 return -rte_errno;
44         }
45
46         gpus = calloc(dev_max, sizeof(struct rte_gpu));
47         if (gpus == NULL) {
48                 GPU_LOG(ERR, "cannot initialize library");
49                 rte_errno = ENOMEM;
50                 return -rte_errno;
51         }
52
53         gpu_max = dev_max;
54         return 0;
55 }
56
57 uint16_t
58 rte_gpu_count_avail(void)
59 {
60         return gpu_count;
61 }
62
63 bool
64 rte_gpu_is_valid(int16_t dev_id)
65 {
66         if (dev_id >= 0 && dev_id < gpu_max &&
67                 gpus[dev_id].state == RTE_GPU_STATE_INITIALIZED)
68                 return true;
69         return false;
70 }
71
72 int16_t
73 rte_gpu_find_next(int16_t dev_id)
74 {
75         if (dev_id < 0)
76                 dev_id = 0;
77         while (dev_id < gpu_max &&
78                         gpus[dev_id].state == RTE_GPU_STATE_UNUSED)
79                 dev_id++;
80
81         if (dev_id >= gpu_max)
82                 return RTE_GPU_ID_NONE;
83         return dev_id;
84 }
85
86 static int16_t
87 gpu_find_free_id(void)
88 {
89         int16_t dev_id;
90
91         for (dev_id = 0; dev_id < gpu_max; dev_id++) {
92                 if (gpus[dev_id].state == RTE_GPU_STATE_UNUSED)
93                         return dev_id;
94         }
95         return RTE_GPU_ID_NONE;
96 }
97
98 static struct rte_gpu *
99 gpu_get_by_id(int16_t dev_id)
100 {
101         if (!rte_gpu_is_valid(dev_id))
102                 return NULL;
103         return &gpus[dev_id];
104 }
105
106 struct rte_gpu *
107 rte_gpu_get_by_name(const char *name)
108 {
109         int16_t dev_id;
110         struct rte_gpu *dev;
111
112         if (name == NULL) {
113                 rte_errno = EINVAL;
114                 return NULL;
115         }
116
117         RTE_GPU_FOREACH(dev_id) {
118                 dev = &gpus[dev_id];
119                 if (strncmp(name, dev->name, RTE_DEV_NAME_MAX_LEN) == 0)
120                         return dev;
121         }
122         return NULL;
123 }
124
125 struct rte_gpu *
126 rte_gpu_allocate(const char *name)
127 {
128         int16_t dev_id;
129         struct rte_gpu *dev;
130
131         if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
132                 GPU_LOG(ERR, "only primary process can allocate device");
133                 rte_errno = EPERM;
134                 return NULL;
135         }
136         if (name == NULL) {
137                 GPU_LOG(ERR, "allocate device without a name");
138                 rte_errno = EINVAL;
139                 return NULL;
140         }
141
142         /* implicit initialization of library before adding first device */
143         if (gpus == NULL && rte_gpu_init(RTE_GPU_DEFAULT_MAX) < 0)
144                 return NULL;
145
146         if (rte_gpu_get_by_name(name) != NULL) {
147                 GPU_LOG(ERR, "device with name %s already exists", name);
148                 rte_errno = EEXIST;
149                 return NULL;
150         }
151         dev_id = gpu_find_free_id();
152         if (dev_id == RTE_GPU_ID_NONE) {
153                 GPU_LOG(ERR, "reached maximum number of devices");
154                 rte_errno = ENOENT;
155                 return NULL;
156         }
157
158         dev = &gpus[dev_id];
159         memset(dev, 0, sizeof(*dev));
160
161         if (rte_strscpy(dev->name, name, RTE_DEV_NAME_MAX_LEN) < 0) {
162                 GPU_LOG(ERR, "device name too long: %s", name);
163                 rte_errno = ENAMETOOLONG;
164                 return NULL;
165         }
166         dev->info.name = dev->name;
167         dev->info.dev_id = dev_id;
168         dev->info.numa_node = -1;
169
170         gpu_count++;
171         GPU_LOG(DEBUG, "new device %s (id %d) of total %d",
172                         name, dev_id, gpu_count);
173         return dev;
174 }
175
176 void
177 rte_gpu_complete_new(struct rte_gpu *dev)
178 {
179         if (dev == NULL)
180                 return;
181
182         dev->state = RTE_GPU_STATE_INITIALIZED;
183 }
184
185 int
186 rte_gpu_release(struct rte_gpu *dev)
187 {
188         if (dev == NULL) {
189                 rte_errno = ENODEV;
190                 return -rte_errno;
191         }
192
193         GPU_LOG(DEBUG, "free device %s (id %d)",
194                         dev->info.name, dev->info.dev_id);
195         dev->state = RTE_GPU_STATE_UNUSED;
196         gpu_count--;
197
198         return 0;
199 }
200
201 int
202 rte_gpu_close(int16_t dev_id)
203 {
204         int firsterr, binerr;
205         int *lasterr = &firsterr;
206         struct rte_gpu *dev;
207
208         dev = gpu_get_by_id(dev_id);
209         if (dev == NULL) {
210                 GPU_LOG(ERR, "close invalid device ID %d", dev_id);
211                 rte_errno = ENODEV;
212                 return -rte_errno;
213         }
214
215         if (dev->ops.dev_close != NULL) {
216                 *lasterr = GPU_DRV_RET(dev->ops.dev_close(dev));
217                 if (*lasterr != 0)
218                         lasterr = &binerr;
219         }
220
221         *lasterr = rte_gpu_release(dev);
222
223         rte_errno = -firsterr;
224         return firsterr;
225 }
226
227 int
228 rte_gpu_info_get(int16_t dev_id, struct rte_gpu_info *info)
229 {
230         struct rte_gpu *dev;
231
232         dev = gpu_get_by_id(dev_id);
233         if (dev == NULL) {
234                 GPU_LOG(ERR, "query invalid device ID %d", dev_id);
235                 rte_errno = ENODEV;
236                 return -rte_errno;
237         }
238         if (info == NULL) {
239                 GPU_LOG(ERR, "query without storage");
240                 rte_errno = EINVAL;
241                 return -rte_errno;
242         }
243
244         if (dev->ops.dev_info_get == NULL) {
245                 *info = dev->info;
246                 return 0;
247         }
248         return GPU_DRV_RET(dev->ops.dev_info_get(dev, info));
249 }