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