1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2013-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 
24 #include "gpu/gpu.h"
25 #include "gpu/eng_state.h"
26 #include "core/hal.h"
27 #include "core/locks.h"
28 
29 #include "gpu/bus/kern_bus.h"
30 
31 // Function pointer wrapper
32 #define engstateStatePreInitUnlocked_Fnptr(pEngstate)      pEngstate->__engstateStatePreInitUnlocked__
33 #define engstateStateInitUnlocked_Fnptr(pEngstate)         pEngstate->__engstateStateInitUnlocked__
34 
35 NV_STATUS
engstateConstructBase_IMPL(OBJENGSTATE * pEngstate,OBJGPU * pGpu,ENGDESCRIPTOR engDesc)36 engstateConstructBase_IMPL
37 (
38     OBJENGSTATE        *pEngstate,
39     OBJGPU             *pGpu,
40     ENGDESCRIPTOR       engDesc
41 )
42 {
43     pEngstate->pGpu         = pGpu;
44     pEngstate->engDesc      = engDesc;
45     pEngstate->currentState = ENGSTATE_STATE_UNDEFINED;
46 
47     if (pEngstate->getProperty(pEngstate, PDB_PROP_ENGSTATE_IS_MISSING))
48         return NV_ERR_NOT_SUPPORTED;
49 
50 #if NV_PRINTF_STRINGS_ALLOWED
51     nvDbgSnprintf(pEngstate->name, sizeof(pEngstate->name), "%s:%d",
52         objGetClassName(pEngstate), ENGDESC_FIELD(pEngstate->engDesc, _INST));
53 #endif
54 
55     return NV_OK;
56 }
57 
58 void
engstateLogStateTransitionPre_IMPL(OBJENGSTATE * pEngstate,ENGSTATE_STATE targetState,ENGSTATE_TRANSITION_DATA * pData)59 engstateLogStateTransitionPre_IMPL
60 (
61     OBJENGSTATE   *pEngstate,
62     ENGSTATE_STATE targetState,
63     ENGSTATE_TRANSITION_DATA *pData
64 )
65 {
66     ENGSTATE_STATS *stats = &pEngstate->stats[targetState];
67     NV_ASSERT_OR_RETURN_VOID(targetState < ENGSTATE_STATE_COUNT);
68 
69     // First call, init
70     portMemSet(stats, 0, sizeof(ENGSTATE_STATS));
71     portMemSet(pData, 0, sizeof(ENGSTATE_TRANSITION_DATA));
72     osGetPerformanceCounter(&pData->transitionStartTimeNs);
73 
74 #if PORT_IS_FUNC_SUPPORTED(portMemExTrackingGetActiveStats)
75     {
76         PORT_MEM_TRACK_ALLOCATOR_STATS memstats = {0};
77         portMemExTrackingGetActiveStats(NULL, &memstats);
78 
79         pData->memoryAllocCount = (NvS64) memstats.numAllocations;
80         pData->memoryAllocSize  = (NvS64) memstats.usefulSize;
81     }
82 #endif
83 }
84 
85 void
engstateLogStateTransitionPost_IMPL(OBJENGSTATE * pEngstate,ENGSTATE_STATE targetState,ENGSTATE_TRANSITION_DATA * pData)86 engstateLogStateTransitionPost_IMPL
87 (
88     OBJENGSTATE   *pEngstate,
89     ENGSTATE_STATE targetState,
90     ENGSTATE_TRANSITION_DATA *pData
91 )
92 {
93     ENGSTATE_STATS *stats = &pEngstate->stats[targetState];
94     NvU64 endTimeNs;
95 
96     NV_ASSERT_OR_RETURN_VOID(targetState < ENGSTATE_STATE_COUNT);
97 
98     osGetPerformanceCounter(&endTimeNs);
99     stats->transitionTimeUs = (endTimeNs - pData->transitionStartTimeNs) / 1000;
100 
101 #if NV_PRINTF_STRINGS_ALLOWED
102     const char *stateStrings[ENGSTATE_STATE_COUNT] =
103     {
104         "Undefined",
105         "Construct",
106         "Pre-Init",
107         "Init",
108         "Pre-Load",
109         "Load",
110         "Post-Load",
111         "Pre-Unload",
112         "Unload",
113         "Post-Unload",
114         "Destroy"
115     };
116     ct_assert(ENGSTATE_STATE_COUNT == 11);
117 
118     NV_PRINTF(LEVEL_INFO,
119         "Engine %s state change: %s -> %s, took %uus\n",
120         engstateGetName(pEngstate),
121         stateStrings[pEngstate->currentState], stateStrings[targetState],
122         stats->transitionTimeUs);
123 #else
124     NV_PRINTF(LEVEL_INFO,
125         "Engine 0x%06x:%d state change: %d -> %d, took %uus\n",
126         objGetClassId(pEngstate), ENGDESC_FIELD(pEngstate->engDesc, _INST),
127         pEngstate->currentState, targetState,
128         stats->transitionTimeUs);
129 #endif
130 
131 #if PORT_IS_FUNC_SUPPORTED(portMemExTrackingGetActiveStats)
132     {
133         PORT_MEM_TRACK_ALLOCATOR_STATS memstats = {0};
134         portMemExTrackingGetActiveStats(NULL, &memstats);
135 
136         stats->memoryAllocCount = (NvS32)((NvS64)memstats.numAllocations - pData->memoryAllocCount);
137         stats->memoryAllocSize  = (NvS32)((NvS64)memstats.usefulSize     - pData->memoryAllocSize);
138 
139         NV_PRINTF(LEVEL_INFO, "    Memory usage change: %d allocations, %d bytes\n",
140             stats->memoryAllocCount, stats->memoryAllocSize);
141     }
142 #endif
143 
144     pEngstate->currentState = targetState;
145 }
146 
147 const char *
engstateGetName_IMPL(OBJENGSTATE * pEngstate)148 engstateGetName_IMPL
149 (
150     OBJENGSTATE *pEngstate
151 )
152 {
153 #if NV_PRINTF_STRINGS_ALLOWED
154     return pEngstate->name;
155 #else
156     return "";
157 #endif
158 }
159 
160 void
engstateLogStateStatus_IMPL(OBJENGSTATE * pEngstate,ENGSTATE_STATE targetState,NV_STATUS targetStatus)161 engstateLogStateStatus_IMPL
162 (
163     OBJENGSTATE   *pEngstate,
164     ENGSTATE_STATE targetState,
165     NV_STATUS      targetStatus
166 )
167 {
168     ENGSTATE_STATUS *status = &pEngstate->status[targetState];
169     NV_ASSERT_OR_RETURN_VOID(targetState < ENGSTATE_STATE_COUNT);
170 
171     status->engStatus = targetStatus;
172 
173 #if NV_PRINTF_STRINGS_ALLOWED
174     portStringCopy(status->name, sizeof(status->name), engstateGetName(pEngstate), portStringLength(engstateGetName(pEngstate)) + 1);
175 #endif
176 }
177 
178 /*!
179  * @brief generic constructor
180  */
181 NV_STATUS
engstateConstructEngine_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate,ENGDESCRIPTOR engDesc)182 engstateConstructEngine_IMPL
183 (
184     OBJGPU       *pGpu,
185     OBJENGSTATE  *pEngstate,
186     ENGDESCRIPTOR engDesc
187 )
188 {
189     return NV_OK;
190 }
191 
192 /*!
193  * @brief destructor
194  */
195 void
engstateDestruct_IMPL(OBJENGSTATE * pEngstate)196 engstateDestruct_IMPL
197 (
198     OBJENGSTATE *pEngstate
199 )
200 {
201 }
202 
203 /*!
204  * @brief init missing engine
205  */
206 void
engstateInitMissing_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate)207 engstateInitMissing_IMPL
208 (
209     OBJGPU      *pGpu,
210     OBJENGSTATE *pEngstate
211 )
212 {
213     return;
214 }
215 
216 /*!
217  * @brief Wrapper around StatePreInitUnlocked and StatePreInitLocked
218  */
219 NV_STATUS
engstateStatePreInit_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate)220 engstateStatePreInit_IMPL(OBJGPU *pGpu, OBJENGSTATE *pEngstate)
221 {
222     LOCK_ASSERT_AND_RETURN(rmGpuLockIsOwner());
223 
224     /* Check if we overrode the unlocked variant */
225     if ((engstateStatePreInitUnlocked_Fnptr(pEngstate)      !=
226          engstateStatePreInitUnlocked_IMPL))
227     {
228         NV_STATUS status, lockStatus;
229 
230         rmGpuLocksRelease(GPUS_LOCK_FLAGS_NONE, NULL);
231 
232         status = engstateStatePreInitUnlocked(pGpu, pEngstate);
233 
234         lockStatus = rmGpuLocksAcquire(GPUS_LOCK_FLAGS_NONE,
235                                        RM_LOCK_MODULES_INIT);
236 
237         if (status == NV_OK)
238             status = lockStatus;
239         if (status != NV_OK)
240             return status;
241     }
242 
243     return engstateStatePreInitLocked(pGpu, pEngstate);
244 }
245 
246 /*!
247  * @brief state pre-init locked
248  */
249 NV_STATUS
engstateStatePreInitLocked_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate)250 engstateStatePreInitLocked_IMPL(OBJGPU *pGpu, OBJENGSTATE *pEngstate)
251 {
252     return NV_OK;
253 }
254 
255 /*!
256  * @brief state pre-init unlocked
257  */
258 NV_STATUS
engstateStatePreInitUnlocked_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate)259 engstateStatePreInitUnlocked_IMPL(OBJGPU *pGpu, OBJENGSTATE *pEngstate)
260 {
261     return NV_OK;
262 }
263 
264 /*!
265  * @brief Wrapper around StateInitUnlocked and StateInitLocked
266  */
267 NV_STATUS
engstateStateInit_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate)268 engstateStateInit_IMPL(OBJGPU *pGpu, OBJENGSTATE *pEngstate)
269 {
270     LOCK_ASSERT_AND_RETURN(rmGpuLockIsOwner());
271 
272     /* Check if we overrode the unlocked variant */
273     if (engstateStateInitUnlocked_Fnptr(pEngstate) != engstateStateInitUnlocked_IMPL)
274     {
275         NV_STATUS status, lockStatus;
276 
277         rmGpuLocksRelease(GPUS_LOCK_FLAGS_NONE, NULL);
278 
279         status = engstateStateInitUnlocked(pGpu, pEngstate);
280         lockStatus = rmGpuLocksAcquire(GPUS_LOCK_FLAGS_NONE,
281                                        RM_LOCK_MODULES_INIT);
282 
283         if (status == NV_OK)
284             status = lockStatus;
285         if (status != NV_OK)
286             return status;
287     }
288 
289     return engstateStateInitLocked(pGpu, pEngstate);
290 }
291 
292 /*!
293  * @brief state init locked
294  */
295 NV_STATUS
engstateStateInitLocked_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate)296 engstateStateInitLocked_IMPL(OBJGPU *pGpu, OBJENGSTATE *pEngstate)
297 {
298     return NV_OK;
299 }
300 
301 /*!
302  * @brief state init unlocked
303  */
304 NV_STATUS
engstateStateInitUnlocked_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate)305 engstateStateInitUnlocked_IMPL(OBJGPU *pGpu, OBJENGSTATE *pEngstate)
306 {
307     return NV_OK;
308 }
309 
310 /*!
311  * @brief state pre-load
312  */
313 NV_STATUS
engstateStatePreLoad_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate,NvU32 flags)314 engstateStatePreLoad_IMPL
315 (
316     OBJGPU  *pGpu,
317     OBJENGSTATE *pEngstate,
318     NvU32 flags
319 )
320 {
321     return NV_OK;
322 }
323 
324 /*!
325  * @brief state load
326  */
327 NV_STATUS
engstateStateLoad_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate,NvU32 flags)328 engstateStateLoad_IMPL
329 (
330     OBJGPU  *pGpu,
331     OBJENGSTATE *pEngstate,
332     NvU32 flags
333 )
334 {
335     return NV_OK;
336 }
337 
338 /*!
339  * @brief state post-load
340  */
341 NV_STATUS
engstateStatePostLoad_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate,NvU32 flags)342 engstateStatePostLoad_IMPL
343 (
344     OBJGPU  *pGpu,
345     OBJENGSTATE *pEngstate,
346     NvU32 flags
347 )
348 {
349     return NV_OK;
350 }
351 
352 /*!
353  * @brief state unload
354  */
355 NV_STATUS
engstateStateUnload_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate,NvU32 flags)356 engstateStateUnload_IMPL
357 (
358     OBJGPU  *pGpu,
359     OBJENGSTATE *pEngstate,
360     NvU32 flags
361 )
362 {
363     return NV_OK;
364 }
365 
366 /*!
367  * @brief state pre-unload
368  */
369 NV_STATUS
engstateStatePreUnload_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate,NvU32 flags)370 engstateStatePreUnload_IMPL
371 (
372     OBJGPU  *pGpu,
373     OBJENGSTATE *pEngstate,
374     NvU32 flags
375 )
376 {
377     return NV_OK;
378 }
379 
380 /*!
381  * @brief state post-unload
382  */
383 NV_STATUS
engstateStatePostUnload_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate,NvU32 flags)384 engstateStatePostUnload_IMPL
385 (
386     OBJGPU  *pGpu,
387     OBJENGSTATE *pEngstate,
388     NvU32 flags
389 )
390 {
391     return NV_OK;
392 }
393 
394 /*!
395  * @brief state destroy
396  */
397 void
engstateStateDestroy_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate)398 engstateStateDestroy_IMPL
399 (
400     OBJGPU *pGpu,
401     OBJENGSTATE *pEngstate
402 )
403 {
404 }
405 
406 /*!
407  * @brief returns the ENGDESCRIPTOR associated with this ENGSTATE
408  *
409  * @param[in]   pEngstate
410  */
411 ENGDESCRIPTOR
engstateGetDescriptor_IMPL(OBJENGSTATE * pEngstate)412 engstateGetDescriptor_IMPL
413 (
414     OBJENGSTATE *pEngstate
415 )
416 {
417     return pEngstate->engDesc;
418 }
419 
420 /*!
421  * @brief checks for presence of the hardware associated with this ENGSTATE
422  *
423  * @param[in]   pGpu
424  * @param[in]   pEngstate
425  */
426 NvBool
engstateIsPresent_IMPL(OBJGPU * pGpu,OBJENGSTATE * pEngstate)427 engstateIsPresent_IMPL
428 (
429     OBJGPU *pGpu,
430     OBJENGSTATE *pEngstate
431 )
432 {
433     KernelBus *pKernelBus = GPU_GET_KERNEL_BUS(pGpu);
434 
435     NV_ASSERT(pEngstate != NULL);
436     return kbusCheckEngine_HAL(pGpu, pKernelBus, pEngstate->engDesc);
437 }
438 
439 
440 /*!
441  * @brief returns the FIFO associated with this ENGSTATE
442  *
443  * @param[in]   pEngstate
444  */
445 OBJFIFO *
engstateGetFifo_IMPL(OBJENGSTATE * pEngstate)446 engstateGetFifo_IMPL
447 (
448     OBJENGSTATE *pEngstate
449 )
450 {
451     OBJGPU         *pGpu = ENG_GET_GPU(pEngstate);
452 
453     return GPU_GET_FIFO(pGpu);
454 }
455 
456