1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2018-2019 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 
24 
25 #include "nvport/nvport.h"
26 #include "deprecated/rmapi_deprecated.h"
27 
28 #include "class/cl0070.h"  // NV01_MEMORY_VIRTUAL/NV01_MEMORY_SYSTEM_DYNAMIC
29 
30 #include "ctrl/ctrl0002.h" // NV01_CONTEXT_DMA_FROM_MEMORY
31 #include "ctrl/ctrl2080/ctrl2080i2c.h" // NV2080_CTRL_I2C_ACCESS_PARAMS
32 #include "ctrl/ctrl0000/ctrl0000gpu.h" // NV0000_CTRL_GPU_IDLE_CHANNELS_PARAMS
33 #include "ctrl/ctrl402c.h" // NV40_I2C
34 
35 void
RmDeprecatedAllocObject(DEPRECATED_CONTEXT * pContext,NVOS05_PARAMETERS * pArgs)36 RmDeprecatedAllocObject
37 (
38     DEPRECATED_CONTEXT *pContext,
39     NVOS05_PARAMETERS *pArgs
40 )
41 {
42     pArgs->status = pContext->RmAlloc(pContext, pArgs->hRoot, pArgs->hObjectParent,
43                                       &pArgs->hObjectNew, pArgs->hClass, NULL, 0);
44 }
45 
46 void
RmDeprecatedAddVblankCallback(DEPRECATED_CONTEXT * pContext,NVOS61_PARAMETERS * pArgs)47 RmDeprecatedAddVblankCallback
48 (
49     DEPRECATED_CONTEXT *pContext,
50     NVOS61_PARAMETERS *pArgs
51 )
52 {
53     NV_STATUS status;
54 
55     if (pArgs->bAdd)
56     {
57         NV_VBLANK_CALLBACK_ALLOCATION_PARAMETERS vblankArgs = {0};
58 
59         vblankArgs.pProc = pArgs->pProc;
60         vblankArgs.LogicalHead = pArgs->LogicalHead;
61         vblankArgs.pParm1 = pArgs->pParm1;
62         vblankArgs.pParm2 = pArgs->pParm2;
63 
64         status = pContext->RmAlloc(pContext, pArgs->hClient, pArgs->hDevice,
65                                    &pArgs->hVblank, NV9010_VBLANK_CALLBACK, &vblankArgs, sizeof(vblankArgs));
66     }
67     else
68     {
69         status = pContext->RmFree(pContext, pArgs->hClient, pArgs->hVblank);
70     }
71 
72     pArgs->status = status;
73 }
74 
75 void
RmDeprecatedAllocContextDma(DEPRECATED_CONTEXT * pContext,NVOS39_PARAMETERS * pArgs)76 RmDeprecatedAllocContextDma
77 (
78     DEPRECATED_CONTEXT *pContext,
79     NVOS39_PARAMETERS  *pArgs
80 )
81 {
82     NV_CONTEXT_DMA_ALLOCATION_PARAMS allocParams = {0};
83     NV_STATUS                        status;
84     NvHandle                         hCtxDmaParent;
85     NvHandle                         hClient = pArgs->hObjectParent;
86     NvU32                            class;
87 
88     //
89     // hMemory parent is used as the parent for the context dma. The legacy
90     // RmAllocContextDma2 unfortunately never took hParent as an argument.
91     //
92     status = RmDeprecatedGetHandleParent(pContext, hClient, pArgs->hMemory, &hCtxDmaParent);
93     if (status != NV_OK)
94         goto done;
95 
96     //
97     // A virtual ContextDma of a NV01_MEMORY_SYSTEM_DYNAMIC object is now implemented
98     // directly in the DynamicMemory object.  We support allocation on the ContextDma
99     // path for API compatibility.
100     //
101     status = RmDeprecatedGetClassID(pContext, hClient, pArgs->hMemory, &class);
102     if ((status == NV_OK) && (class == NV01_MEMORY_SYSTEM_DYNAMIC))
103     {
104         NV_MEMORY_VIRTUAL_ALLOCATION_PARAMS allocVirtualParams = { 0 };
105 
106         // Apply limit
107         allocVirtualParams.offset = pArgs->offset;
108         allocVirtualParams.limit = pArgs->limit;
109 
110         // Use default address space for this context
111         allocVirtualParams.hVASpace = 0;
112 
113         status = pContext->RmAlloc(pContext, hClient, hCtxDmaParent,
114                                    &pArgs->hObjectNew,
115                                    NV01_MEMORY_VIRTUAL,
116                                    &allocVirtualParams,
117                                    sizeof(allocVirtualParams));
118         goto done;
119     }
120 
121     allocParams.hSubDevice = pArgs->hSubDevice;
122     allocParams.flags = pArgs->flags;
123     allocParams.hMemory = pArgs->hMemory;
124     allocParams.offset = pArgs->offset;
125     allocParams.limit = pArgs->limit;
126 
127     status = pContext->RmAlloc(pContext, hClient, hCtxDmaParent,
128                                &pArgs->hObjectNew, pArgs->hClass, &allocParams, sizeof(allocParams));
129 
130 done:
131     pArgs->status = status;
132 }
133 
134 void
RmDeprecatedBindContextDma(DEPRECATED_CONTEXT * pContext,NVOS49_PARAMETERS * pArgs)135 RmDeprecatedBindContextDma
136 (
137     DEPRECATED_CONTEXT *pContext,
138     NVOS49_PARAMETERS  *pArgs
139 )
140 {
141     NV0002_CTRL_BIND_CONTEXTDMA_PARAMS bindParams = {0};
142     NV_STATUS                          status;
143     NvU32                              class;
144 
145     // Allow ContextDma promoted to DynamicMemory to be silently bound for compatibility
146     status = RmDeprecatedGetClassID(pContext, pArgs->hClient, pArgs->hCtxDma, &class);
147     if ((status == NV_OK) && (class == NV01_MEMORY_SYSTEM_DYNAMIC))
148     {
149         pArgs->status = status;
150         return;
151     }
152 
153     bindParams.hChannel = pArgs->hChannel;
154 
155     status = pContext->RmControl(pContext, pArgs->hClient, pArgs->hCtxDma, NV0002_CTRL_CMD_BIND_CONTEXTDMA,
156                                  &bindParams, sizeof(bindParams));
157 
158     pArgs->status = status;
159 }
160 
161 void
RmDeprecatedI2CAccess(DEPRECATED_CONTEXT * pContext,NVOS_I2C_ACCESS_PARAMS * pArgs)162 RmDeprecatedI2CAccess
163 (
164     DEPRECATED_CONTEXT     *pContext,
165     NVOS_I2C_ACCESS_PARAMS *pArgs
166 )
167 {
168     NV_STATUS                      status = NV_OK;
169     NV_STATUS                      statusTmp = NV_OK;
170     NV2080_CTRL_I2C_ACCESS_PARAMS *pControlParams = 0;
171     void                          *pEmbeddedParams = 0;
172     NvP64                          orginalEmbeddedPtr = NvP64_NULL;
173     NvHandle                       hSubDevice;
174     NvBool                         bMustFreeSubDevice = NV_FALSE;
175 
176     // Param can be either a hSubdevice or hDevice, control is on subdevice
177     status = RmDeprecatedFindOrCreateSubDeviceHandle(pContext, pArgs->hClient, pArgs->hDevice,
178                                                      &hSubDevice, &bMustFreeSubDevice);
179     if (status != NV_OK)
180         goto done;
181 
182     //
183     // Need to copy fields into local address space (if kernel) before we can
184     // call RmControl. DEPRECATED_CONTEXT::RmControl expects all params to be in
185     // local address space.
186     //
187     status = pContext->CopyUser(pContext, RMAPI_DEPRECATED_COPYIN, RMAPI_DEPRECATED_BUFFER_ALLOCATE,
188                                 pArgs->paramStructPtr, sizeof(NV2080_CTRL_I2C_ACCESS_PARAMS), (void**)&pControlParams);
189     if (status != NV_OK)
190         goto done;
191 
192     if (pControlParams->dataBuffSize)
193     {
194         if (pControlParams->dataBuffSize <= NV402C_CTRL_I2C_MESSAGE_LENGTH_MAX)
195         {
196             status = pContext->CopyUser(pContext, RMAPI_DEPRECATED_COPYIN, RMAPI_DEPRECATED_BUFFER_ALLOCATE,
197                                         pControlParams->data, pControlParams->dataBuffSize, &pEmbeddedParams);
198             if (status != NV_OK)
199                 goto done;
200 
201             orginalEmbeddedPtr = pControlParams->data;
202             pControlParams->data = NV_PTR_TO_NvP64(pEmbeddedParams);
203         }
204         else
205         {
206             // Invalid I2C access datasize, ignore the databuffer
207             // RS-TODO This should return an error, but ignore for now until KMD initializes their params
208             pControlParams->dataBuffSize = 0;
209             pControlParams->data = NvP64_NULL;
210         }
211     }
212 
213     status = pContext->RmControl(pContext, pArgs->hClient, hSubDevice, NV2080_CTRL_CMD_I2C_ACCESS,
214                                  pControlParams, sizeof(NV2080_CTRL_I2C_ACCESS_PARAMS));
215 
216 done:
217     if (pEmbeddedParams)
218     {
219         // Restore original value before copy back
220         pControlParams->data = orginalEmbeddedPtr;
221 
222         statusTmp = pContext->CopyUser(pContext, RMAPI_DEPRECATED_COPYOUT, RMAPI_DEPRECATED_BUFFER_ALLOCATE,
223                                        pControlParams->data, pControlParams->dataBuffSize, &pEmbeddedParams);
224         if (status == NV_OK)
225             status = statusTmp;
226     }
227 
228     if (pControlParams)
229     {
230         statusTmp = pContext->CopyUser(pContext, RMAPI_DEPRECATED_COPYOUT, RMAPI_DEPRECATED_BUFFER_ALLOCATE,
231                                        pArgs->paramStructPtr, sizeof(NV2080_CTRL_I2C_ACCESS_PARAMS), (void **)&pControlParams);
232         if (status == NV_OK)
233             status = statusTmp;
234     }
235 
236     if (bMustFreeSubDevice)
237     {
238         pContext->RmFree(pContext, pArgs->hClient, hSubDevice);
239     }
240 
241     pArgs->status = status;
242 }
243 
244 void
RmDeprecatedIdleChannels(DEPRECATED_CONTEXT * pContext,NVOS30_PARAMETERS * pArgs)245 RmDeprecatedIdleChannels
246 (
247     DEPRECATED_CONTEXT *pContext,
248     NVOS30_PARAMETERS  *pArgs
249 )
250 {
251     NV0000_CTRL_GPU_IDLE_CHANNELS_PARAMS params     = {0};
252     NV_STATUS                            status;
253     NvU32                                handleBufferSize;
254     void                                *phClients  = 0;
255     void                                *phDevices  = 0;
256     void                                *phChannels = 0;
257 
258     params.hDevice     = pArgs->hDevice;
259     params.hChannel    = pArgs->hChannel;
260     params.numChannels = pArgs->numChannels;
261     params.flags       = pArgs->flags;
262     params.timeout     = pArgs->timeout;
263 
264     if (!portSafeMulU32(pArgs->numChannels, sizeof(NvU32), &handleBufferSize))
265     {
266         status = NV_ERR_INVALID_ARGUMENT;
267         goto done;
268     }
269 
270     // XXX this should have a max - but copying old behavior for now
271     if (DRF_VAL(OS30, _FLAGS, _CHANNEL, pArgs->flags) == NVOS30_FLAGS_CHANNEL_LIST &&
272         params.numChannels)
273     {
274         // Copy-in phClients
275         status = pContext->CopyUser(pContext, RMAPI_DEPRECATED_COPYIN, RMAPI_DEPRECATED_BUFFER_ALLOCATE,
276                                     pArgs->phClients, handleBufferSize, &phClients);
277         if (status != NV_OK)
278             goto done;
279 
280         params.phClients = NV_PTR_TO_NvP64(phClients);
281 
282         // Copy-in phDevices
283         status = pContext->CopyUser(pContext, RMAPI_DEPRECATED_COPYIN, RMAPI_DEPRECATED_BUFFER_ALLOCATE,
284                                     pArgs->phDevices, handleBufferSize, &phDevices);
285         if (status != NV_OK)
286             goto done;
287 
288         params.phDevices = NV_PTR_TO_NvP64(phDevices);
289 
290         // Copy-in phChannels
291         status = pContext->CopyUser(pContext, RMAPI_DEPRECATED_COPYIN, RMAPI_DEPRECATED_BUFFER_ALLOCATE,
292                                     pArgs->phChannels, handleBufferSize, &phChannels);
293         if (status != NV_OK)
294             goto done;
295 
296         params.phChannels = NV_PTR_TO_NvP64(phChannels);
297     }
298 
299     status = pContext->RmControl(pContext, pArgs->hClient, pArgs->hClient,
300                                  NV0000_CTRL_CMD_IDLE_CHANNELS,
301                                  &params, sizeof(params));
302 
303 done:
304 
305     if (phClients)
306     {
307         pContext->CopyUser(pContext, RMAPI_DEPRECATED_COPYRELEASE, RMAPI_DEPRECATED_BUFFER_ALLOCATE,
308                            pArgs->phClients, handleBufferSize, &phClients);
309     }
310 
311     if (phDevices)
312     {
313         pContext->CopyUser(pContext, RMAPI_DEPRECATED_COPYRELEASE, RMAPI_DEPRECATED_BUFFER_ALLOCATE,
314                            pArgs->phDevices, handleBufferSize, &phDevices);
315     }
316 
317     if (phChannels)
318     {
319         pContext->CopyUser(pContext, RMAPI_DEPRECATED_COPYRELEASE, RMAPI_DEPRECATED_BUFFER_ALLOCATE,
320                            pArgs->phChannels, handleBufferSize, &phChannels);
321     }
322     pArgs->status = status;
323 }
324