xref: /dpdk/drivers/gpu/cuda/cuda.c (revision 7850d19f3f189cd07def97bf5ea5ffe68755fac8)
11306a73bSElena Agostini /* SPDX-License-Identifier: BSD-3-Clause
21306a73bSElena Agostini  * Copyright (c) 2021 NVIDIA Corporation & Affiliates
31306a73bSElena Agostini  */
41306a73bSElena Agostini 
51306a73bSElena Agostini #include <dlfcn.h>
61306a73bSElena Agostini 
71306a73bSElena Agostini #include <rte_malloc.h>
81306a73bSElena Agostini #include <rte_pci.h>
91306a73bSElena Agostini #include <rte_bus_pci.h>
101306a73bSElena Agostini #include <rte_byteorder.h>
111306a73bSElena Agostini #include <rte_dev.h>
121306a73bSElena Agostini 
131306a73bSElena Agostini #include <gpudev_driver.h>
1424c77594SElena Agostini 
151306a73bSElena Agostini #include <cuda.h>
161306a73bSElena Agostini #include <cudaTypedefs.h>
171306a73bSElena Agostini 
1824c77594SElena Agostini #include "common.h"
19*7850d19fSElena Agostini #include "devices.h"
2024c77594SElena Agostini 
211306a73bSElena Agostini #define CUDA_DRIVER_MIN_VERSION 11040
221306a73bSElena Agostini #define CUDA_API_MIN_VERSION 3020
231306a73bSElena Agostini 
241306a73bSElena Agostini /* CUDA Driver functions loaded with dlsym() */
251306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuInit)(unsigned int flags);
261306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuDriverGetVersion)(int *driverVersion);
271306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuGetProcAddress)(const char *symbol,
281306a73bSElena Agostini 		void **pfn, int cudaVersion, uint64_t flags);
291306a73bSElena Agostini 
301306a73bSElena Agostini /* CUDA Driver functions loaded with cuGetProcAddress for versioning */
311306a73bSElena Agostini static PFN_cuGetErrorString pfn_cuGetErrorString;
321306a73bSElena Agostini static PFN_cuGetErrorName pfn_cuGetErrorName;
331306a73bSElena Agostini static PFN_cuPointerSetAttribute pfn_cuPointerSetAttribute;
341306a73bSElena Agostini static PFN_cuDeviceGetAttribute pfn_cuDeviceGetAttribute;
351306a73bSElena Agostini static PFN_cuDeviceGetByPCIBusId pfn_cuDeviceGetByPCIBusId;
361306a73bSElena Agostini static PFN_cuDevicePrimaryCtxRetain pfn_cuDevicePrimaryCtxRetain;
371306a73bSElena Agostini static PFN_cuDevicePrimaryCtxRelease pfn_cuDevicePrimaryCtxRelease;
381306a73bSElena Agostini static PFN_cuDeviceTotalMem pfn_cuDeviceTotalMem;
391306a73bSElena Agostini static PFN_cuDeviceGetName pfn_cuDeviceGetName;
401306a73bSElena Agostini static PFN_cuCtxGetApiVersion pfn_cuCtxGetApiVersion;
411306a73bSElena Agostini static PFN_cuCtxSetCurrent pfn_cuCtxSetCurrent;
421306a73bSElena Agostini static PFN_cuCtxGetCurrent pfn_cuCtxGetCurrent;
431306a73bSElena Agostini static PFN_cuCtxGetDevice pfn_cuCtxGetDevice;
441306a73bSElena Agostini static PFN_cuCtxGetExecAffinity pfn_cuCtxGetExecAffinity;
451306a73bSElena Agostini static PFN_cuMemAlloc pfn_cuMemAlloc;
461306a73bSElena Agostini static PFN_cuMemFree pfn_cuMemFree;
471306a73bSElena Agostini static PFN_cuMemHostRegister pfn_cuMemHostRegister;
481306a73bSElena Agostini static PFN_cuMemHostUnregister pfn_cuMemHostUnregister;
491306a73bSElena Agostini static PFN_cuMemHostGetDevicePointer pfn_cuMemHostGetDevicePointer;
501306a73bSElena Agostini static PFN_cuFlushGPUDirectRDMAWrites pfn_cuFlushGPUDirectRDMAWrites;
511306a73bSElena Agostini 
521306a73bSElena Agostini static void *cudalib;
531306a73bSElena Agostini static unsigned int cuda_api_version;
541306a73bSElena Agostini static int cuda_driver_version;
5524c77594SElena Agostini static gdr_t gdrc_h;
561306a73bSElena Agostini 
571306a73bSElena Agostini #define CUDA_MAX_ALLOCATION_NUM 512
581306a73bSElena Agostini 
591306a73bSElena Agostini #define GPU_PAGE_SHIFT 16
601306a73bSElena Agostini #define GPU_PAGE_SIZE (1UL << GPU_PAGE_SHIFT)
611306a73bSElena Agostini 
6224c77594SElena Agostini RTE_LOG_REGISTER_DEFAULT(cuda_logtype, NOTICE);
631306a73bSElena Agostini 
641306a73bSElena Agostini /* NVIDIA GPU address map */
651306a73bSElena Agostini static const struct rte_pci_id pci_id_cuda_map[] = {
661306a73bSElena Agostini 	{
671306a73bSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
68*7850d19fSElena Agostini 				NVIDIA_GPU_A40_DEVICE_ID)
6965ac1464SElena Agostini 	},
7065ac1464SElena Agostini 	{
7165ac1464SElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
721306a73bSElena Agostini 				NVIDIA_GPU_A30_24GB_DEVICE_ID)
731306a73bSElena Agostini 	},
741306a73bSElena Agostini 	{
751306a73bSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
76*7850d19fSElena Agostini 				NVIDIA_GPU_A30X_24GB_DPU_DEVICE_ID)
77442876b2SElena Agostini 	},
78442876b2SElena Agostini 	{
79442876b2SElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
801306a73bSElena Agostini 				NVIDIA_GPU_A10_24GB_DEVICE_ID)
811306a73bSElena Agostini 	},
821306a73bSElena Agostini 	{
831306a73bSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
84*7850d19fSElena Agostini 				NVIDIA_GPU_A10G_DEVICE_ID)
85*7850d19fSElena Agostini 	},
86*7850d19fSElena Agostini 	{
87*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
88*7850d19fSElena Agostini 				NVIDIA_GPU_A10M_DEVICE_ID)
89*7850d19fSElena Agostini 	},
90*7850d19fSElena Agostini 	{
91*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
92*7850d19fSElena Agostini 				NVIDIA_GPU_A100_40GB_SXM4_DEVICE_ID)
93*7850d19fSElena Agostini 	},
94*7850d19fSElena Agostini 	{
95*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
96*7850d19fSElena Agostini 				NVIDIA_GPU_A100_40GB_PCIE_DEVICE_ID)
97*7850d19fSElena Agostini 	},
98*7850d19fSElena Agostini 	{
99*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
100*7850d19fSElena Agostini 				NVIDIA_GPU_A100_80GB_SXM4_DEVICE_ID)
101*7850d19fSElena Agostini 	},
102*7850d19fSElena Agostini 	{
103*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
104*7850d19fSElena Agostini 				NVIDIA_GPU_A100_80GB_PCIE_DEVICE_ID)
105*7850d19fSElena Agostini 	},
106*7850d19fSElena Agostini 	{
107*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
108*7850d19fSElena Agostini 				NVIDIA_GPU_A100X_80GB_DPU_DEVICE_ID)
109*7850d19fSElena Agostini 	},
110*7850d19fSElena Agostini 	{
111*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
112*7850d19fSElena Agostini 				NVIDIA_GPU_GA100_PG506_207)
113*7850d19fSElena Agostini 	},
114*7850d19fSElena Agostini 	{
115*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
116*7850d19fSElena Agostini 				NVIDIA_GPU_GA100_PCIE)
117*7850d19fSElena Agostini 	},
118*7850d19fSElena Agostini 	{
119*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
120*7850d19fSElena Agostini 				NVIDIA_GPU_GA100_PG506_217)
121*7850d19fSElena Agostini 	},
122*7850d19fSElena Agostini 	{
123*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
124*7850d19fSElena Agostini 				NVIDIA_GPU_V100_16GB_SXM2_DEVICE_ID)
125*7850d19fSElena Agostini 	},
126*7850d19fSElena Agostini 	{
127*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
128*7850d19fSElena Agostini 				NVIDIA_GPU_V100_16GB_DGXS_DEVICE_ID)
129*7850d19fSElena Agostini 	},
130*7850d19fSElena Agostini 	{
131*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
132*7850d19fSElena Agostini 				NVIDIA_GPU_V100_16GB_FHHL_DEVICE_ID)
133*7850d19fSElena Agostini 	},
134*7850d19fSElena Agostini 	{
135*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
136*7850d19fSElena Agostini 				NVIDIA_GPU_V100_16GB_PCIE_DEVICE_ID)
137*7850d19fSElena Agostini 	},
138*7850d19fSElena Agostini 	{
139*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
140*7850d19fSElena Agostini 				NVIDIA_GPU_V100_32GB_SXM2_DEVICE_ID)
14156b5bb50SElena Agostini 	},
14256b5bb50SElena Agostini 	{
14356b5bb50SElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
14456b5bb50SElena Agostini 				NVIDIA_GPU_V100_32GB_PCIE_DEVICE_ID)
1451306a73bSElena Agostini 	},
1461306a73bSElena Agostini 	{
1471306a73bSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
148*7850d19fSElena Agostini 				NVIDIA_GPU_V100_32GB_DGXS_DEVICE_ID)
1491306a73bSElena Agostini 	},
1501306a73bSElena Agostini 	{
1511306a73bSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
152*7850d19fSElena Agostini 				NVIDIA_GPU_V100_32GB_SXM3_DEVICE_ID)
153*7850d19fSElena Agostini 	},
154*7850d19fSElena Agostini 	{
155*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
156*7850d19fSElena Agostini 				NVIDIA_GPU_V100_32GB_SXM3_H_DEVICE_ID)
157*7850d19fSElena Agostini 	},
158*7850d19fSElena Agostini 	{
159*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
160*7850d19fSElena Agostini 				NVIDIA_GPU_V100_SXM2)
161*7850d19fSElena Agostini 	},
162*7850d19fSElena Agostini 	{
163*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
164*7850d19fSElena Agostini 				NVIDIA_GPU_V100S_PCIE)
165*7850d19fSElena Agostini 	},
166*7850d19fSElena Agostini 	{
167*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
168*7850d19fSElena Agostini 				NVIDIA_GPU_TITAN_V_CEO_ED)
169*7850d19fSElena Agostini 	},
170*7850d19fSElena Agostini 	{
171*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
172*7850d19fSElena Agostini 				NVIDIA_GPU_GV100GL_PG500_216)
173*7850d19fSElena Agostini 	},
174*7850d19fSElena Agostini 	{
175*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
176*7850d19fSElena Agostini 				NVIDIA_GPU_GV100GL_PG503_216)
177*7850d19fSElena Agostini 	},
178*7850d19fSElena Agostini 	{
179*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
180*7850d19fSElena Agostini 				NVIDIA_GPU_TU102_TITAN_RTX)
181*7850d19fSElena Agostini 	},
182*7850d19fSElena Agostini 	{
183*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
184*7850d19fSElena Agostini 				NVIDIA_GPU_TU102GL_QUADRO_RTX)
185*7850d19fSElena Agostini 	},
186*7850d19fSElena Agostini 	{
187*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
188*7850d19fSElena Agostini 				NVIDIA_GPU_GV100_QUADRO_DEVICE_ID)
189*7850d19fSElena Agostini 	},
190*7850d19fSElena Agostini 	{
191*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
192*7850d19fSElena Agostini 				NVIDIA_GPU_QUADRO_RTX_4000)
193*7850d19fSElena Agostini 	},
194*7850d19fSElena Agostini 	{
195*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
196*7850d19fSElena Agostini 				NVIDIA_GPU_QUADRO_RTX_5000)
197*7850d19fSElena Agostini 	},
198*7850d19fSElena Agostini 	{
199*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
200*7850d19fSElena Agostini 				NVIDIA_GPU_QUADRO_RTX_6000)
201*7850d19fSElena Agostini 	},
202*7850d19fSElena Agostini 	{
203*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
204*7850d19fSElena Agostini 				NVIDIA_GPU_QUADRO_RTX_8000)
205*7850d19fSElena Agostini 	},
206*7850d19fSElena Agostini 	{
207*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
208*7850d19fSElena Agostini 				NVIDIA_GPU_QUADRO_RTX_A4000)
209*7850d19fSElena Agostini 	},
210*7850d19fSElena Agostini 	{
211*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
212*7850d19fSElena Agostini 				NVIDIA_GPU_QUADRO_RTX_A6000)
213*7850d19fSElena Agostini 	},
214*7850d19fSElena Agostini 	{
215*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
216*7850d19fSElena Agostini 				NVIDIA_GPU_QUADRO_RTX_A5000)
217*7850d19fSElena Agostini 	},
218*7850d19fSElena Agostini 	{
219*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
220*7850d19fSElena Agostini 				NVIDIA_GPU_QUADRO_RTX_A4500)
221*7850d19fSElena Agostini 	},
222*7850d19fSElena Agostini 	{
223*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
224*7850d19fSElena Agostini 				NVIDIA_GPU_QUADRO_RTX_A5500)
225*7850d19fSElena Agostini 	},
226*7850d19fSElena Agostini 	{
227*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
228*7850d19fSElena Agostini 				NVIDIA_GPU_QUADRO_RTX_A2000)
229*7850d19fSElena Agostini 	},
230*7850d19fSElena Agostini 	{
231*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
232*7850d19fSElena Agostini 				NVIDIA_GPU_QUADRO_RTX_A2000_12GB)
233*7850d19fSElena Agostini 	},
234*7850d19fSElena Agostini 	{
235*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
236*7850d19fSElena Agostini 				NVIDIA_GPU_T4G)
237*7850d19fSElena Agostini 	},
238*7850d19fSElena Agostini 	{
239*7850d19fSElena Agostini 		RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
240*7850d19fSElena Agostini 				NVIDIA_GPU_T4)
2411306a73bSElena Agostini 	},
2421306a73bSElena Agostini 	{
2431306a73bSElena Agostini 		.device_id = 0
2441306a73bSElena Agostini 	}
2451306a73bSElena Agostini };
2461306a73bSElena Agostini 
2471306a73bSElena Agostini /* Device private info */
2481306a73bSElena Agostini struct cuda_info {
2491306a73bSElena Agostini 	char gpu_name[RTE_DEV_NAME_MAX_LEN];
2501306a73bSElena Agostini 	CUdevice cu_dev;
2511306a73bSElena Agostini 	int gdr_supported;
2521306a73bSElena Agostini 	int gdr_write_ordering;
2531306a73bSElena Agostini 	int gdr_flush_type;
2541306a73bSElena Agostini };
2551306a73bSElena Agostini 
2561306a73bSElena Agostini /* Type of memory allocated by CUDA driver */
2571306a73bSElena Agostini enum mem_type {
2581306a73bSElena Agostini 	GPU_MEM = 0,
2591306a73bSElena Agostini 	CPU_REGISTERED,
2601306a73bSElena Agostini 	GPU_REGISTERED /* Not used yet */
2611306a73bSElena Agostini };
2621306a73bSElena Agostini 
2631306a73bSElena Agostini /* key associated to a memory address */
2641306a73bSElena Agostini typedef uintptr_t cuda_ptr_key;
2651306a73bSElena Agostini 
2661306a73bSElena Agostini /* Single entry of the memory list */
2671306a73bSElena Agostini struct mem_entry {
2681306a73bSElena Agostini 	CUdeviceptr ptr_d;
269c8557ed4SElena Agostini 	CUdeviceptr ptr_orig_d;
2701306a73bSElena Agostini 	void *ptr_h;
2711306a73bSElena Agostini 	size_t size;
272c8557ed4SElena Agostini 	size_t size_orig;
2731306a73bSElena Agostini 	struct rte_gpu *dev;
2741306a73bSElena Agostini 	CUcontext ctx;
2751306a73bSElena Agostini 	cuda_ptr_key pkey;
2761306a73bSElena Agostini 	enum mem_type mtype;
27724c77594SElena Agostini 	gdr_mh_t mh;
2781306a73bSElena Agostini 	struct mem_entry *prev;
2791306a73bSElena Agostini 	struct mem_entry *next;
2801306a73bSElena Agostini };
2811306a73bSElena Agostini 
2821306a73bSElena Agostini static struct mem_entry *mem_alloc_list_head;
2831306a73bSElena Agostini static struct mem_entry *mem_alloc_list_tail;
2841306a73bSElena Agostini static uint32_t mem_alloc_list_last_elem;
2851306a73bSElena Agostini 
2861306a73bSElena Agostini /* Load the CUDA symbols */
2871306a73bSElena Agostini 
2881306a73bSElena Agostini static int
2891306a73bSElena Agostini cuda_loader(void)
2901306a73bSElena Agostini {
2911306a73bSElena Agostini 	char cuda_path[1024];
2921306a73bSElena Agostini 
2931306a73bSElena Agostini 	if (getenv("CUDA_PATH_L") == NULL)
2941306a73bSElena Agostini 		snprintf(cuda_path, 1024, "%s", "libcuda.so");
2951306a73bSElena Agostini 	else
2960105d49eSElena Agostini 		snprintf(cuda_path, 1024, "%s/%s", getenv("CUDA_PATH_L"), "libcuda.so");
2971306a73bSElena Agostini 
2981306a73bSElena Agostini 	cudalib = dlopen(cuda_path, RTLD_LAZY);
2991306a73bSElena Agostini 	if (cudalib == NULL) {
3001306a73bSElena Agostini 		rte_cuda_log(ERR, "Failed to find CUDA library in %s (CUDA_PATH_L=%s)",
3011306a73bSElena Agostini 				cuda_path, getenv("CUDA_PATH_L"));
3021306a73bSElena Agostini 		return -1;
3031306a73bSElena Agostini 	}
3041306a73bSElena Agostini 
3051306a73bSElena Agostini 	return 0;
3061306a73bSElena Agostini }
3071306a73bSElena Agostini 
3081306a73bSElena Agostini static int
3091306a73bSElena Agostini cuda_sym_func_loader(void)
3101306a73bSElena Agostini {
3111306a73bSElena Agostini 	if (cudalib == NULL)
3121306a73bSElena Agostini 		return -1;
3131306a73bSElena Agostini 
3141306a73bSElena Agostini 	sym_cuInit = dlsym(cudalib, "cuInit");
3151306a73bSElena Agostini 	if (sym_cuInit == NULL) {
3161306a73bSElena Agostini 		rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuInit");
3171306a73bSElena Agostini 		return -1;
3181306a73bSElena Agostini 	}
3191306a73bSElena Agostini 
3201306a73bSElena Agostini 	sym_cuDriverGetVersion = dlsym(cudalib, "cuDriverGetVersion");
3211306a73bSElena Agostini 	if (sym_cuDriverGetVersion == NULL) {
3221306a73bSElena Agostini 		rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuDriverGetVersion");
3231306a73bSElena Agostini 		return -1;
3241306a73bSElena Agostini 	}
3251306a73bSElena Agostini 
3261306a73bSElena Agostini 	sym_cuGetProcAddress = dlsym(cudalib, "cuGetProcAddress");
3271306a73bSElena Agostini 	if (sym_cuGetProcAddress == NULL) {
3281306a73bSElena Agostini 		rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuGetProcAddress");
3291306a73bSElena Agostini 		return -1;
3301306a73bSElena Agostini 	}
3311306a73bSElena Agostini 
3321306a73bSElena Agostini 	return 0;
3331306a73bSElena Agostini }
3341306a73bSElena Agostini 
3351306a73bSElena Agostini static int
3361306a73bSElena Agostini cuda_pfn_func_loader(void)
3371306a73bSElena Agostini {
3381306a73bSElena Agostini 	CUresult res;
3391306a73bSElena Agostini 
3401306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuGetErrorString",
3411306a73bSElena Agostini 			(void **) (&pfn_cuGetErrorString), cuda_driver_version, 0);
3421306a73bSElena Agostini 	if (res != 0) {
3431306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuGetErrorString failed with %d", res);
3441306a73bSElena Agostini 		return -1;
3451306a73bSElena Agostini 	}
3461306a73bSElena Agostini 
3471306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuGetErrorName",
3481306a73bSElena Agostini 			(void **)(&pfn_cuGetErrorName), cuda_driver_version, 0);
3491306a73bSElena Agostini 	if (res != 0) {
3501306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuGetErrorName failed with %d", res);
3511306a73bSElena Agostini 		return -1;
3521306a73bSElena Agostini 	}
3531306a73bSElena Agostini 
3541306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuPointerSetAttribute",
3551306a73bSElena Agostini 			(void **)(&pfn_cuPointerSetAttribute), cuda_driver_version, 0);
3561306a73bSElena Agostini 	if (res != 0) {
3571306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuPointerSetAttribute failed with %d", res);
3581306a73bSElena Agostini 		return -1;
3591306a73bSElena Agostini 	}
3601306a73bSElena Agostini 
3611306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuDeviceGetAttribute",
3621306a73bSElena Agostini 			(void **)(&pfn_cuDeviceGetAttribute), cuda_driver_version, 0);
3631306a73bSElena Agostini 	if (res != 0) {
3641306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetAttribute failed with %d", res);
3651306a73bSElena Agostini 		return -1;
3661306a73bSElena Agostini 	}
3671306a73bSElena Agostini 
3681306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuDeviceGetByPCIBusId",
3691306a73bSElena Agostini 			(void **)(&pfn_cuDeviceGetByPCIBusId), cuda_driver_version, 0);
3701306a73bSElena Agostini 	if (res != 0) {
3711306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetByPCIBusId failed with %d", res);
3721306a73bSElena Agostini 		return -1;
3731306a73bSElena Agostini 	}
3741306a73bSElena Agostini 
3751306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuDeviceGetName",
3761306a73bSElena Agostini 			(void **)(&pfn_cuDeviceGetName), cuda_driver_version, 0);
3771306a73bSElena Agostini 	if (res != 0) {
3781306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetName failed with %d", res);
3791306a73bSElena Agostini 		return -1;
3801306a73bSElena Agostini 	}
3811306a73bSElena Agostini 
3821306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuDevicePrimaryCtxRetain",
3831306a73bSElena Agostini 			(void **)(&pfn_cuDevicePrimaryCtxRetain), cuda_driver_version, 0);
3841306a73bSElena Agostini 	if (res != 0) {
3851306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuDevicePrimaryCtxRetain failed with %d", res);
3861306a73bSElena Agostini 		return -1;
3871306a73bSElena Agostini 	}
3881306a73bSElena Agostini 
3891306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuDevicePrimaryCtxRelease",
3901306a73bSElena Agostini 			(void **)(&pfn_cuDevicePrimaryCtxRelease), cuda_driver_version, 0);
3911306a73bSElena Agostini 	if (res != 0) {
3921306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuDevicePrimaryCtxRelease failed with %d", res);
3931306a73bSElena Agostini 		return -1;
3941306a73bSElena Agostini 	}
3951306a73bSElena Agostini 
3961306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuDeviceTotalMem",
3971306a73bSElena Agostini 			(void **)(&pfn_cuDeviceTotalMem), cuda_driver_version, 0);
3981306a73bSElena Agostini 	if (res != 0) {
3991306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuDeviceTotalMem failed with %d", res);
4001306a73bSElena Agostini 		return -1;
4011306a73bSElena Agostini 	}
4021306a73bSElena Agostini 
4031306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuCtxGetApiVersion",
4041306a73bSElena Agostini 			(void **)(&pfn_cuCtxGetApiVersion), cuda_driver_version, 0);
4051306a73bSElena Agostini 	if (res != 0) {
4061306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetApiVersion failed with %d", res);
4071306a73bSElena Agostini 		return -1;
4081306a73bSElena Agostini 	}
4091306a73bSElena Agostini 
4101306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuCtxGetDevice",
4111306a73bSElena Agostini 			(void **)(&pfn_cuCtxGetDevice), cuda_driver_version, 0);
4121306a73bSElena Agostini 	if (res != 0) {
4131306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetDevice failed with %d", res);
4141306a73bSElena Agostini 		return -1;
4151306a73bSElena Agostini 	}
4161306a73bSElena Agostini 
4171306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuCtxSetCurrent",
4181306a73bSElena Agostini 			(void **)(&pfn_cuCtxSetCurrent), cuda_driver_version, 0);
4191306a73bSElena Agostini 	if (res != 0) {
4201306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuCtxSetCurrent failed with %d", res);
4211306a73bSElena Agostini 		return -1;
4221306a73bSElena Agostini 	}
4231306a73bSElena Agostini 
4241306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuCtxGetCurrent",
4251306a73bSElena Agostini 			(void **)(&pfn_cuCtxGetCurrent), cuda_driver_version, 0);
4261306a73bSElena Agostini 	if (res != 0) {
4271306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetCurrent failed with %d", res);
4281306a73bSElena Agostini 		return -1;
4291306a73bSElena Agostini 	}
4301306a73bSElena Agostini 
4311306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuCtxGetExecAffinity",
4321306a73bSElena Agostini 			(void **)(&pfn_cuCtxGetExecAffinity), cuda_driver_version, 0);
4331306a73bSElena Agostini 	if (res != 0) {
4341306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetExecAffinity failed with %d", res);
4351306a73bSElena Agostini 		return -1;
4361306a73bSElena Agostini 	}
4371306a73bSElena Agostini 
4381306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuMemAlloc",
4391306a73bSElena Agostini 			(void **)(&pfn_cuMemAlloc), cuda_driver_version, 0);
4401306a73bSElena Agostini 	if (res != 0) {
4411306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuMemAlloc failed with %d", res);
4421306a73bSElena Agostini 		return -1;
4431306a73bSElena Agostini 	}
4441306a73bSElena Agostini 
4451306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuMemFree",
4461306a73bSElena Agostini 			(void **)(&pfn_cuMemFree), cuda_driver_version, 0);
4471306a73bSElena Agostini 	if (res != 0) {
4481306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuMemFree failed with %d", res);
4491306a73bSElena Agostini 		return -1;
4501306a73bSElena Agostini 	}
4511306a73bSElena Agostini 
4521306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuMemHostRegister",
4531306a73bSElena Agostini 			(void **)(&pfn_cuMemHostRegister), cuda_driver_version, 0);
4541306a73bSElena Agostini 	if (res != 0) {
4551306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuMemHostRegister failed with %d", res);
4561306a73bSElena Agostini 		return -1;
4571306a73bSElena Agostini 	}
4581306a73bSElena Agostini 
4591306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuMemHostUnregister",
4601306a73bSElena Agostini 			(void **)(&pfn_cuMemHostUnregister), cuda_driver_version, 0);
4611306a73bSElena Agostini 	if (res != 0) {
4621306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuMemHostUnregister failed with %d", res);
4631306a73bSElena Agostini 		return -1;
4641306a73bSElena Agostini 	}
4651306a73bSElena Agostini 
4661306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuMemHostGetDevicePointer",
4671306a73bSElena Agostini 			(void **)(&pfn_cuMemHostGetDevicePointer), cuda_driver_version, 0);
4681306a73bSElena Agostini 	if (res != 0) {
4691306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve pfn_cuMemHostGetDevicePointer failed with %d", res);
4701306a73bSElena Agostini 		return -1;
4711306a73bSElena Agostini 	}
4721306a73bSElena Agostini 
4731306a73bSElena Agostini 	res = sym_cuGetProcAddress("cuFlushGPUDirectRDMAWrites",
4741306a73bSElena Agostini 			(void **)(&pfn_cuFlushGPUDirectRDMAWrites), cuda_driver_version, 0);
4751306a73bSElena Agostini 	if (res != 0) {
4761306a73bSElena Agostini 		rte_cuda_log(ERR, "Retrieve cuFlushGPUDirectRDMAWrites failed with %d", res);
4771306a73bSElena Agostini 		return -1;
4781306a73bSElena Agostini 	}
4791306a73bSElena Agostini 
4801306a73bSElena Agostini 	return 0;
4811306a73bSElena Agostini }
4821306a73bSElena Agostini 
4831306a73bSElena Agostini /* Generate a key from a memory pointer */
4841306a73bSElena Agostini static cuda_ptr_key
4851306a73bSElena Agostini get_hash_from_ptr(void *ptr)
4861306a73bSElena Agostini {
4871306a73bSElena Agostini 	return (uintptr_t)ptr;
4881306a73bSElena Agostini }
4891306a73bSElena Agostini 
4901306a73bSElena Agostini static uint32_t
4911306a73bSElena Agostini mem_list_count_item(void)
4921306a73bSElena Agostini {
4931306a73bSElena Agostini 	return mem_alloc_list_last_elem;
4941306a73bSElena Agostini }
4951306a73bSElena Agostini 
4961306a73bSElena Agostini /* Initiate list of memory allocations if not done yet */
4971306a73bSElena Agostini static struct mem_entry *
4981306a73bSElena Agostini mem_list_add_item(void)
4991306a73bSElena Agostini {
5001306a73bSElena Agostini 	/* Initiate list of memory allocations if not done yet */
5011306a73bSElena Agostini 	if (mem_alloc_list_head == NULL) {
5021306a73bSElena Agostini 		mem_alloc_list_head = rte_zmalloc(NULL,
5031306a73bSElena Agostini 				sizeof(struct mem_entry),
5041306a73bSElena Agostini 				RTE_CACHE_LINE_SIZE);
5051306a73bSElena Agostini 		if (mem_alloc_list_head == NULL) {
5061306a73bSElena Agostini 			rte_cuda_log(ERR, "Failed to allocate memory for memory list");
5071306a73bSElena Agostini 			return NULL;
5081306a73bSElena Agostini 		}
5091306a73bSElena Agostini 
5101306a73bSElena Agostini 		mem_alloc_list_head->next = NULL;
5111306a73bSElena Agostini 		mem_alloc_list_head->prev = NULL;
5121306a73bSElena Agostini 		mem_alloc_list_tail = mem_alloc_list_head;
5131306a73bSElena Agostini 	} else {
5141306a73bSElena Agostini 		struct mem_entry *mem_alloc_list_cur = rte_zmalloc(NULL,
5151306a73bSElena Agostini 				sizeof(struct mem_entry),
5161306a73bSElena Agostini 				RTE_CACHE_LINE_SIZE);
5171306a73bSElena Agostini 
5181306a73bSElena Agostini 		if (mem_alloc_list_cur == NULL) {
5191306a73bSElena Agostini 			rte_cuda_log(ERR, "Failed to allocate memory for memory list");
5201306a73bSElena Agostini 			return NULL;
5211306a73bSElena Agostini 		}
5221306a73bSElena Agostini 
5231306a73bSElena Agostini 		mem_alloc_list_tail->next = mem_alloc_list_cur;
5241306a73bSElena Agostini 		mem_alloc_list_cur->prev = mem_alloc_list_tail;
5251306a73bSElena Agostini 		mem_alloc_list_tail = mem_alloc_list_tail->next;
5261306a73bSElena Agostini 		mem_alloc_list_tail->next = NULL;
5271306a73bSElena Agostini 	}
5281306a73bSElena Agostini 
5291306a73bSElena Agostini 	mem_alloc_list_last_elem++;
5301306a73bSElena Agostini 
5311306a73bSElena Agostini 	return mem_alloc_list_tail;
5321306a73bSElena Agostini }
5331306a73bSElena Agostini 
5341306a73bSElena Agostini static struct mem_entry *
5351306a73bSElena Agostini mem_list_find_item(cuda_ptr_key pk)
5361306a73bSElena Agostini {
5371306a73bSElena Agostini 	struct mem_entry *mem_alloc_list_cur = NULL;
5381306a73bSElena Agostini 
5391306a73bSElena Agostini 	if (mem_alloc_list_head == NULL) {
5401306a73bSElena Agostini 		rte_cuda_log(ERR, "Memory list doesn't exist");
5411306a73bSElena Agostini 		return NULL;
5421306a73bSElena Agostini 	}
5431306a73bSElena Agostini 
5441306a73bSElena Agostini 	if (mem_list_count_item() == 0) {
5451306a73bSElena Agostini 		rte_cuda_log(ERR, "No items in memory list");
5461306a73bSElena Agostini 		return NULL;
5471306a73bSElena Agostini 	}
5481306a73bSElena Agostini 
5491306a73bSElena Agostini 	mem_alloc_list_cur = mem_alloc_list_head;
5501306a73bSElena Agostini 
5511306a73bSElena Agostini 	while (mem_alloc_list_cur != NULL) {
5521306a73bSElena Agostini 		if (mem_alloc_list_cur->pkey == pk)
5531306a73bSElena Agostini 			return mem_alloc_list_cur;
5541306a73bSElena Agostini 		mem_alloc_list_cur = mem_alloc_list_cur->next;
5551306a73bSElena Agostini 	}
5561306a73bSElena Agostini 
5571306a73bSElena Agostini 	return mem_alloc_list_cur;
5581306a73bSElena Agostini }
5591306a73bSElena Agostini 
5601306a73bSElena Agostini static int
5611306a73bSElena Agostini mem_list_del_item(cuda_ptr_key pk)
5621306a73bSElena Agostini {
5631306a73bSElena Agostini 	struct mem_entry *mem_alloc_list_cur = NULL;
5641306a73bSElena Agostini 
5651306a73bSElena Agostini 	mem_alloc_list_cur = mem_list_find_item(pk);
5661306a73bSElena Agostini 	if (mem_alloc_list_cur == NULL)
5671306a73bSElena Agostini 		return -EINVAL;
5681306a73bSElena Agostini 
5691306a73bSElena Agostini 	/* if key is in head */
57098ddd04cSElena Agostini 	if (mem_alloc_list_cur->prev == NULL) {
5711306a73bSElena Agostini 		mem_alloc_list_head = mem_alloc_list_cur->next;
57298ddd04cSElena Agostini 		if (mem_alloc_list_head != NULL)
57398ddd04cSElena Agostini 			mem_alloc_list_head->prev = NULL;
57498ddd04cSElena Agostini 	} else {
5751306a73bSElena Agostini 		mem_alloc_list_cur->prev->next = mem_alloc_list_cur->next;
5761306a73bSElena Agostini 		if (mem_alloc_list_cur->next != NULL)
5771306a73bSElena Agostini 			mem_alloc_list_cur->next->prev = mem_alloc_list_cur->prev;
5781306a73bSElena Agostini 	}
5791306a73bSElena Agostini 
5801306a73bSElena Agostini 	rte_free(mem_alloc_list_cur);
5811306a73bSElena Agostini 
5821306a73bSElena Agostini 	mem_alloc_list_last_elem--;
5831306a73bSElena Agostini 
5841306a73bSElena Agostini 	return 0;
5851306a73bSElena Agostini }
5861306a73bSElena Agostini 
5871306a73bSElena Agostini static int
5881306a73bSElena Agostini cuda_dev_info_get(struct rte_gpu *dev, struct rte_gpu_info *info)
5891306a73bSElena Agostini {
5901306a73bSElena Agostini 	int ret = 0;
5911306a73bSElena Agostini 	CUresult res;
5921306a73bSElena Agostini 	struct rte_gpu_info parent_info;
5931306a73bSElena Agostini 	CUexecAffinityParam affinityPrm;
5941306a73bSElena Agostini 	const char *err_string;
5951306a73bSElena Agostini 	struct cuda_info *private;
5961306a73bSElena Agostini 	CUcontext current_ctx;
5971306a73bSElena Agostini 	CUcontext input_ctx;
5981306a73bSElena Agostini 
59994220b39SElena Agostini 	if (dev == NULL) {
60094220b39SElena Agostini 		rte_errno = ENODEV;
60194220b39SElena Agostini 		return -rte_errno;
60294220b39SElena Agostini 	}
6031306a73bSElena Agostini 
6041306a73bSElena Agostini 	/* Child initialization time probably called by rte_gpu_add_child() */
6051306a73bSElena Agostini 	if (dev->mpshared->info.parent != RTE_GPU_ID_NONE &&
6061306a73bSElena Agostini 			dev->mpshared->dev_private == NULL) {
6071306a73bSElena Agostini 		/* Store current ctx */
6081306a73bSElena Agostini 		res = pfn_cuCtxGetCurrent(&current_ctx);
6091306a73bSElena Agostini 		if (res != 0) {
6101306a73bSElena Agostini 			pfn_cuGetErrorString(res, &(err_string));
6111306a73bSElena Agostini 			rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s",
6121306a73bSElena Agostini 					err_string);
61394220b39SElena Agostini 			rte_errno = EPERM;
61494220b39SElena Agostini 			return -rte_errno;
6151306a73bSElena Agostini 		}
6161306a73bSElena Agostini 
6171306a73bSElena Agostini 		/* Set child ctx as current ctx */
6181306a73bSElena Agostini 		input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
6191306a73bSElena Agostini 		res = pfn_cuCtxSetCurrent(input_ctx);
6201306a73bSElena Agostini 		if (res != 0) {
6211306a73bSElena Agostini 			pfn_cuGetErrorString(res, &(err_string));
6221306a73bSElena Agostini 			rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s",
6231306a73bSElena Agostini 					err_string);
62494220b39SElena Agostini 			rte_errno = EPERM;
62594220b39SElena Agostini 			return -rte_errno;
6261306a73bSElena Agostini 		}
6271306a73bSElena Agostini 
6281306a73bSElena Agostini 		/*
6291306a73bSElena Agostini 		 * Ctx capacity info
6301306a73bSElena Agostini 		 */
6311306a73bSElena Agostini 
6321306a73bSElena Agostini 		/* MPS compatible */
6331306a73bSElena Agostini 		res = pfn_cuCtxGetExecAffinity(&affinityPrm,
6341306a73bSElena Agostini 				CU_EXEC_AFFINITY_TYPE_SM_COUNT);
6351306a73bSElena Agostini 		if (res != 0) {
6361306a73bSElena Agostini 			pfn_cuGetErrorString(res, &(err_string));
6371306a73bSElena Agostini 			rte_cuda_log(ERR, "cuCtxGetExecAffinity failed with %s",
6381306a73bSElena Agostini 					err_string);
6391306a73bSElena Agostini 		}
6401306a73bSElena Agostini 		dev->mpshared->info.processor_count =
6411306a73bSElena Agostini 				(uint32_t)affinityPrm.param.smCount.val;
6421306a73bSElena Agostini 
6431306a73bSElena Agostini 		ret = rte_gpu_info_get(dev->mpshared->info.parent, &parent_info);
64494220b39SElena Agostini 		if (ret) {
64594220b39SElena Agostini 			rte_errno = ENODEV;
64694220b39SElena Agostini 			return -rte_errno;
64794220b39SElena Agostini 		}
6481306a73bSElena Agostini 		dev->mpshared->info.total_memory = parent_info.total_memory;
6491306a73bSElena Agostini 
6501fd3de64SElena Agostini 		dev->mpshared->info.page_size = parent_info.page_size;
6511fd3de64SElena Agostini 
6521306a73bSElena Agostini 		/*
6531306a73bSElena Agostini 		 * GPU Device private info
6541306a73bSElena Agostini 		 */
6551306a73bSElena Agostini 		dev->mpshared->dev_private = rte_zmalloc(NULL,
6561306a73bSElena Agostini 				sizeof(struct cuda_info),
6571306a73bSElena Agostini 				RTE_CACHE_LINE_SIZE);
6581306a73bSElena Agostini 		if (dev->mpshared->dev_private == NULL) {
6591306a73bSElena Agostini 			rte_cuda_log(ERR, "Failed to allocate memory for GPU process private");
66094220b39SElena Agostini 			rte_errno = EPERM;
66194220b39SElena Agostini 			return -rte_errno;
6621306a73bSElena Agostini 		}
6631306a73bSElena Agostini 
6641306a73bSElena Agostini 		private = (struct cuda_info *)dev->mpshared->dev_private;
6651306a73bSElena Agostini 
6661306a73bSElena Agostini 		res = pfn_cuCtxGetDevice(&(private->cu_dev));
6671306a73bSElena Agostini 		if (res != 0) {
6681306a73bSElena Agostini 			pfn_cuGetErrorString(res, &(err_string));
6691306a73bSElena Agostini 			rte_cuda_log(ERR, "cuCtxGetDevice failed with %s",
6701306a73bSElena Agostini 					err_string);
67194220b39SElena Agostini 			rte_errno = EPERM;
67294220b39SElena Agostini 			return -rte_errno;
6731306a73bSElena Agostini 		}
6741306a73bSElena Agostini 
6751306a73bSElena Agostini 		res = pfn_cuDeviceGetName(private->gpu_name,
6761306a73bSElena Agostini 				RTE_DEV_NAME_MAX_LEN, private->cu_dev);
6771306a73bSElena Agostini 		if (res != 0) {
6781306a73bSElena Agostini 			pfn_cuGetErrorString(res, &(err_string));
6791306a73bSElena Agostini 			rte_cuda_log(ERR, "cuDeviceGetName failed with %s",
6801306a73bSElena Agostini 					err_string);
68194220b39SElena Agostini 			rte_errno = EPERM;
68294220b39SElena Agostini 			return -rte_errno;
6831306a73bSElena Agostini 		}
6841306a73bSElena Agostini 
6851306a73bSElena Agostini 		/* Restore original ctx as current ctx */
6861306a73bSElena Agostini 		res = pfn_cuCtxSetCurrent(current_ctx);
6871306a73bSElena Agostini 		if (res != 0) {
6881306a73bSElena Agostini 			pfn_cuGetErrorString(res, &(err_string));
6891306a73bSElena Agostini 			rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
6901306a73bSElena Agostini 					err_string);
69194220b39SElena Agostini 			rte_errno = EPERM;
69294220b39SElena Agostini 			return -rte_errno;
6931306a73bSElena Agostini 		}
6941306a73bSElena Agostini 	}
6951306a73bSElena Agostini 
6961306a73bSElena Agostini 	*info = dev->mpshared->info;
6971306a73bSElena Agostini 
6981306a73bSElena Agostini 	return 0;
6991306a73bSElena Agostini }
7001306a73bSElena Agostini 
7011306a73bSElena Agostini /*
7021306a73bSElena Agostini  * GPU Memory
7031306a73bSElena Agostini  */
7041306a73bSElena Agostini 
7051306a73bSElena Agostini static int
706c8557ed4SElena Agostini cuda_mem_alloc(struct rte_gpu *dev, size_t size, unsigned int align, void **ptr)
7071306a73bSElena Agostini {
7081306a73bSElena Agostini 	CUresult res;
7091306a73bSElena Agostini 	const char *err_string;
7101306a73bSElena Agostini 	CUcontext current_ctx;
7111306a73bSElena Agostini 	CUcontext input_ctx;
7121306a73bSElena Agostini 	unsigned int flag = 1;
7131306a73bSElena Agostini 
7141306a73bSElena Agostini 	if (dev == NULL)
7151306a73bSElena Agostini 		return -ENODEV;
7161306a73bSElena Agostini 
7171306a73bSElena Agostini 	/* Store current ctx */
7181306a73bSElena Agostini 	res = pfn_cuCtxGetCurrent(&current_ctx);
7191306a73bSElena Agostini 	if (res != 0) {
7201306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
7211306a73bSElena Agostini 		rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s",
7221306a73bSElena Agostini 				err_string);
72394220b39SElena Agostini 		rte_errno = EPERM;
72494220b39SElena Agostini 		return -rte_errno;
7251306a73bSElena Agostini 	}
7261306a73bSElena Agostini 
7271306a73bSElena Agostini 	/* Set child ctx as current ctx */
7281306a73bSElena Agostini 	input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
7291306a73bSElena Agostini 	res = pfn_cuCtxSetCurrent(input_ctx);
7301306a73bSElena Agostini 	if (res != 0) {
7311306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
7321306a73bSElena Agostini 		rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s",
7331306a73bSElena Agostini 				err_string);
73494220b39SElena Agostini 		rte_errno = EPERM;
73594220b39SElena Agostini 		return -rte_errno;
7361306a73bSElena Agostini 	}
7371306a73bSElena Agostini 
7381306a73bSElena Agostini 	/* Get next memory list item */
7391306a73bSElena Agostini 	mem_alloc_list_tail = mem_list_add_item();
74094220b39SElena Agostini 	if (mem_alloc_list_tail == NULL) {
74194220b39SElena Agostini 		rte_errno = EPERM;
74294220b39SElena Agostini 		return -rte_errno;
74394220b39SElena Agostini 	}
7441306a73bSElena Agostini 
7451306a73bSElena Agostini 	/* Allocate memory */
7461306a73bSElena Agostini 	mem_alloc_list_tail->size = size;
747c8557ed4SElena Agostini 	mem_alloc_list_tail->size_orig = size + align;
748c8557ed4SElena Agostini 
749c8557ed4SElena Agostini 	res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_orig_d),
750c8557ed4SElena Agostini 			mem_alloc_list_tail->size_orig);
7511306a73bSElena Agostini 	if (res != 0) {
7521306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
7531306a73bSElena Agostini 		rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
7541306a73bSElena Agostini 				err_string);
75594220b39SElena Agostini 		rte_errno = EPERM;
75694220b39SElena Agostini 		return -rte_errno;
7571306a73bSElena Agostini 	}
7581306a73bSElena Agostini 
759c8557ed4SElena Agostini 	/* Align memory address */
760c8557ed4SElena Agostini 	mem_alloc_list_tail->ptr_d = mem_alloc_list_tail->ptr_orig_d;
761c8557ed4SElena Agostini 	if (align && ((uintptr_t)mem_alloc_list_tail->ptr_d) % align)
762c8557ed4SElena Agostini 		mem_alloc_list_tail->ptr_d += (align -
763c8557ed4SElena Agostini 				(((uintptr_t)mem_alloc_list_tail->ptr_d) % align));
764c8557ed4SElena Agostini 
7651306a73bSElena Agostini 	/* GPUDirect RDMA attribute required */
7661306a73bSElena Agostini 	res = pfn_cuPointerSetAttribute(&flag,
7671306a73bSElena Agostini 			CU_POINTER_ATTRIBUTE_SYNC_MEMOPS,
7681306a73bSElena Agostini 			mem_alloc_list_tail->ptr_d);
7691306a73bSElena Agostini 	if (res != 0) {
7701306a73bSElena Agostini 		rte_cuda_log(ERR, "Could not set SYNC MEMOP attribute for "
7711306a73bSElena Agostini 				"GPU memory at  %"PRIu32", err %d",
7721306a73bSElena Agostini 				(uint32_t)mem_alloc_list_tail->ptr_d, res);
77394220b39SElena Agostini 		rte_errno = EPERM;
77494220b39SElena Agostini 		return -rte_errno;
7751306a73bSElena Agostini 	}
7761306a73bSElena Agostini 
7771306a73bSElena Agostini 	mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_d);
7781306a73bSElena Agostini 	mem_alloc_list_tail->ptr_h = NULL;
7791306a73bSElena Agostini 	mem_alloc_list_tail->dev = dev;
7801306a73bSElena Agostini 	mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
7811306a73bSElena Agostini 	mem_alloc_list_tail->mtype = GPU_MEM;
7821306a73bSElena Agostini 
7831306a73bSElena Agostini 	/* Restore original ctx as current ctx */
7841306a73bSElena Agostini 	res = pfn_cuCtxSetCurrent(current_ctx);
7851306a73bSElena Agostini 	if (res != 0) {
7861306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
7871306a73bSElena Agostini 		rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
7881306a73bSElena Agostini 				err_string);
78994220b39SElena Agostini 		rte_errno = EPERM;
79094220b39SElena Agostini 		return -rte_errno;
7911306a73bSElena Agostini 	}
7921306a73bSElena Agostini 
7931306a73bSElena Agostini 	*ptr = (void *)mem_alloc_list_tail->ptr_d;
7941306a73bSElena Agostini 
7951306a73bSElena Agostini 	return 0;
7961306a73bSElena Agostini }
7971306a73bSElena Agostini 
7981306a73bSElena Agostini static int
7991306a73bSElena Agostini cuda_mem_register(struct rte_gpu *dev, size_t size, void *ptr)
8001306a73bSElena Agostini {
8011306a73bSElena Agostini 	CUresult res;
8021306a73bSElena Agostini 	const char *err_string;
8031306a73bSElena Agostini 	CUcontext current_ctx;
8041306a73bSElena Agostini 	CUcontext input_ctx;
8051306a73bSElena Agostini 	unsigned int flag = 1;
8061306a73bSElena Agostini 	int use_ptr_h = 0;
8071306a73bSElena Agostini 
8081306a73bSElena Agostini 	if (dev == NULL)
8091306a73bSElena Agostini 		return -ENODEV;
8101306a73bSElena Agostini 
8111306a73bSElena Agostini 	/* Store current ctx */
8121306a73bSElena Agostini 	res = pfn_cuCtxGetCurrent(&current_ctx);
8131306a73bSElena Agostini 	if (res != 0) {
8141306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
8151306a73bSElena Agostini 		rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s",
8161306a73bSElena Agostini 				err_string);
81794220b39SElena Agostini 		rte_errno = EPERM;
81894220b39SElena Agostini 		return -rte_errno;
8191306a73bSElena Agostini 	}
8201306a73bSElena Agostini 
8211306a73bSElena Agostini 	/* Set child ctx as current ctx */
8221306a73bSElena Agostini 	input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
8231306a73bSElena Agostini 	res = pfn_cuCtxSetCurrent(input_ctx);
8241306a73bSElena Agostini 	if (res != 0) {
8251306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
8261306a73bSElena Agostini 		rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s",
8271306a73bSElena Agostini 				err_string);
82894220b39SElena Agostini 		rte_errno = EPERM;
82994220b39SElena Agostini 		return -rte_errno;
8301306a73bSElena Agostini 	}
8311306a73bSElena Agostini 
8321306a73bSElena Agostini 	/* Get next memory list item */
8331306a73bSElena Agostini 	mem_alloc_list_tail = mem_list_add_item();
83494220b39SElena Agostini 	if (mem_alloc_list_tail == NULL) {
83594220b39SElena Agostini 		rte_errno = EPERM;
83694220b39SElena Agostini 		return -rte_errno;
83794220b39SElena Agostini 	}
8381306a73bSElena Agostini 
8391306a73bSElena Agostini 	/* Allocate memory */
8401306a73bSElena Agostini 	mem_alloc_list_tail->size = size;
8411306a73bSElena Agostini 	mem_alloc_list_tail->ptr_h = ptr;
8421306a73bSElena Agostini 
8431306a73bSElena Agostini 	res = pfn_cuMemHostRegister(mem_alloc_list_tail->ptr_h,
8441306a73bSElena Agostini 			mem_alloc_list_tail->size,
8451306a73bSElena Agostini 			CU_MEMHOSTREGISTER_PORTABLE |
8461306a73bSElena Agostini 			CU_MEMHOSTREGISTER_DEVICEMAP);
8471306a73bSElena Agostini 	if (res != 0) {
8481306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
8491306a73bSElena Agostini 		rte_cuda_log(ERR, "cuMemHostRegister failed with %s ptr %p size %zd",
8501306a73bSElena Agostini 				err_string,
8511306a73bSElena Agostini 				mem_alloc_list_tail->ptr_h,
8521306a73bSElena Agostini 				mem_alloc_list_tail->size);
85394220b39SElena Agostini 		rte_errno = EPERM;
85494220b39SElena Agostini 		return -rte_errno;
8551306a73bSElena Agostini 	}
8561306a73bSElena Agostini 
8571306a73bSElena Agostini 	res = pfn_cuDeviceGetAttribute(&(use_ptr_h),
8581306a73bSElena Agostini 			CU_DEVICE_ATTRIBUTE_CAN_USE_HOST_POINTER_FOR_REGISTERED_MEM,
8591306a73bSElena Agostini 			((struct cuda_info *)(dev->mpshared->dev_private))->cu_dev);
8601306a73bSElena Agostini 	if (res != 0) {
8611306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
8621306a73bSElena Agostini 		rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s",
8631306a73bSElena Agostini 				err_string);
86494220b39SElena Agostini 		rte_errno = EPERM;
86594220b39SElena Agostini 		return -rte_errno;
8661306a73bSElena Agostini 	}
8671306a73bSElena Agostini 
8681306a73bSElena Agostini 	if (use_ptr_h == 0) {
8691306a73bSElena Agostini 		res = pfn_cuMemHostGetDevicePointer(&(mem_alloc_list_tail->ptr_d),
8701306a73bSElena Agostini 				mem_alloc_list_tail->ptr_h, 0);
8711306a73bSElena Agostini 		if (res != 0) {
8721306a73bSElena Agostini 			pfn_cuGetErrorString(res, &(err_string));
8731306a73bSElena Agostini 			rte_cuda_log(ERR, "cuMemHostGetDevicePointer failed with %s",
8741306a73bSElena Agostini 					err_string);
87594220b39SElena Agostini 			rte_errno = EPERM;
87694220b39SElena Agostini 			return -rte_errno;
8771306a73bSElena Agostini 		}
8781306a73bSElena Agostini 
8791306a73bSElena Agostini 		if ((uintptr_t)mem_alloc_list_tail->ptr_d !=
8801306a73bSElena Agostini 				(uintptr_t)mem_alloc_list_tail->ptr_h) {
8811306a73bSElena Agostini 			rte_cuda_log(ERR, "Host input pointer is different wrt GPU registered pointer");
88294220b39SElena Agostini 			rte_errno = ENOTSUP;
88394220b39SElena Agostini 			return -rte_errno;
8841306a73bSElena Agostini 		}
8851306a73bSElena Agostini 	} else {
8861306a73bSElena Agostini 		mem_alloc_list_tail->ptr_d = (CUdeviceptr)mem_alloc_list_tail->ptr_h;
8871306a73bSElena Agostini 	}
8881306a73bSElena Agostini 
8891306a73bSElena Agostini 	/* GPUDirect RDMA attribute required */
8901306a73bSElena Agostini 	res = pfn_cuPointerSetAttribute(&flag,
8911306a73bSElena Agostini 			CU_POINTER_ATTRIBUTE_SYNC_MEMOPS,
8921306a73bSElena Agostini 			mem_alloc_list_tail->ptr_d);
8931306a73bSElena Agostini 	if (res != 0) {
8941306a73bSElena Agostini 		rte_cuda_log(ERR, "Could not set SYNC MEMOP attribute for GPU memory at %"PRIu32
8951306a73bSElena Agostini 				", err %d", (uint32_t)mem_alloc_list_tail->ptr_d, res);
89694220b39SElena Agostini 		rte_errno = EPERM;
89794220b39SElena Agostini 		return -rte_errno;
8981306a73bSElena Agostini 	}
8991306a73bSElena Agostini 
9001306a73bSElena Agostini 	mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_h);
9011306a73bSElena Agostini 	mem_alloc_list_tail->size = size;
9021306a73bSElena Agostini 	mem_alloc_list_tail->dev = dev;
9031306a73bSElena Agostini 	mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
9041306a73bSElena Agostini 	mem_alloc_list_tail->mtype = CPU_REGISTERED;
905c8557ed4SElena Agostini 	mem_alloc_list_tail->ptr_orig_d = mem_alloc_list_tail->ptr_d;
9061306a73bSElena Agostini 
9071306a73bSElena Agostini 	/* Restore original ctx as current ctx */
9081306a73bSElena Agostini 	res = pfn_cuCtxSetCurrent(current_ctx);
9091306a73bSElena Agostini 	if (res != 0) {
9101306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
9111306a73bSElena Agostini 		rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
9121306a73bSElena Agostini 				err_string);
91394220b39SElena Agostini 		rte_errno = EPERM;
91494220b39SElena Agostini 		return -rte_errno;
9151306a73bSElena Agostini 	}
9161306a73bSElena Agostini 
9171306a73bSElena Agostini 	return 0;
9181306a73bSElena Agostini }
9191306a73bSElena Agostini 
9201306a73bSElena Agostini static int
92124c77594SElena Agostini cuda_mem_cpu_map(struct rte_gpu *dev, __rte_unused size_t size, void *ptr_in, void **ptr_out)
92224c77594SElena Agostini {
92324c77594SElena Agostini 	struct mem_entry *mem_item;
92424c77594SElena Agostini 	cuda_ptr_key hk;
92524c77594SElena Agostini 
92624c77594SElena Agostini 	if (dev == NULL)
92724c77594SElena Agostini 		return -ENODEV;
92824c77594SElena Agostini 
92924c77594SElena Agostini 	hk = get_hash_from_ptr((void *)ptr_in);
93024c77594SElena Agostini 
93124c77594SElena Agostini 	mem_item = mem_list_find_item(hk);
93224c77594SElena Agostini 	if (mem_item == NULL) {
93324c77594SElena Agostini 		rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory.", ptr_in);
93424c77594SElena Agostini 		rte_errno = EPERM;
93524c77594SElena Agostini 		return -rte_errno;
93624c77594SElena Agostini 	}
93724c77594SElena Agostini 
93824c77594SElena Agostini 	if (mem_item->mtype != GPU_MEM) {
93924c77594SElena Agostini 		rte_cuda_log(ERR, "Memory address 0x%p is not GPU memory type.", ptr_in);
94024c77594SElena Agostini 		rte_errno = EPERM;
94124c77594SElena Agostini 		return -rte_errno;
94224c77594SElena Agostini 	}
94324c77594SElena Agostini 
94424c77594SElena Agostini 	if (mem_item->size != size)
94524c77594SElena Agostini 		rte_cuda_log(WARNING,
94624c77594SElena Agostini 				"Can't expose memory area with size (%zd) different from original size (%zd).",
94724c77594SElena Agostini 				size, mem_item->size);
94824c77594SElena Agostini 
94924c77594SElena Agostini 	if (gdrcopy_pin(&gdrc_h, &(mem_item->mh), (uint64_t)mem_item->ptr_d,
95024c77594SElena Agostini 					mem_item->size, &(mem_item->ptr_h))) {
95124c77594SElena Agostini 		rte_cuda_log(ERR, "Error exposing GPU memory address 0x%p.", ptr_in);
95224c77594SElena Agostini 		rte_errno = EPERM;
95324c77594SElena Agostini 		return -rte_errno;
95424c77594SElena Agostini 	}
95524c77594SElena Agostini 
95624c77594SElena Agostini 	*ptr_out = mem_item->ptr_h;
95724c77594SElena Agostini 
95824c77594SElena Agostini 	return 0;
95924c77594SElena Agostini }
96024c77594SElena Agostini 
96124c77594SElena Agostini static int
9621306a73bSElena Agostini cuda_mem_free(struct rte_gpu *dev, void *ptr)
9631306a73bSElena Agostini {
9641306a73bSElena Agostini 	CUresult res;
9651306a73bSElena Agostini 	struct mem_entry *mem_item;
9661306a73bSElena Agostini 	const char *err_string;
9671306a73bSElena Agostini 	cuda_ptr_key hk;
9681306a73bSElena Agostini 
9691306a73bSElena Agostini 	if (dev == NULL)
9701306a73bSElena Agostini 		return -ENODEV;
9711306a73bSElena Agostini 
9721306a73bSElena Agostini 	hk = get_hash_from_ptr((void *)ptr);
9731306a73bSElena Agostini 
9741306a73bSElena Agostini 	mem_item = mem_list_find_item(hk);
9751306a73bSElena Agostini 	if (mem_item == NULL) {
9761306a73bSElena Agostini 		rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory", ptr);
97794220b39SElena Agostini 		rte_errno = EPERM;
97894220b39SElena Agostini 		return -rte_errno;
9791306a73bSElena Agostini 	}
9801306a73bSElena Agostini 
9811306a73bSElena Agostini 	if (mem_item->mtype == GPU_MEM) {
982c8557ed4SElena Agostini 		res = pfn_cuMemFree(mem_item->ptr_orig_d);
9831306a73bSElena Agostini 		if (res != 0) {
9841306a73bSElena Agostini 			pfn_cuGetErrorString(res, &(err_string));
9851306a73bSElena Agostini 			rte_cuda_log(ERR, "cuMemFree current failed with %s",
9861306a73bSElena Agostini 					err_string);
98794220b39SElena Agostini 			rte_errno = EPERM;
98894220b39SElena Agostini 			return -rte_errno;
9891306a73bSElena Agostini 		}
9901306a73bSElena Agostini 
9911306a73bSElena Agostini 		return mem_list_del_item(hk);
9921306a73bSElena Agostini 	}
9931306a73bSElena Agostini 
9941306a73bSElena Agostini 	rte_cuda_log(ERR, "Memory type %d not supported", mem_item->mtype);
9951306a73bSElena Agostini 
9961306a73bSElena Agostini 	return -EPERM;
9971306a73bSElena Agostini }
9981306a73bSElena Agostini 
9991306a73bSElena Agostini static int
10001306a73bSElena Agostini cuda_mem_unregister(struct rte_gpu *dev, void *ptr)
10011306a73bSElena Agostini {
10021306a73bSElena Agostini 	CUresult res;
10031306a73bSElena Agostini 	struct mem_entry *mem_item;
10041306a73bSElena Agostini 	const char *err_string;
10051306a73bSElena Agostini 	cuda_ptr_key hk;
10061306a73bSElena Agostini 
10071306a73bSElena Agostini 	if (dev == NULL)
10081306a73bSElena Agostini 		return -ENODEV;
10091306a73bSElena Agostini 
10101306a73bSElena Agostini 	hk = get_hash_from_ptr((void *)ptr);
10111306a73bSElena Agostini 
10121306a73bSElena Agostini 	mem_item = mem_list_find_item(hk);
10131306a73bSElena Agostini 	if (mem_item == NULL) {
10141306a73bSElena Agostini 		rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory", ptr);
101594220b39SElena Agostini 		rte_errno = EPERM;
101694220b39SElena Agostini 		return -rte_errno;
10171306a73bSElena Agostini 	}
10181306a73bSElena Agostini 
10191306a73bSElena Agostini 	if (mem_item->mtype == CPU_REGISTERED) {
10201306a73bSElena Agostini 		res = pfn_cuMemHostUnregister(ptr);
10211306a73bSElena Agostini 		if (res != 0) {
10221306a73bSElena Agostini 			pfn_cuGetErrorString(res, &(err_string));
10231306a73bSElena Agostini 			rte_cuda_log(ERR, "cuMemHostUnregister current failed with %s",
10241306a73bSElena Agostini 					err_string);
102594220b39SElena Agostini 			rte_errno = EPERM;
102694220b39SElena Agostini 			return -rte_errno;
10271306a73bSElena Agostini 		}
10281306a73bSElena Agostini 
10291306a73bSElena Agostini 		return mem_list_del_item(hk);
10301306a73bSElena Agostini 	}
10311306a73bSElena Agostini 
10321306a73bSElena Agostini 	rte_cuda_log(ERR, "Memory type %d not supported", mem_item->mtype);
10331306a73bSElena Agostini 
103494220b39SElena Agostini 	rte_errno = EPERM;
103594220b39SElena Agostini 	return -rte_errno;
10361306a73bSElena Agostini }
10371306a73bSElena Agostini 
10381306a73bSElena Agostini static int
103924c77594SElena Agostini cuda_mem_cpu_unmap(struct rte_gpu *dev, void *ptr_in)
104024c77594SElena Agostini {
104124c77594SElena Agostini 	struct mem_entry *mem_item;
104224c77594SElena Agostini 	cuda_ptr_key hk;
104324c77594SElena Agostini 
104424c77594SElena Agostini 	if (dev == NULL)
104524c77594SElena Agostini 		return -ENODEV;
104624c77594SElena Agostini 
104724c77594SElena Agostini 	hk = get_hash_from_ptr((void *)ptr_in);
104824c77594SElena Agostini 
104924c77594SElena Agostini 	mem_item = mem_list_find_item(hk);
105024c77594SElena Agostini 	if (mem_item == NULL) {
105124c77594SElena Agostini 		rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory.", ptr_in);
105224c77594SElena Agostini 		rte_errno = EPERM;
105324c77594SElena Agostini 		return -rte_errno;
105424c77594SElena Agostini 	}
105524c77594SElena Agostini 
105624c77594SElena Agostini 	if (gdrcopy_unpin(gdrc_h, mem_item->mh, (void *)mem_item->ptr_d,
105724c77594SElena Agostini 			mem_item->size)) {
105824c77594SElena Agostini 		rte_cuda_log(ERR, "Error unexposing GPU memory address 0x%p.", ptr_in);
105924c77594SElena Agostini 		rte_errno = EPERM;
106024c77594SElena Agostini 		return -rte_errno;
106124c77594SElena Agostini 	}
106224c77594SElena Agostini 
106324c77594SElena Agostini 	return 0;
106424c77594SElena Agostini }
106524c77594SElena Agostini 
106624c77594SElena Agostini static int
10671306a73bSElena Agostini cuda_dev_close(struct rte_gpu *dev)
10681306a73bSElena Agostini {
10691306a73bSElena Agostini 	if (dev == NULL)
10701306a73bSElena Agostini 		return -EINVAL;
10711306a73bSElena Agostini 
10721306a73bSElena Agostini 	rte_free(dev->mpshared->dev_private);
10731306a73bSElena Agostini 
10741306a73bSElena Agostini 	return 0;
10751306a73bSElena Agostini }
10761306a73bSElena Agostini 
10771306a73bSElena Agostini static int
10781306a73bSElena Agostini cuda_wmb(struct rte_gpu *dev)
10791306a73bSElena Agostini {
10801306a73bSElena Agostini 	CUresult res;
10811306a73bSElena Agostini 	const char *err_string;
10821306a73bSElena Agostini 	CUcontext current_ctx;
10831306a73bSElena Agostini 	CUcontext input_ctx;
10841306a73bSElena Agostini 	struct cuda_info *private;
10851306a73bSElena Agostini 
108694220b39SElena Agostini 	if (dev == NULL) {
108794220b39SElena Agostini 		rte_errno = ENODEV;
108894220b39SElena Agostini 		return -rte_errno;
108994220b39SElena Agostini 	}
10901306a73bSElena Agostini 
10911306a73bSElena Agostini 	private = (struct cuda_info *)dev->mpshared->dev_private;
10921306a73bSElena Agostini 
10931306a73bSElena Agostini 	if (private->gdr_write_ordering != CU_GPU_DIRECT_RDMA_WRITES_ORDERING_NONE) {
10941306a73bSElena Agostini 		/*
10951306a73bSElena Agostini 		 * No need to explicitly force the write ordering because
10961306a73bSElena Agostini 		 * the device natively supports it
10971306a73bSElena Agostini 		 */
10981306a73bSElena Agostini 		return 0;
10991306a73bSElena Agostini 	}
11001306a73bSElena Agostini 
11011306a73bSElena Agostini 	if (private->gdr_flush_type != CU_FLUSH_GPU_DIRECT_RDMA_WRITES_OPTION_HOST) {
11021306a73bSElena Agostini 		/*
11031306a73bSElena Agostini 		 * Can't flush GDR writes with cuFlushGPUDirectRDMAWrites CUDA function.
11041306a73bSElena Agostini 		 * Application needs to use alternative methods.
11051306a73bSElena Agostini 		 */
11061306a73bSElena Agostini 		rte_cuda_log(WARNING, "Can't flush GDR writes with cuFlushGPUDirectRDMAWrites CUDA function."
11071306a73bSElena Agostini 				"Application needs to use alternative methods.");
110894220b39SElena Agostini 
110994220b39SElena Agostini 		rte_errno = ENOTSUP;
111094220b39SElena Agostini 		return -rte_errno;
11111306a73bSElena Agostini 	}
11121306a73bSElena Agostini 
11131306a73bSElena Agostini 	/* Store current ctx */
11141306a73bSElena Agostini 	res = pfn_cuCtxGetCurrent(&current_ctx);
11151306a73bSElena Agostini 	if (res != 0) {
11161306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
11171306a73bSElena Agostini 		rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s",
11181306a73bSElena Agostini 				err_string);
111994220b39SElena Agostini 		rte_errno = EPERM;
112094220b39SElena Agostini 		return -rte_errno;
11211306a73bSElena Agostini 	}
11221306a73bSElena Agostini 
11231306a73bSElena Agostini 	/* Set child ctx as current ctx */
11241306a73bSElena Agostini 	input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
11251306a73bSElena Agostini 	res = pfn_cuCtxSetCurrent(input_ctx);
11261306a73bSElena Agostini 	if (res != 0) {
11271306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
11281306a73bSElena Agostini 		rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s",
11291306a73bSElena Agostini 				err_string);
113094220b39SElena Agostini 		rte_errno = EPERM;
113194220b39SElena Agostini 		return -rte_errno;
11321306a73bSElena Agostini 	}
11331306a73bSElena Agostini 
11341306a73bSElena Agostini 	res = pfn_cuFlushGPUDirectRDMAWrites(CU_FLUSH_GPU_DIRECT_RDMA_WRITES_TARGET_CURRENT_CTX,
11351306a73bSElena Agostini 			CU_FLUSH_GPU_DIRECT_RDMA_WRITES_TO_ALL_DEVICES);
11361306a73bSElena Agostini 	if (res != 0) {
11371306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
11381306a73bSElena Agostini 		rte_cuda_log(ERR, "cuFlushGPUDirectRDMAWrites current failed with %s",
11391306a73bSElena Agostini 				err_string);
114094220b39SElena Agostini 		rte_errno = EPERM;
114194220b39SElena Agostini 		return -rte_errno;
11421306a73bSElena Agostini 	}
11431306a73bSElena Agostini 
11441306a73bSElena Agostini 	/* Restore original ctx as current ctx */
11451306a73bSElena Agostini 	res = pfn_cuCtxSetCurrent(current_ctx);
11461306a73bSElena Agostini 	if (res != 0) {
11471306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
11481306a73bSElena Agostini 		rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
11491306a73bSElena Agostini 				err_string);
115094220b39SElena Agostini 		rte_errno = EPERM;
115194220b39SElena Agostini 		return -rte_errno;
11521306a73bSElena Agostini 	}
11531306a73bSElena Agostini 
11541306a73bSElena Agostini 	return 0;
11551306a73bSElena Agostini }
11561306a73bSElena Agostini 
11571306a73bSElena Agostini static int
11581306a73bSElena Agostini cuda_gpu_probe(__rte_unused struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
11591306a73bSElena Agostini {
11601306a73bSElena Agostini 	struct rte_gpu *dev = NULL;
11611306a73bSElena Agostini 	CUresult res;
11621306a73bSElena Agostini 	CUdevice cu_dev_id;
11631306a73bSElena Agostini 	CUcontext pctx;
11641306a73bSElena Agostini 	char dev_name[RTE_DEV_NAME_MAX_LEN];
11651306a73bSElena Agostini 	const char *err_string;
11661306a73bSElena Agostini 	int processor_count = 0;
11671306a73bSElena Agostini 	struct cuda_info *private;
11681306a73bSElena Agostini 
11691306a73bSElena Agostini 	if (pci_dev == NULL) {
11701306a73bSElena Agostini 		rte_cuda_log(ERR, "NULL PCI device");
117194220b39SElena Agostini 		rte_errno = ENODEV;
117294220b39SElena Agostini 		return -rte_errno;
11731306a73bSElena Agostini 	}
11741306a73bSElena Agostini 
11751306a73bSElena Agostini 	rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
11761306a73bSElena Agostini 
11771306a73bSElena Agostini 	/* Allocate memory to be used privately by drivers */
11781306a73bSElena Agostini 	dev = rte_gpu_allocate(pci_dev->device.name);
117994220b39SElena Agostini 	if (dev == NULL) {
118094220b39SElena Agostini 		rte_errno = ENODEV;
118194220b39SElena Agostini 		return -rte_errno;
118294220b39SElena Agostini 	}
11831306a73bSElena Agostini 
11841306a73bSElena Agostini 	/* Initialize values only for the first CUDA driver call */
11851306a73bSElena Agostini 	if (dev->mpshared->info.dev_id == 0) {
11861306a73bSElena Agostini 		mem_alloc_list_head = NULL;
11871306a73bSElena Agostini 		mem_alloc_list_tail = NULL;
11881306a73bSElena Agostini 		mem_alloc_list_last_elem = 0;
11891306a73bSElena Agostini 
11901306a73bSElena Agostini 		/* Load libcuda.so library */
11911306a73bSElena Agostini 		if (cuda_loader()) {
11921306a73bSElena Agostini 			rte_cuda_log(ERR, "CUDA Driver library not found");
119394220b39SElena Agostini 			rte_errno = ENOTSUP;
119494220b39SElena Agostini 			return -rte_errno;
11951306a73bSElena Agostini 		}
11961306a73bSElena Agostini 
11971306a73bSElena Agostini 		/* Load initial CUDA functions */
11981306a73bSElena Agostini 		if (cuda_sym_func_loader()) {
11991306a73bSElena Agostini 			rte_cuda_log(ERR, "CUDA functions not found in library");
120094220b39SElena Agostini 			rte_errno = ENOTSUP;
120194220b39SElena Agostini 			return -rte_errno;
12021306a73bSElena Agostini 		}
12031306a73bSElena Agostini 
12041306a73bSElena Agostini 		/*
12051306a73bSElena Agostini 		 * Required to initialize the CUDA Driver.
12061306a73bSElena Agostini 		 * Multiple calls of cuInit() will return immediately
12071306a73bSElena Agostini 		 * without making any relevant change
12081306a73bSElena Agostini 		 */
12091306a73bSElena Agostini 		sym_cuInit(0);
12101306a73bSElena Agostini 
12111306a73bSElena Agostini 		res = sym_cuDriverGetVersion(&cuda_driver_version);
12121306a73bSElena Agostini 		if (res != 0) {
12131306a73bSElena Agostini 			rte_cuda_log(ERR, "cuDriverGetVersion failed with %d", res);
121494220b39SElena Agostini 			rte_errno = ENOTSUP;
121594220b39SElena Agostini 			return -rte_errno;
12161306a73bSElena Agostini 		}
12171306a73bSElena Agostini 
12181306a73bSElena Agostini 		if (cuda_driver_version < CUDA_DRIVER_MIN_VERSION) {
12191306a73bSElena Agostini 			rte_cuda_log(ERR, "CUDA Driver version found is %d. "
12201306a73bSElena Agostini 					"Minimum requirement is %d",
12211306a73bSElena Agostini 					cuda_driver_version,
12221306a73bSElena Agostini 					CUDA_DRIVER_MIN_VERSION);
122394220b39SElena Agostini 			rte_errno = ENOTSUP;
122494220b39SElena Agostini 			return -rte_errno;
12251306a73bSElena Agostini 		}
12261306a73bSElena Agostini 
12271306a73bSElena Agostini 		if (cuda_pfn_func_loader()) {
12281306a73bSElena Agostini 			rte_cuda_log(ERR, "CUDA PFN functions not found in library");
122994220b39SElena Agostini 			rte_errno = ENOTSUP;
123094220b39SElena Agostini 			return -rte_errno;
12311306a73bSElena Agostini 		}
123224c77594SElena Agostini 
123324c77594SElena Agostini 		gdrc_h = NULL;
12341306a73bSElena Agostini 	}
12351306a73bSElena Agostini 
12361306a73bSElena Agostini 	/* Fill HW specific part of device structure */
12371306a73bSElena Agostini 	dev->device = &pci_dev->device;
12381306a73bSElena Agostini 	dev->mpshared->info.numa_node = pci_dev->device.numa_node;
12391306a73bSElena Agostini 
12401306a73bSElena Agostini 	/* Get NVIDIA GPU Device descriptor */
12411306a73bSElena Agostini 	res = pfn_cuDeviceGetByPCIBusId(&cu_dev_id, dev->device->name);
12421306a73bSElena Agostini 	if (res != 0) {
12431306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
12441306a73bSElena Agostini 		rte_cuda_log(ERR, "cuDeviceGetByPCIBusId name %s failed with %d: %s",
12451306a73bSElena Agostini 				dev->device->name, res, err_string);
124694220b39SElena Agostini 		rte_errno = EPERM;
124794220b39SElena Agostini 		return -rte_errno;
12481306a73bSElena Agostini 	}
12491306a73bSElena Agostini 
12501306a73bSElena Agostini 	res = pfn_cuDevicePrimaryCtxRetain(&pctx, cu_dev_id);
12511306a73bSElena Agostini 	if (res != 0) {
12521306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
12531306a73bSElena Agostini 		rte_cuda_log(ERR, "cuDevicePrimaryCtxRetain name %s failed with %d: %s",
12541306a73bSElena Agostini 				dev->device->name, res, err_string);
125594220b39SElena Agostini 		rte_errno = EPERM;
125694220b39SElena Agostini 		return -rte_errno;
12571306a73bSElena Agostini 	}
12581306a73bSElena Agostini 
12591306a73bSElena Agostini 	res = pfn_cuCtxGetApiVersion(pctx, &cuda_api_version);
12601306a73bSElena Agostini 	if (res != 0) {
12611306a73bSElena Agostini 		rte_cuda_log(ERR, "cuCtxGetApiVersion failed with %d", res);
126294220b39SElena Agostini 		rte_errno = ENOTSUP;
126394220b39SElena Agostini 		return -rte_errno;
12641306a73bSElena Agostini 	}
12651306a73bSElena Agostini 
12661306a73bSElena Agostini 	if (cuda_api_version < CUDA_API_MIN_VERSION) {
12671306a73bSElena Agostini 		rte_cuda_log(ERR, "CUDA API version found is %d Minimum requirement is %d",
12681306a73bSElena Agostini 				cuda_api_version, CUDA_API_MIN_VERSION);
126994220b39SElena Agostini 		rte_errno = ENOTSUP;
127094220b39SElena Agostini 		return -rte_errno;
12711306a73bSElena Agostini 	}
12721306a73bSElena Agostini 
12731306a73bSElena Agostini 	dev->mpshared->info.context = (uint64_t)pctx;
12741306a73bSElena Agostini 
12751306a73bSElena Agostini 	/*
12761306a73bSElena Agostini 	 * GPU Device generic info
12771306a73bSElena Agostini 	 */
12781306a73bSElena Agostini 
12791306a73bSElena Agostini 	/* Processor count */
12801306a73bSElena Agostini 	res = pfn_cuDeviceGetAttribute(&(processor_count),
12811306a73bSElena Agostini 			CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT,
12821306a73bSElena Agostini 			cu_dev_id);
12831306a73bSElena Agostini 	if (res != 0) {
12841306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
12851306a73bSElena Agostini 		rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s",
12861306a73bSElena Agostini 				err_string);
128794220b39SElena Agostini 		rte_errno = EPERM;
128894220b39SElena Agostini 		return -rte_errno;
12891306a73bSElena Agostini 	}
12901306a73bSElena Agostini 	dev->mpshared->info.processor_count = (uint32_t)processor_count;
12911306a73bSElena Agostini 
12921306a73bSElena Agostini 	/* Total memory */
12931306a73bSElena Agostini 	res = pfn_cuDeviceTotalMem(&dev->mpshared->info.total_memory, cu_dev_id);
12941306a73bSElena Agostini 	if (res != 0) {
12951306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
12961306a73bSElena Agostini 		rte_cuda_log(ERR, "cuDeviceTotalMem failed with %s",
12971306a73bSElena Agostini 				err_string);
129894220b39SElena Agostini 		rte_errno = EPERM;
129994220b39SElena Agostini 		return -rte_errno;
13001306a73bSElena Agostini 	}
13011306a73bSElena Agostini 
13021fd3de64SElena Agostini 	dev->mpshared->info.page_size = (size_t)GPU_PAGE_SIZE;
13031fd3de64SElena Agostini 
13041306a73bSElena Agostini 	/*
13051306a73bSElena Agostini 	 * GPU Device private info
13061306a73bSElena Agostini 	 */
13071306a73bSElena Agostini 	dev->mpshared->dev_private = rte_zmalloc(NULL,
13081306a73bSElena Agostini 			sizeof(struct cuda_info),
13091306a73bSElena Agostini 			RTE_CACHE_LINE_SIZE);
13101306a73bSElena Agostini 	if (dev->mpshared->dev_private == NULL) {
13111306a73bSElena Agostini 		rte_cuda_log(ERR, "Failed to allocate memory for GPU process private");
131294220b39SElena Agostini 		rte_errno = EPERM;
131394220b39SElena Agostini 		return -rte_errno;
13141306a73bSElena Agostini 	}
13151306a73bSElena Agostini 
13161306a73bSElena Agostini 	private = (struct cuda_info *)dev->mpshared->dev_private;
13171306a73bSElena Agostini 	private->cu_dev = cu_dev_id;
13181306a73bSElena Agostini 	res = pfn_cuDeviceGetName(private->gpu_name,
13191306a73bSElena Agostini 			RTE_DEV_NAME_MAX_LEN,
13201306a73bSElena Agostini 			cu_dev_id);
13211306a73bSElena Agostini 	if (res != 0) {
13221306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
13231306a73bSElena Agostini 		rte_cuda_log(ERR, "cuDeviceGetName failed with %s",
13241306a73bSElena Agostini 				err_string);
132594220b39SElena Agostini 		rte_errno = EPERM;
132694220b39SElena Agostini 		return -rte_errno;
13271306a73bSElena Agostini 	}
13281306a73bSElena Agostini 
13291306a73bSElena Agostini 	res = pfn_cuDeviceGetAttribute(&(private->gdr_supported),
13301306a73bSElena Agostini 			CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_SUPPORTED,
13311306a73bSElena Agostini 			cu_dev_id);
13321306a73bSElena Agostini 	if (res != 0) {
13331306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
13341306a73bSElena Agostini 		rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s",
13351306a73bSElena Agostini 				err_string);
133694220b39SElena Agostini 		rte_errno = EPERM;
133794220b39SElena Agostini 		return -rte_errno;
13381306a73bSElena Agostini 	}
13391306a73bSElena Agostini 
13401306a73bSElena Agostini 	if (private->gdr_supported == 0)
13411306a73bSElena Agostini 		rte_cuda_log(WARNING, "GPU %s doesn't support GPUDirect RDMA",
13421306a73bSElena Agostini 				pci_dev->device.name);
13431306a73bSElena Agostini 
13441306a73bSElena Agostini 	res = pfn_cuDeviceGetAttribute(&(private->gdr_write_ordering),
13451306a73bSElena Agostini 			CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_WRITES_ORDERING,
13461306a73bSElena Agostini 			cu_dev_id);
13471306a73bSElena Agostini 	if (res != 0) {
13481306a73bSElena Agostini 		pfn_cuGetErrorString(res, &(err_string));
13491306a73bSElena Agostini 		rte_cuda_log(ERR,
13501306a73bSElena Agostini 				"cuDeviceGetAttribute failed with %s",
13511306a73bSElena Agostini 				err_string);
135294220b39SElena Agostini 		rte_errno = EPERM;
135394220b39SElena Agostini 		return -rte_errno;
13541306a73bSElena Agostini 	}
13551306a73bSElena Agostini 
13561306a73bSElena Agostini 	if (private->gdr_write_ordering == CU_GPU_DIRECT_RDMA_WRITES_ORDERING_NONE) {
13571306a73bSElena Agostini 		res = pfn_cuDeviceGetAttribute(&(private->gdr_flush_type),
13581306a73bSElena Agostini 				CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_FLUSH_WRITES_OPTIONS,
13591306a73bSElena Agostini 				cu_dev_id);
13601306a73bSElena Agostini 		if (res != 0) {
13611306a73bSElena Agostini 			pfn_cuGetErrorString(res, &(err_string));
13621306a73bSElena Agostini 			rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s",
13631306a73bSElena Agostini 					err_string);
136494220b39SElena Agostini 			rte_errno = EPERM;
136594220b39SElena Agostini 			return -rte_errno;
13661306a73bSElena Agostini 		}
13671306a73bSElena Agostini 
13681306a73bSElena Agostini 		if (private->gdr_flush_type != CU_FLUSH_GPU_DIRECT_RDMA_WRITES_OPTION_HOST)
13691306a73bSElena Agostini 			rte_cuda_log(ERR, "GPUDirect RDMA flush writes API is not supported");
13701306a73bSElena Agostini 	}
13711306a73bSElena Agostini 
13721306a73bSElena Agostini 	dev->ops.dev_info_get = cuda_dev_info_get;
13731306a73bSElena Agostini 	dev->ops.dev_close = cuda_dev_close;
13741306a73bSElena Agostini 	dev->ops.mem_alloc = cuda_mem_alloc;
13751306a73bSElena Agostini 	dev->ops.mem_free = cuda_mem_free;
13761306a73bSElena Agostini 	dev->ops.mem_register = cuda_mem_register;
13771306a73bSElena Agostini 	dev->ops.mem_unregister = cuda_mem_unregister;
137824c77594SElena Agostini 	dev->ops.mem_cpu_map = cuda_mem_cpu_map;
137924c77594SElena Agostini 	dev->ops.mem_cpu_unmap = cuda_mem_cpu_unmap;
13801306a73bSElena Agostini 	dev->ops.wmb = cuda_wmb;
13811306a73bSElena Agostini 
13821306a73bSElena Agostini 	rte_gpu_complete_new(dev);
13831306a73bSElena Agostini 
13841306a73bSElena Agostini 	rte_cuda_debug("dev id = %u name = %s",
13851306a73bSElena Agostini 			dev->mpshared->info.dev_id, private->gpu_name);
13861306a73bSElena Agostini 
13871306a73bSElena Agostini 	return 0;
13881306a73bSElena Agostini }
13891306a73bSElena Agostini 
13901306a73bSElena Agostini static int
13911306a73bSElena Agostini cuda_gpu_remove(struct rte_pci_device *pci_dev)
13921306a73bSElena Agostini {
13931306a73bSElena Agostini 	struct rte_gpu *dev;
13941306a73bSElena Agostini 	int ret;
13951306a73bSElena Agostini 	uint8_t gpu_id;
13961306a73bSElena Agostini 
139794220b39SElena Agostini 	if (pci_dev == NULL) {
139894220b39SElena Agostini 		rte_errno = ENODEV;
139994220b39SElena Agostini 		return -rte_errno;
140094220b39SElena Agostini 	}
14011306a73bSElena Agostini 
14021306a73bSElena Agostini 	dev = rte_gpu_get_by_name(pci_dev->device.name);
14031306a73bSElena Agostini 	if (dev == NULL) {
14041306a73bSElena Agostini 		rte_cuda_log(ERR, "Couldn't find HW dev \"%s\" to uninitialise it",
14051306a73bSElena Agostini 				pci_dev->device.name);
140694220b39SElena Agostini 		rte_errno = ENODEV;
140794220b39SElena Agostini 		return -rte_errno;
14081306a73bSElena Agostini 	}
14091306a73bSElena Agostini 	gpu_id = dev->mpshared->info.dev_id;
14101306a73bSElena Agostini 
14111306a73bSElena Agostini 	/* release dev from library */
14121306a73bSElena Agostini 	ret = rte_gpu_release(dev);
14131306a73bSElena Agostini 	if (ret)
14141306a73bSElena Agostini 		rte_cuda_log(ERR, "Device %i failed to uninit: %i", gpu_id, ret);
14151306a73bSElena Agostini 
14161306a73bSElena Agostini 	rte_cuda_debug("Destroyed dev = %u", gpu_id);
14171306a73bSElena Agostini 
14181306a73bSElena Agostini 	return 0;
14191306a73bSElena Agostini }
14201306a73bSElena Agostini 
14211306a73bSElena Agostini static struct rte_pci_driver rte_cuda_driver = {
14221306a73bSElena Agostini 	.id_table = pci_id_cuda_map,
14231306a73bSElena Agostini 	.drv_flags = RTE_PCI_DRV_WC_ACTIVATE,
14241306a73bSElena Agostini 	.probe = cuda_gpu_probe,
14251306a73bSElena Agostini 	.remove = cuda_gpu_remove,
14261306a73bSElena Agostini };
14271306a73bSElena Agostini 
14281306a73bSElena Agostini RTE_PMD_REGISTER_PCI(gpu_cuda, rte_cuda_driver);
14291306a73bSElena Agostini RTE_PMD_REGISTER_PCI_TABLE(gpu_cuda, pci_id_cuda_map);
14301306a73bSElena Agostini RTE_PMD_REGISTER_KMOD_DEP(gpu_cuda, "* nvidia & (nv_peer_mem | nvpeer_mem)");
1431