1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2018-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 #include "deprecated/rmapi_deprecated.h"
24 
25 #include "class/cl0080.h" // NV01_DEVICE_0
26 #include "class/cl2080.h" // NV20_SUBDEVICE_0
27 #include "ctrl/ctrl0000/ctrl0000client.h" // NV0000_CTRL_CMD_CLIENT_GET_CHILD_HANDLE
28 #include "ctrl/ctrl0080/ctrl0080gpu.h" // NV0080_CTRL_CMD_GPU_FIND_SUBDEVICE_HANDLE
29 #include "nvos.h"
30 
31 #include <stddef.h>
32 
33 NV_STATUS
RmDeprecatedGetHandleParent(DEPRECATED_CONTEXT * pContext,NvHandle hClient,NvHandle hObject,NvHandle * phParent)34 RmDeprecatedGetHandleParent
35 (
36     DEPRECATED_CONTEXT *pContext,
37     NvHandle            hClient,
38     NvHandle            hObject,
39     NvHandle           *phParent
40 )
41 {
42     NV0000_CTRL_CLIENT_GET_HANDLE_INFO_PARAMS parentParams = {0};
43     NV_STATUS                                 status;
44 
45     parentParams.hObject = hObject;
46     parentParams.index = NV0000_CTRL_CMD_CLIENT_GET_HANDLE_INFO_INDEX_PARENT;
47 
48     status = pContext->RmControl(pContext, hClient, hClient, NV0000_CTRL_CMD_CLIENT_GET_HANDLE_INFO,
49                                  &parentParams, sizeof(parentParams));
50 
51     *phParent = parentParams.data.hResult;
52 
53     return status;
54 }
55 
56 NV_STATUS
RmDeprecatedGetClassID(DEPRECATED_CONTEXT * pContext,NvHandle hClient,NvHandle hObject,NvU32 * pClassId)57 RmDeprecatedGetClassID
58 (
59     DEPRECATED_CONTEXT *pContext,
60     NvHandle            hClient,
61     NvHandle            hObject,
62     NvU32              *pClassId
63 )
64 {
65     NV0000_CTRL_CLIENT_GET_HANDLE_INFO_PARAMS classIdParams = {0};
66     NV_STATUS                                 status;
67 
68     classIdParams.hObject = hObject;
69     classIdParams.index = NV0000_CTRL_CMD_CLIENT_GET_HANDLE_INFO_INDEX_CLASSID;
70 
71     status = pContext->RmControl(pContext, hClient, hClient,
72                                  NV0000_CTRL_CMD_CLIENT_GET_HANDLE_INFO,
73                                  &classIdParams,
74                                  sizeof(classIdParams));
75 
76     *pClassId = NvU64_LO32(classIdParams.data.iResult);
77 
78     return status;
79 }
80 
81 NV_STATUS
RmDeprecatedFindOrCreateSubDeviceHandle(DEPRECATED_CONTEXT * pContext,NvHandle hClient,NvHandle hDeviceOrSubDevice,NvHandle * pHSubDevice,NvBool * pBMustFree)82 RmDeprecatedFindOrCreateSubDeviceHandle
83 (
84     DEPRECATED_CONTEXT *pContext,
85     NvHandle            hClient,
86     NvHandle            hDeviceOrSubDevice,
87     NvHandle           *pHSubDevice,
88     NvBool             *pBMustFree
89 )
90 {
91     NV0080_CTRL_GPU_FIND_SUBDEVICE_HANDLE_PARAM findParams = {0};
92     NV_STATUS                                   status;
93     NvU32                                       classId;
94 
95     //
96     // Step 1.) check if we already have a subdevice
97     //
98     status = RmDeprecatedGetClassID(pContext, hClient, hDeviceOrSubDevice, &classId);
99 
100     if (status != NV_OK)
101         return status;
102 
103     if (classId == NV20_SUBDEVICE_0)
104     {
105         *pBMustFree = NV_FALSE;
106         *pHSubDevice = hDeviceOrSubDevice;
107         return NV_OK;
108     }
109     else if (classId != NV01_DEVICE_0)
110     {
111         return NV_ERR_INVALID_ARGUMENT;
112     }
113 
114     //
115     // Step 2.) check if there is a subdevice allocated under this device
116     //
117     findParams.subDeviceInst = 0;
118 
119     status = pContext->RmControl(pContext, hClient, hDeviceOrSubDevice,
120                                  NV0080_CTRL_CMD_GPU_FIND_SUBDEVICE_HANDLE,
121                                  &findParams,
122                                  sizeof(findParams));
123 
124     if (status == NV_OK && findParams.hSubDevice)
125     {
126         *pBMustFree = NV_FALSE;
127         *pHSubDevice = findParams.hSubDevice;
128         return status;
129     }
130 
131     //
132     // Step 3.) if there is no device, we temporarily allocate a subdevice.
133     // Subdevice must be freed before we exit out to allow the client to reserve
134     // it if it chooses to do so later on.
135     //
136     *pBMustFree = NV_TRUE;
137 
138     *pHSubDevice = 0;
139 
140     status = pContext->RmAlloc(pContext, hClient, hDeviceOrSubDevice, pHSubDevice, NV20_SUBDEVICE_0, NULL, 0);
141 
142     return status;
143 }
144 
RmDeprecatedGetOrAllocObject(DEPRECATED_CONTEXT * pContext,NvHandle hClient,NvU32 classId,NvHandle * pHObject)145 NV_STATUS RmDeprecatedGetOrAllocObject
146 (
147     DEPRECATED_CONTEXT *pContext,
148     NvHandle hClient,
149     NvU32 classId,
150     NvHandle *pHObject
151 )
152 {
153     NV_STATUS status;
154 
155     NV0000_CTRL_CMD_CLIENT_GET_CHILD_HANDLE_PARAMS params = {0};
156     params.hParent = *pHObject;
157     params.classId = classId;
158     status = pContext->RmControl(pContext, hClient, hClient,
159                                  NV0000_CTRL_CMD_CLIENT_GET_CHILD_HANDLE,
160                                  &params, sizeof(params));
161     // Object already exists, just return it
162     if (status == NV_OK && params.hObject != 0)
163     {
164         *pHObject = params.hObject;
165     }
166     else
167     {
168         //
169         // Object does not exist yet, allocate.
170         // TODO: Fill alloc params for classes that need them
171         //
172         status = pContext->RmAlloc(pContext, hClient, *pHObject,
173                                    pHObject, classId, NULL, 0);
174     }
175     return status;
176 }
177 
178 NV_STATUS
RmDeprecatedConvertOs32ToOs02Flags(NvU32 attr,NvU32 attr2,NvU32 os32Flags,NvU32 * pOs02Flags)179 RmDeprecatedConvertOs32ToOs02Flags
180 (
181     NvU32 attr,
182     NvU32 attr2,
183     NvU32 os32Flags,
184     NvU32 *pOs02Flags
185 )
186 {
187     NvU32 os02Flags = 0;
188     NV_STATUS rmStatus = NV_OK;
189 
190     switch (DRF_VAL(OS32, _ATTR, _PHYSICALITY, attr))
191     {
192         case NVOS32_ATTR_PHYSICALITY_DEFAULT: // NVOS02 defaults to contiguous.
193         case NVOS32_ATTR_PHYSICALITY_CONTIGUOUS:
194         {
195             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _PHYSICALITY, _CONTIGUOUS, os02Flags);
196             break;
197         }
198         case NVOS32_ATTR_PHYSICALITY_NONCONTIGUOUS:
199         {
200             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _PHYSICALITY, _NONCONTIGUOUS, os02Flags);
201             break;
202         }
203         default:
204         {
205             rmStatus = NV_ERR_INVALID_FLAGS;
206             break;
207         }
208     }
209 
210     switch (DRF_VAL(OS32, _ATTR, _LOCATION, attr))
211     {
212         case NVOS32_ATTR_LOCATION_PCI:
213         case NVOS32_ATTR_LOCATION_ANY: // NVOS02 defaults to PCI
214         {
215             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _LOCATION, _PCI, os02Flags);
216             break;
217         }
218         case NVOS32_ATTR_LOCATION_AGP:
219         {
220             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _LOCATION, _AGP, os02Flags);
221             break;
222         }
223         case NVOS32_ATTR_LOCATION_VIDMEM:
224         {
225             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _LOCATION, _VIDMEM, os02Flags);
226             break;
227         }
228         default:
229         {
230             rmStatus = NV_ERR_INVALID_FLAGS;
231             break;
232         }
233     }
234 
235     switch (DRF_VAL(OS32, _ATTR, _COHERENCY, attr))
236     {
237         case NVOS32_ATTR_COHERENCY_UNCACHED:
238         {
239             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _COHERENCY, _UNCACHED, os02Flags);
240             break;
241         }
242         case NVOS32_ATTR_COHERENCY_CACHED:
243         {
244             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _COHERENCY, _CACHED, os02Flags);
245             break;
246         }
247         case NVOS32_ATTR_COHERENCY_WRITE_COMBINE:
248         {
249             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _COHERENCY, _WRITE_COMBINE, os02Flags);
250             break;
251         }
252         case NVOS32_ATTR_COHERENCY_WRITE_THROUGH:
253         {
254             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _COHERENCY, _WRITE_THROUGH, os02Flags);
255             break;
256         }
257         case NVOS32_ATTR_COHERENCY_WRITE_PROTECT:
258         {
259             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _COHERENCY, _WRITE_PROTECT, os02Flags);
260             break;
261         }
262         case NVOS32_ATTR_COHERENCY_WRITE_BACK:
263         {
264             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _COHERENCY, _WRITE_BACK, os02Flags);
265             break;
266         }
267         default:
268         {
269             rmStatus = NV_ERR_INVALID_FLAGS;
270             break;
271         }
272     }
273 
274     switch (DRF_VAL(OS32, _ATTR2, _GPU_CACHEABLE, attr2))
275     {
276         case NVOS32_ATTR2_GPU_CACHEABLE_YES:
277         {
278             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _GPU_CACHEABLE, _YES, os02Flags);
279             break;
280         }
281         case NVOS32_ATTR2_GPU_CACHEABLE_DEFAULT: // NVOS02 defaults to non-cacheable
282         case NVOS32_ATTR2_GPU_CACHEABLE_NO:
283         {
284             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _GPU_CACHEABLE, _NO, os02Flags);
285             break;
286         }
287         default:
288         {
289             rmStatus = NV_ERR_INVALID_FLAGS;
290             break;
291         }
292     }
293 
294     switch (DRF_VAL(OS32, _ATTR2, _REGISTER_MEMDESC_TO_PHYS_RM, attr2))
295     {
296         case NVOS32_ATTR2_REGISTER_MEMDESC_TO_PHYS_RM_TRUE:
297         {
298             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _REGISTER_MEMDESC_TO_PHYS_RM, _TRUE, os02Flags);
299             break;
300         }
301         case NVOS32_ATTR2_REGISTER_MEMDESC_TO_PHYS_RM_FALSE:
302         {
303             os02Flags = FLD_SET_DRF(OS02, _FLAGS, _REGISTER_MEMDESC_TO_PHYS_RM, _FALSE, os02Flags);
304             break;
305         }
306         default:
307         {
308             rmStatus = NV_ERR_INVALID_FLAGS;
309             break;
310         }
311     }
312 
313     // VidHeapControl never creates a mapping
314     os02Flags = FLD_SET_DRF(OS02, _FLAGS, _MAPPING, _NO_MAP, os02Flags);
315     if (os32Flags & NVOS32_ALLOC_FLAGS_KERNEL_MAPPING_MAP)
316         os02Flags = FLD_SET_DRF(OS02, _FLAGS, _KERNEL_MAPPING, _MAP, os02Flags);
317     else
318         os02Flags = FLD_SET_DRF(OS02, _FLAGS, _KERNEL_MAPPING, _NO_MAP, os02Flags);
319 
320     if (FLD_TEST_DRF(OS32, _ATTR2, _PROTECTION_USER, _READ_ONLY, attr2))
321         os02Flags = FLD_SET_DRF(OS02, _FLAGS, _ALLOC_USER_READ_ONLY, _YES, os02Flags);
322 
323     if (FLD_TEST_DRF(OS32, _ATTR2, _PROTECTION_DEVICE, _READ_ONLY, attr2))
324         os02Flags = FLD_SET_DRF(OS02, _FLAGS, _ALLOC_DEVICE_READ_ONLY, _YES, os02Flags);
325 
326     if (FLD_TEST_DRF(OS32, _ATTR2, _NISO_DISPLAY, _YES, attr2))
327         os02Flags = FLD_SET_DRF(OS02, _FLAGS, _ALLOC_NISO_DISPLAY, _YES, os02Flags);
328     else
329         os02Flags = FLD_SET_DRF(OS02, _FLAGS, _ALLOC_NISO_DISPLAY, _NO, os02Flags);
330 
331     if (rmStatus == NV_OK)
332     {
333         *pOs02Flags = os02Flags;
334     }
335 
336     return rmStatus;
337 }
338 
339 NV_STATUS
RmDeprecatedConvertOs02ToOs32Flags(NvU32 os02Flags,NvU32 * pAttr,NvU32 * pAttr2,NvU32 * pOs32Flags)340 RmDeprecatedConvertOs02ToOs32Flags
341 (
342     NvU32 os02Flags,
343     NvU32 *pAttr,
344     NvU32 *pAttr2,
345     NvU32 *pOs32Flags
346 )
347 {
348     NvU32 os32Flags = 0;
349     NvU32 attr = 0, attr2 = 0;
350     NV_STATUS rmStatus = NV_OK;
351 
352     attr = FLD_SET_DRF(OS32, _ATTR, _PAGE_SIZE, _DEFAULT, attr);
353 
354     if (FLD_TEST_DRF(OS02, _FLAGS, _PHYSICALITY, _CONTIGUOUS, os02Flags))
355         attr = FLD_SET_DRF(OS32, _ATTR, _PHYSICALITY, _CONTIGUOUS, attr);
356     else
357         attr = FLD_SET_DRF(OS32, _ATTR, _PHYSICALITY, _NONCONTIGUOUS, attr);
358 
359     switch (DRF_VAL(OS02, _FLAGS, _LOCATION, os02Flags))
360     {
361         case NVOS02_FLAGS_LOCATION_PCI:
362         {
363             attr = FLD_SET_DRF(OS32, _ATTR, _LOCATION, _PCI, attr);
364             break;
365         }
366         case NVOS02_FLAGS_LOCATION_VIDMEM:
367         {
368             attr = FLD_SET_DRF(OS32, _ATTR, _LOCATION, _VIDMEM, attr);
369             break;
370         }
371         default:
372         {
373             rmStatus = NV_ERR_INVALID_FLAGS;
374             break;
375         }
376     }
377 
378     switch (DRF_VAL(OS02, _FLAGS, _COHERENCY, os02Flags))
379     {
380         case NVOS02_FLAGS_COHERENCY_UNCACHED:
381         {
382             attr = FLD_SET_DRF(OS32, _ATTR, _COHERENCY, _UNCACHED, attr);
383             break;
384         }
385         case NVOS02_FLAGS_COHERENCY_CACHED:
386         {
387             attr = FLD_SET_DRF(OS32, _ATTR, _COHERENCY, _CACHED, attr);
388             break;
389         }
390         case NVOS02_FLAGS_COHERENCY_WRITE_COMBINE:
391         {
392             attr = FLD_SET_DRF(OS32, _ATTR, _COHERENCY, _WRITE_COMBINE, attr);
393             break;
394         }
395         case NVOS02_FLAGS_COHERENCY_WRITE_THROUGH:
396         {
397             attr = FLD_SET_DRF(OS32, _ATTR, _COHERENCY, _WRITE_THROUGH, attr);
398             break;
399         }
400         case NVOS02_FLAGS_COHERENCY_WRITE_PROTECT:
401         {
402             attr = FLD_SET_DRF(OS32, _ATTR, _COHERENCY, _WRITE_PROTECT, attr);
403             break;
404         }
405         case NVOS02_FLAGS_COHERENCY_WRITE_BACK:
406         {
407             attr = FLD_SET_DRF(OS32, _ATTR, _COHERENCY, _WRITE_BACK, attr);
408             break;
409         }
410         default:
411         {
412             rmStatus = NV_ERR_INVALID_FLAGS;
413             break;
414         }
415     }
416 
417     if (FLD_TEST_DRF(OS02, _FLAGS, _GPU_CACHEABLE, _YES, os02Flags))
418         attr2 |= DRF_DEF(OS32, _ATTR2, _GPU_CACHEABLE, _YES);
419     else
420         attr2 |= DRF_DEF(OS32, _ATTR2, _GPU_CACHEABLE, _NO);
421 
422     if (FLD_TEST_DRF(OS02, _FLAGS, _KERNEL_MAPPING, _MAP, os02Flags))
423         os32Flags |= NVOS32_ALLOC_FLAGS_KERNEL_MAPPING_MAP;
424 
425     if (FLD_TEST_DRF(OS02, _FLAGS, _ALLOC_NISO_DISPLAY, _YES, os02Flags))
426         attr2 |= DRF_DEF(OS32, _ATTR2, _NISO_DISPLAY, _YES);
427     else
428         attr2 |= DRF_DEF(OS32, _ATTR2, _NISO_DISPLAY, _NO);
429 
430     if (FLD_TEST_DRF(OS02, _FLAGS, _ALLOC_USER_READ_ONLY, _YES, os02Flags))
431         attr2 |= DRF_DEF(OS32, _ATTR2, _PROTECTION_USER, _READ_ONLY);
432 
433     if (FLD_TEST_DRF(OS02, _FLAGS, _ALLOC_DEVICE_READ_ONLY, _YES, os02Flags))
434         attr2 |= DRF_DEF(OS32, _ATTR2, _PROTECTION_DEVICE, _READ_ONLY);
435 
436     if (FLD_TEST_DRF(OS02, _FLAGS, _REGISTER_MEMDESC_TO_PHYS_RM, _TRUE, os02Flags))
437         attr2 |= DRF_DEF(OS32, _ATTR2, _REGISTER_MEMDESC_TO_PHYS_RM, _TRUE);
438     else
439         attr2 |= DRF_DEF(OS32, _ATTR2, _REGISTER_MEMDESC_TO_PHYS_RM, _FALSE);
440 
441     if (rmStatus == NV_OK)
442     {
443         *pOs32Flags = os32Flags;
444         *pAttr = attr;
445         *pAttr2 = attr2;
446     }
447 
448     return rmStatus;
449 }
450