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