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