1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2015-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 /***************************************************************************\
25 * *
26 * This module contains the Platform Request Handler control interface *
27 * *
28 \***************************************************************************/
29
30 /* ------------------------ Includes --------------------------------------- */
31 #include "nvRmReg.h"
32 #include "platform/platform_request_handler.h"
33 #include "platform/platform_request_handler_utils.h"
34 #include "platform/acpi_common.h"
35 #include "diagnostics/tracer.h"
36 #include "os/os.h"
37 #include "objtmr.h"
38 #include "core/locks.h"
39 #include "gps.h"
40 #include "rmapi/client_resource.h"
41
42 /* ------------------------ Datatypes -------------------------------------- */
43 // private typedef for this source file.
44 typedef NV_STATUS PfmreqhndlrControlHandler(PlatformRequestHandler *pPlatformRequestHandler, NvU16 locale, NvU32 *pData);
45
46 // prototypes, to be used inside _PfmreqhndlrControlHandlerTable[]
47 static PfmreqhndlrControlHandler _handleCmdSystemPfmreqhndlrGetSupportedFunctions;
48 static PfmreqhndlrControlHandler _handleCmdSystemPfmreqhndlrDataInitUsingSbiosAndAck;
49
50 typedef struct
51 {
52 NvU16 command;
53 PfmreqhndlrControlHandler *handler;
54 } PFM_REQ_HNDLR_CONTROL_ENTRY;
55
56 PFM_REQ_HNDLR_CONTROL_ENTRY _PfmreqhndlrControlTable[] =
57 {
58 { NV0000_CTRL_CMD_SYSTEM_PFM_REQ_HNDLR_SYS_GET_SUPPORTED_FUNCTIONS , _handleCmdSystemPfmreqhndlrGetSupportedFunctions },
59 { NV0000_CTRL_CMD_SYSTEM_PFM_REQ_HNDLR_DATA_INIT_USING_SBIOS_AND_ACK, _handleCmdSystemPfmreqhndlrDataInitUsingSbiosAndAck },
60
61 // always end with a NULL record
62 { NV0000_CTRL_CMD_SYSTEM_PFM_REQ_HNDLR_INVALID, NULL }
63 };
64
65 NvU16 PerfSensorBlockMap[][32] = {
66 {
67 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 0, 1
68 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 2, 3
69 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 4, 5
70 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 6, 7
71 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 8, 9
72 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 10, 11
73 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 12, 13
74 PFM_REQ_HNDLR_TC_ENABLE, PFM_REQ_HNDLR_RESERVED_COUNTER, // 14, 15
75 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 16, 17
76 PFM_REQ_HNDLR_PSR_PUB_ENTRY(PFM_REQ_HNDLR_PM1_STATE_AVAIL), PFM_REQ_HNDLR_RESERVED_COUNTER, // 18, 19
77 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 20, 21
78 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 22, 23
79 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 24, 25
80 PFM_REQ_HNDLR_CURR_VALUE_PUB_ENTRY(PFM_REQ_HNDLR_TGPU_SENSOR), PFM_REQ_HNDLR_RESERVED_COUNTER, // 26, 27
81 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 28, 29
82 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER // 30, 31
83 },
84 {
85 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 0, 1
86 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 2, 3
87 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 4, 5
88 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 6, 7
89 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 8, 9
90 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 10, 11
91 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 12, 13
92 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 14, 15
93 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 16, 17
94 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_VPS_PS20_SUPPORT, // 18, 19
95 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 20, 21
96 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 22, 23
97 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 24, 25
98 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 26, 27
99 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 28, 29
100 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER // 30, 31
101 },
102 {
103 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 0, 1
104 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 2, 3
105 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 4, 5
106 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 6, 7
107 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 8, 9
108 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 10, 11
109 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 12, 13
110 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 14, 15
111 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 16, 17
112 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 18, 19
113 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 20, 21
114 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 22, 23
115 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 24, 25
116 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 26, 27
117 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 28, 29
118 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER // 30, 31
119 },
120 {
121 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 0, 1
122 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 2, 3
123 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 4, 5
124 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 6, 7
125 PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_TGPU_SENSOR), PFM_REQ_HNDLR_RESERVED_COUNTER, // 8, 9
126 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 10, 11
127 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 12, 13
128 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 14, 15
129 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 16, 17
130 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 18, 19
131 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 20, 21
132 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 22, 23
133 PFM_REQ_HNDLR_AVAIL_SENSOR_MSK, PFM_REQ_HNDLR_RESERVED_COUNTER, // 24, 25
134 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 26, 27
135 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER, // 28, 29
136 PFM_REQ_HNDLR_RESERVED_COUNTER, PFM_REQ_HNDLR_RESERVED_COUNTER // 30, 31
137 }
138 };
139
140 /* ------------------------ Macros ----------------------------------------- */
141 /*!
142 * Macro to detect and request a new update if it is necessary.
143 * If system has already applied the update or reset to EDPpeak limit
144 * the subsequent requests to do the same are ignored unless its different request.
145 */
146 #define PFM_REQ_HNDLR_IS_EDPPEAK_UPDATE_REQUIRED(bUpdateAcpiRequest, bEnabled) \
147 ((bUpdateAcpiRequest && !bEnabled) || (!bUpdateAcpiRequest && bEnabled))
148
149 /*!
150 * Macro to detect and request to enable user configurable TGP mode if it is necessary.
151 * If system has already applied the update or reset to user configurable TGP mode
152 * the subsequent requests to do the same are ignored unless its different request.
153 */
154 #define PFM_REQ_HNDLR_IS_USER_CONFIG_TGP_MODE_UPDATE_REQUIRED(bUpdateAcpiRequest, bEnabled) \
155 ((bUpdateAcpiRequest && !bEnabled) || (!bUpdateAcpiRequest && bEnabled))
156
157 /*!
158 * Macro to detect if a PLATFORM REQUEST HANDLER counter value is valid, the counter is valid if
159 * the counter is supported and its value updated with a valid bit set.
160 */
161 #define PFM_REQ_HNDLR_IS_COUNTER_VALID(pPlatformRequestHandler, counterId) \
162 ((&(pPlatformRequestHandler->sensorData))->PFMREQHNDLRSensorCache[counterId].bSupported && \
163 (!(&(pPlatformRequestHandler->sensorData))->PFMREQHNDLRSensorCache[counterId].bInvalid))
164
165 /* ------------------------ Defines ---------------------------------------- */
166 #define PFM_REQ_HNDLR_USE_SBIOS_LIMIT (0U)
167 #define PFM_REQ_HNDLR_DISABLE_LIMIT (255U)
168 #define PFM_REQ_HNDLR_AVAILABLE_SENSOR_BLOCKS (4U)
169 #define NV0000_CTRL_PFM_REQ_HNDLR_THERM_LIMIT_SRC_USER_LIMITED (1)
170 #define NV0000_CTRL_PFM_REQ_HNDLR_THERM_LIMIT_SRC_SBIOS_LIMITED (2)
171 #define NV0000_CTRL_PFM_REQ_HNDLR_THERM_LIMIT_SRC_SBIOS_UNLIMITED (3)
172 #define NV0000_CTRL_PFM_REQ_HNDLR_THERM_LIMIT_SRC_SBIOS_NOT_SUPPORTED (4)
173 #define NV0000_CTRL_PFM_REQ_HNDLR_THERM_LIMIT_SRC_USER_DISABLED (5)
174
175 /* ---------------------- Static Function Prototypes ----------------------- */
176 static NV_STATUS _pfmreqhndlrSampleSensorLimit (PlatformRequestHandler *pPlatformRequestHandler, NvU32 id, NvU32 timeStamp);
177 static NV_STATUS _pfmreqhndlrSampleSensorLimit_ACPI (PlatformRequestHandler *pPlatformRequestHandler, NvU32 id, NvU32 timeStamp);
178 static NV_STATUS _pfmreqhndlrUpdateSystemParamLimit (PlatformRequestHandler *pPlatformRequestHandler, NvU32 id);
179 static void _pfmreqhndlrUpdateSystemParamLimitWorkItem (NvU32 gpuInstance, void *pParams);
180 static void _pfmreqhndlrResetCounter (PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData, NvU32 id, NvU32 timeStamp);
181 static void _pfmreqhndlrUpdateCounter (PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData, NvU32 id, NvBool bValid, NvU32 value, NvU32 timeStamp);
182 static void _pfmreqhndlrOverrideCounter (PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData, NvU32 id, NvU32 value, NvU32 timeStamp);
183 static void _pfmreqhndlrCancelCounterOverride (PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData, NvU32 id, NvU32 timeStamp);
184 static void _pfmreqhndlrInitSupportedCounter (PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData, NvU32 id, NvBool bVolatile, NvU32 timeStamp);
185 static NvBool _pfmreqhndlrIsCacheEntryStale (PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData, NvU32 counterId, NvU32 timeStamp);
186 static NV_STATUS _pfmreqhndlrCallPshareStatus (PlatformRequestHandler *pPlatformRequestHandler, NvBool bInit);
187 static NvU32 _pfmreqhndlrGetTimeStamp (PlatformRequestHandler *pPlatformRequestHandler);
188 static NV_STATUS _pfmreqhndlrEnablePM1 (OBJGPU *pGpu, NvBool bEnable);
189 static NV_STATUS _pfmreqhndlrSetSupportedStatesFromAcpiParams(OBJGPU *pGpu, PlatformRequestHandler *pPlatformRequestHandler, NvU32 supportedSubfuncs);
190 static NV_STATUS _pfmreqhndlrHandleUserConfigurableTgpModePlatformCustomization(PlatformRequestHandler *pPlatformRequestHandler, OBJGPU *pGpu);
191 static void _pfmreqhndlrUpdatePlatformPowerModeWorkItem (NvU32 gpuInstance, void *pParams);
192 static void _pfmreqhndlrPlatformPowerModeStateReset (PlatformRequestHandler *pPlatformRequestHandler);
193 static NV_STATUS _pfmreqhndlrUpdatePpmdLimit (PlatformRequestHandler *pPlatformRequestHandler, OBJGPU *pGpu, NvBool bInit);
194 static NV_STATUS _pfmreqhndlrUpdateTgpuLimit (PlatformRequestHandler *pPlatformRequestHandler, OBJGPU *pGpu);
195 static void _pfmreqhndlrHandlePlatformSetEdppLimitInfoWorkItem(NvU32 gpuInstance, void *pParams);
196
197 /* ------------------------ Public Functions ------------------------------ */
198 NV_STATUS
pfmreqhndlrControl_IMPL(PlatformRequestHandler * pPlatformRequestHandler,NvU16 command,NvU16 locale,NvU32 * pData)199 pfmreqhndlrControl_IMPL
200 (
201 PlatformRequestHandler *pPlatformRequestHandler,
202 NvU16 command,
203 NvU16 locale,
204 NvU32 *pData
205 )
206 {
207 PFM_REQ_HNDLR_CONTROL_ENTRY *pPfmreqhndlrCtrlTableEntry = NULL;
208
209 if (!pPlatformRequestHandler)
210 {
211 return NV_ERR_NOT_SUPPORTED;
212 }
213
214 for (pPfmreqhndlrCtrlTableEntry = _PfmreqhndlrControlTable;
215 pPfmreqhndlrCtrlTableEntry->handler;
216 pPfmreqhndlrCtrlTableEntry++)
217 {
218 if (command == pPfmreqhndlrCtrlTableEntry->command)
219 {
220 return pPfmreqhndlrCtrlTableEntry->handler(pPlatformRequestHandler, locale, pData);
221 }
222 }
223
224 return NV_ERR_NOT_SUPPORTED;
225 }
226
227 /*!
228 * Set/Remove the operating limit of a specific system-parameter (denoted by
229 * id) using a deferred workitem.
230 *
231 * @param[in] pPlatformRequestHandler *PlatformRequestHandler pointer
232 * @param[in] id Identifier of parameter (PFM_REQ_HNDLR_*_SENSOR) to update
233 * @param[in] limit
234 * New operating-limit to set for the parameter. All limits are accepted as
235 * unsigned integers, but internally they should be formatted based on the
236 * type of id/sensor they correspond to. Limits for temperature-sensors for
237 * instance should be stored in NvTemp format.
238 * @param[in] bSet Indicates we are setting or removing the limit
239 *
240 * @return NV_OK Upon successful update
241 * @return NV_ERR_INVALID_ARGUMENT Invalid parameter type/id
242 * @return NV_ERR_INVALID_REQUEST
243 * Returned if the provided PlatformRequestHandler pointer was NULL or if the corresponding
244 * OBJGPU object could not be found.
245 */
246 NV_STATUS
pfmreqhndlrOperatingLimitUpdate_IMPL(PlatformRequestHandler * pPlatformRequestHandler,NvU32 id,NvU32 limit,NvBool bSet)247 pfmreqhndlrOperatingLimitUpdate_IMPL
248 (
249 PlatformRequestHandler *pPlatformRequestHandler,
250 NvU32 id,
251 NvU32 limit,
252 NvBool bSet
253 )
254 {
255 NV_STATUS status = NV_OK;
256 OBJGPU *pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
257
258 if (id >= PFM_REQ_HNDLR_PSHAREPARAMS_COUNT)
259 {
260 return NV_ERR_INVALID_ARGUMENT;
261 }
262 NV_ASSERT_OR_RETURN(NULL != pPlatformRequestHandler, NV_ERR_INVALID_REQUEST);
263
264 if (bSet)
265 {
266 //
267 // Temperature limits arrive in NvTemp format but are stored in NvU32
268 // format. Perform the converstion. The limits will be transformed back to
269 // NvTemp values before they are used. Once the analogous ACPI code is
270 // changed to perform an immediate conversion from NvS32 to NvTemp, the
271 // limits can be stored in NvTemp format directly and double-conversion can
272 // be removed.
273 //
274 switch (id)
275 {
276 case PFM_REQ_HNDLR_TGPU_SENSOR:
277 limit = NV_TYPES_NV_TEMP_TO_CELSIUS_ROUNDED((NvTemp)limit);
278 break;
279 }
280
281 status = pfmreqhndlrUpdatePerfCounter(pPlatformRequestHandler, PFM_REQ_HNDLR_LIMIT(id), limit);
282 if (status != NV_OK)
283 {
284 NV_PRINTF(LEVEL_ERROR, "Update perf counter failed.\n");
285 DBG_BREAKPOINT();
286 return status;
287 }
288 }
289 else
290 {
291 _pfmreqhndlrResetCounter(&pPlatformRequestHandler->sensorData, PFM_REQ_HNDLR_LIMIT(id),
292 _pfmreqhndlrGetTimeStamp(pPlatformRequestHandler));
293 }
294
295 // Record which counter needs to be updated
296 pPlatformRequestHandler->sysControlData.queuedCounterMask |= NVBIT(id);
297
298 //
299 // Don't submit the workitem again if there is already a pending workitem,
300 // all the touched counters will be updated once the workitem is executed.
301 //
302 if (!pPlatformRequestHandler->sysControlData.bWorkItemPending)
303 {
304 status = osQueueWorkItem(pGpu,
305 _pfmreqhndlrUpdateSystemParamLimitWorkItem, NULL);
306
307 if (status != NV_OK)
308 {
309 //
310 // It is not a real failure if the OS doesn't support workitem,
311 // thus setting the status to NV_OK so that we will update the
312 // limit directly in this situation. But if the error code is
313 // not NV_ERR_NOT_SUPPORTED, then we treat it as real failure
314 // and will not do any update. The queued ID will be kept in
315 // this situation so that we can still handle it if we get any
316 // chance to queue another workitem later.
317 //
318 if (status == NV_ERR_NOT_SUPPORTED)
319 {
320 //
321 // Reset the queued id if the workitem is not supported (we
322 // will update the limit directly)
323 //
324 pPlatformRequestHandler->sysControlData.queuedCounterMask &= ~(NVBIT(id));
325 status = NV_OK;
326 }
327 }
328 else
329 {
330 pPlatformRequestHandler->sysControlData.bWorkItemPending = NV_TRUE;
331 }
332 }
333
334 if (status == NV_OK)
335 {
336 if (!pPlatformRequestHandler->sysControlData.bWorkItemPending)
337 {
338 //
339 // Update the limit directly if nothing wrong and no workitem is
340 // queued
341 //
342 return _pfmreqhndlrUpdateSystemParamLimit(pPlatformRequestHandler, id);
343 }
344 else
345 {
346 //
347 // Let the client knows that more processing is needed since
348 // workitem is queued
349 //
350 return NV_WARN_MORE_PROCESSING_REQUIRED;
351 }
352 }
353
354 return status;
355 }
356
357 //
358 // cliresCtrlCmdSystemPfmreqhndlrCtrl
359 //
360 // This function process control request for the PLATFORM REQUEST HANDLER object.
361 //
362 NV_STATUS
cliresCtrlCmdSystemPfmreqhndlrCtrl_IMPL(RmClientResource * pRmCliRes,NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_CTRL_PARAMS * pParams)363 cliresCtrlCmdSystemPfmreqhndlrCtrl_IMPL
364 (
365 RmClientResource *pRmCliRes,
366 NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_CTRL_PARAMS *pParams
367 )
368 {
369 OBJSYS *pSys = SYS_GET_INSTANCE();
370 PlatformRequestHandler *pPlatformRequestHandler = SYS_GET_PFM_REQ_HNDLR(pSys);
371 OBJGPU *pGpu = NULL;
372 PPFM_REQ_HNDLR_SENSOR_DATA pPfmreqhndlrData = NULL;
373 NV_STATUS status = NV_OK;
374 NvU32 timeStamp;
375 NvU32 newLimit;
376 NvU32 counterVal;
377 NvU16 counterId;
378 RM_API *pRmApi = NULL;
379
380 if (NULL == pPlatformRequestHandler)
381 {
382 return NV_ERR_NOT_SUPPORTED;
383 }
384 pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
385 pPfmreqhndlrData = &(pPlatformRequestHandler->sensorData);
386
387 if (NULL == pGpu)
388 {
389 return NV_ERR_NOT_SUPPORTED;
390 }
391
392 pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
393
394 timeStamp = _pfmreqhndlrGetTimeStamp(pPlatformRequestHandler);
395
396 switch (pParams->cmd)
397 {
398 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_THERM_LIMIT:
399 {
400 counterId = (NvU16)pParams->input[NV0000_CTRL_PFM_REQ_HNDLR_INPUT_SENSOR_INDEX];
401
402 if (PFM_REQ_HNDLR_VALID_LIMIT_ID(counterId))
403 {
404 if (NV_OK == pfmreqhndlrGetPerfSensorCounterById(pPlatformRequestHandler,
405 counterId,
406 &counterVal))
407 {
408 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_THERMAL_LIMIT] = counterVal;
409 if (pPfmreqhndlrData->PFMREQHNDLRSensorCache[counterId].bOverridden)
410 {
411 // the Thermal limit is from a user specified limit.
412 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_LIMIT_SOURCE] =
413 NV0000_CTRL_PFM_REQ_HNDLR_THERM_LIMIT_SRC_USER_LIMITED;
414 }
415 else
416 {
417 // the thermal limit is from the SBIOS.
418 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_LIMIT_SOURCE] =
419 NV0000_CTRL_PFM_REQ_HNDLR_THERM_LIMIT_SRC_SBIOS_LIMITED;
420 }
421 }
422 else
423 {
424 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_THERMAL_LIMIT] = 0;
425 if (pPfmreqhndlrData->PFMREQHNDLRSensorCache[counterId].bSupported)
426 {
427 // the SBIOS is not limiting the thermal sensor.
428 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_LIMIT_SOURCE] =
429 NV0000_CTRL_PFM_REQ_HNDLR_THERM_LIMIT_SRC_SBIOS_UNLIMITED;
430 }
431 else
432 {
433 // the SBIOS is not supporting this thermal limit.
434 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_LIMIT_SOURCE] =
435 NV0000_CTRL_PFM_REQ_HNDLR_THERM_LIMIT_SRC_SBIOS_NOT_SUPPORTED;
436 }
437 }
438 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_MIN_LIMIT] = 1;
439 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_MAX_LIMIT] = 100;
440
441 status = NV_OK;
442 }
443 else
444 {
445 status = NV_ERR_INVALID_ARGUMENT;
446 }
447 break;
448 }
449 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_THERM_LIMIT:
450 {
451 newLimit = pParams->input[NV0000_CTRL_PFM_REQ_HNDLR_INPUT_THERMAL_LIMIT];
452 counterId = (NvU16)pParams->input[NV0000_CTRL_PFM_REQ_HNDLR_INPUT_SENSOR_INDEX];
453
454 if (PFM_REQ_HNDLR_VALID_LIMIT_ID(counterId))
455 {
456 if (PFM_REQ_HNDLR_USE_SBIOS_LIMIT == newLimit)
457 {
458 // clear any override & invalidate the cached limit.
459 _pfmreqhndlrCancelCounterOverride(pPfmreqhndlrData, counterId, timeStamp);
460 }
461 else
462 {
463 // push the new limit into the sensor cache & mark it as overridden.
464 _pfmreqhndlrOverrideCounter(pPfmreqhndlrData, counterId, pParams->input[NV0000_CTRL_PFM_REQ_HNDLR_INPUT_THERMAL_LIMIT], timeStamp);
465 }
466
467 if (PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_TGPU_SENSOR) == counterId)
468 {
469 // get & apply the new limit.
470 if (NV_OK == pfmreqhndlrGetPerfSensorCounterById(pPlatformRequestHandler,
471 counterId,
472 &counterVal))
473 {
474 NV2080_CTRL_CMD_INTERNAL_THERM_PFM_REQ_HNDLR_UPDATE_TGPU_LIMIT_PARAMS params = { 0 };
475 params.targetTemp = NV_TYPES_CELSIUS_TO_NV_TEMP(newLimit);;
476
477 status = pRmApi->Control(pRmApi,
478 pGpu->hInternalClient,
479 pGpu->hInternalSubdevice,
480 NV2080_CTRL_CMD_INTERNAL_THERM_PFM_REQ_HNDLR_UPDATE_TGPU_LIMIT,
481 ¶ms,
482 sizeof(params));
483
484 if (status != NV_OK)
485 {
486 status = NV_ERR_NOT_SUPPORTED;
487 break;
488 }
489 }
490 }
491 status = NV_OK;
492 }
493 else
494 {
495 status = NV_ERR_INVALID_ARGUMENT;
496 }
497 break;
498 }
499 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_TEMP_CTRL_STATUS:
500 {
501 //
502 // No longer able to turn on/off the temperature controller, so
503 // getting status is no longer needed.
504 //
505 status = NV_ERR_NOT_SUPPORTED;
506 break;
507 }
508 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_TEMP_CTRL_STATUS:
509 {
510 // No longer able to turn on/off the temperature controller
511 status = NV_ERR_NOT_SUPPORTED;
512 break;
513 }
514 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_TEMP_CTRL_DOWN_N_DELTA:
515 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_TEMP_CTRL_HOLD_DELTA:
516 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_TEMP_CTRL_UP_DELTA:
517 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_TEMP_CTRL_ENGAGE_DELTA:
518 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_TEMP_CTRL_DISENGAGE_DELTA:
519 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_TEMP_CTRL_DOWN_N_DELTA:
520 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_TEMP_CTRL_HOLD_DELTA:
521 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_TEMP_CTRL_UP_DELTA:
522 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_TEMP_CTRL_ENGAGE_DELTA:
523 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_TEMP_CTRL_DISENGAGE_DELTA:
524 {
525 status = NV_ERR_INVALID_ARGUMENT;
526 break;
527 }
528 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_PERF_SENSOR:
529 {
530 status = pfmreqhndlrGetPerfSensorCounterById(pPlatformRequestHandler,
531 (NvU16)pParams->input[NV0000_CTRL_PFM_REQ_HNDLR_INPUT_SENSOR_INDEX],
532 &counterVal);
533 if (NV_OK == status)
534 {
535 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_PERF_SENSOR_VALUE] = counterVal;
536 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_PERF_SENSOR_AVAILABLE] = NV_TRUE;
537 }
538 else
539 {
540 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_PERF_SENSOR_VALUE] = 0;
541 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_RESULT_PERF_SENSOR_AVAILABLE] = NV_FALSE;
542 }
543 break;
544 }
545 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_CALL_ACPI:
546 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_IGPU_TURBO:
547 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_TEMP_PERIOD:
548 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_TEMP_PERIOD:
549 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_TEMP_NUDGE_FACTOR:
550 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_TEMP_NUDGE_FACTOR:
551 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_TEMP_THRESHOLD_SAMPLES:
552 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_TEMP_THRESHOLD_SAMPLES:
553 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_TEMP_PERF_LIMITS:
554 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_TEMP_PERF_LIMITS:
555 {
556 status = NV_ERR_NOT_SUPPORTED;
557 break;
558 }
559 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_PM1_AVAILABLE:
560 {
561 if (!pPlatformRequestHandler->controlData.bPM1ForcedOff)
562 {
563 status = _pfmreqhndlrEnablePM1(pGpu,
564 pParams->input[NV0000_CTRL_PFM_REQ_HNDLR_INPUT_PM1_AVAILABLE]);
565 }
566 else
567 {
568 status = NV_ERR_NOT_SUPPORTED;
569 }
570 break;
571 }
572 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_PM1_AVAILABLE:
573 {
574 if (!pPlatformRequestHandler->controlData.bPM1ForcedOff)
575 {
576 status = pfmreqhndlrGetPerfSensorCounterById(pPlatformRequestHandler,
577 PFM_REQ_HNDLR_PM1_STATE_AVAIL,
578 &counterVal);
579 if (NV_OK == status)
580 {
581 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_OUTPUT_PM1_AVAILABLE] = counterVal;
582 }
583 else
584 {
585 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_OUTPUT_PM1_AVAILABLE] = 0;
586 }
587 }
588 else
589 {
590 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_OUTPUT_PM1_AVAILABLE] = 0;
591 status = NV_ERR_NOT_SUPPORTED;
592 }
593 break;
594 }
595 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_CPU_PACKAGE_LIMITS:
596 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_CPU_PACKAGE_LIMITS:
597 {
598 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS_EX acpiParamsEx = {0};
599
600 // Use EX type struct -- three NvU32s for both input and output for input
601 acpiParamsEx.inSize = NV0000_CTRL_PFM_REQ_HNDLR_PPL_ARGS_COUNT * sizeof(NvU32);
602 acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_PPL_ARGS_VERSION_IDX] =
603 FLD_SET_DRF(0000_CTRL_PFM_REQ_HNDLR, _PPL_ARG0_VERSION, _MAJOR, _V1,
604 acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_PPL_ARGS_VERSION_IDX]);
605 acpiParamsEx.outSize = NV0000_CTRL_PFM_REQ_HNDLR_PPL_ARGS_COUNT * sizeof(NvU32);
606
607 if (pParams->cmd == NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_CPU_PACKAGE_LIMITS)
608 {
609 acpiParamsEx.pfmreqhndlrFunc = GPS_FUNC_SETPPL;
610 acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_PPL_ARGS_LIMIT1_IDX] =
611 pParams->input[NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_CPU_PACKAGE_LIMITS_PL1];
612 acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_PPL_ARGS_LIMIT2_IDX] =
613 pParams->input[NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_CPU_PACKAGE_LIMITS_PL1] * 2;
614 }
615 else
616 {
617 acpiParamsEx.pfmreqhndlrFunc = GPS_FUNC_GETPPL;
618 }
619
620 status = pfmreqhndlrCallACPI_EX(pGpu, &acpiParamsEx);
621 if (NV_OK == status)
622 {
623 // Check for major version 1
624 if (FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PPL_ARG0_VERSION, _MAJOR, _V1,
625 acpiParamsEx.output[NV0000_CTRL_PFM_REQ_HNDLR_PPL_ARGS_VERSION_IDX]))
626 {
627 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_CPU_PACKAGE_LIMITS_PL1] =
628 acpiParamsEx.output[NV0000_CTRL_PFM_REQ_HNDLR_PPL_ARGS_LIMIT1_IDX];
629 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_CPU_PACKAGE_LIMITS_PL2] =
630 acpiParamsEx.output[NV0000_CTRL_PFM_REQ_HNDLR_PPL_ARGS_LIMIT2_IDX];
631 }
632 else
633 {
634 status = NV_ERR_INVALID_DATA;
635 }
636 }
637 break;
638 }
639 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_CPU_FREQ_LIMIT:
640 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_CPU_FREQ_LIMIT:
641 {
642 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS_EX acpiParamsEx = {0};
643
644 // Use EX type struct -- two NvU32s for both input and output for input
645 acpiParamsEx.inSize = NV0000_CTRL_PFM_REQ_HNDLR_TRL_ARGS_COUNT * sizeof(NvU32);
646 acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_TRL_ARGS_VERSION_IDX] =
647 FLD_SET_DRF(0000_CTRL_PFM_REQ_HNDLR, _TRL_ARG0_VERSION, _MAJOR, _V1,
648 acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_TRL_ARGS_VERSION_IDX]);
649 acpiParamsEx.outSize = NV0000_CTRL_PFM_REQ_HNDLR_TRL_ARGS_COUNT * sizeof(NvU32);
650
651 if (pParams->cmd == NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_CPU_FREQ_LIMIT)
652 {
653 acpiParamsEx.pfmreqhndlrFunc = GPS_FUNC_SETTRL;
654 acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_TRL_ARGS_FREQ_MHZ_IDX] =
655 pParams->input[NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_CPU_FREQ_LIMIT_MHZ];
656 }
657 else
658 {
659 acpiParamsEx.pfmreqhndlrFunc = GPS_FUNC_GETTRL;
660 acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_TRL_ARGS_FREQ_MHZ_IDX] = 0;
661 }
662
663 status = pfmreqhndlrCallACPI_EX(pGpu, &acpiParamsEx);
664 if (NV_OK == status)
665 {
666 // Check for major version 1
667 if (FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _TRL_ARG0_VERSION, _MAJOR, _V1,
668 acpiParamsEx.output[NV0000_CTRL_PFM_REQ_HNDLR_TRL_ARGS_VERSION_IDX]))
669 {
670 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_CPU_FREQ_LIMIT_MHZ] =
671 acpiParamsEx.output[NV0000_CTRL_PFM_REQ_HNDLR_TRL_ARGS_FREQ_MHZ_IDX];
672 }
673 else
674 {
675 status = NV_ERR_INVALID_DATA;
676 }
677 }
678 break;
679 }
680 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_PPM:
681 {
682 //
683 // Mask is cached in pfmreqhndlrStateLoad and when we recieve SBIOS notification on battery transitions in AC.
684 // Index is cached in pfmreqhndlrStateLoad, SBIOS notification and in the workItem to set the Platform power mode.
685 // Return the cached values instead of making ACPI calls.
686 //
687 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_PPM_INDEX] =
688 (NvS32) pPlatformRequestHandler->ppmData.ppmIdxCurrent;
689 pParams->result[NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_GET_PPM_AVAILABLE_MASK] =
690 (NvS32) pPlatformRequestHandler->ppmData.ppmMaskCurrent;
691
692 status = NV_OK;
693 break;
694 }
695 case NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_PPM:
696 {
697
698 // Return error if platform power modes are not supported
699 if (pPlatformRequestHandler->ppmData.ppmMaskCurrent == NV0000_CTRL_PFM_REQ_HNDLR_PPM_MASK_INVALID)
700 {
701 status = NV_ERR_INVALID_DATA;
702 break;
703 }
704 NvU8 clientPpmIdx = (NvU8) pParams->input[NV0000_CTRL_PFM_REQ_HNDLR_CMD_TYPE_SET_PPM_INDEX];
705
706 // If requested mode is same as current mode, return success
707 if (pPlatformRequestHandler->ppmData.ppmIdxCurrent == clientPpmIdx)
708 {
709 status = NV_OK;
710 break;
711 }
712
713 // Return error for invalid mask or if index requested is not present in the mask
714 if ((clientPpmIdx == NV0000_CTRL_PFM_REQ_HNDLR_PPM_INDEX_INVALID) ||
715 !(pPlatformRequestHandler->ppmData.ppmMaskCurrent & NVBIT(clientPpmIdx)))
716 {
717 status = NV_ERR_INVALID_DATA;
718 break;
719 }
720
721 status = NV_ERR_BUSY_RETRY;
722 if (!pPlatformRequestHandler->ppmData.bWorkItemPending)
723 {
724 pPlatformRequestHandler->ppmData.ppmIdxRequested = clientPpmIdx;
725 // Create a workItem to change Platform Power Mode
726 status = osQueueWorkItem(pGpu, _pfmreqhndlrUpdatePlatformPowerModeWorkItem, NULL);
727 if (status == NV_OK)
728 {
729 // Queing workitem succeeded, mark it as pending.
730 pPlatformRequestHandler->ppmData.bWorkItemPending = NV_TRUE;
731 }
732 }
733 break;
734 }
735 default:
736 {
737 NV_PRINTF(LEVEL_ERROR, "Unknown request %x\n", pParams->cmd);
738 status = NV_ERR_NOT_SUPPORTED;
739 break;
740 }
741 }
742 return status;
743 }
744
745 NV_STATUS
cliresCtrlCmdSystemPfmreqhndlrGetFrmData_IMPL(RmClientResource * pRmCliRes,NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_GET_FRM_DATA_PARAMS * pParams)746 cliresCtrlCmdSystemPfmreqhndlrGetFrmData_IMPL
747 (
748 RmClientResource *pRmCliRes,
749 NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_GET_FRM_DATA_PARAMS *pParams
750 )
751 {
752 OBJSYS *pSys = SYS_GET_INSTANCE();
753 PlatformRequestHandler *pPlatformRequestHandler = SYS_GET_PFM_REQ_HNDLR(pSys);
754 NvU8 logicalBufferStart;
755 NvU8 block0Size;
756
757 if (NULL==pPlatformRequestHandler)
758 {
759 return NV_ERR_NOT_SUPPORTED;
760 }
761
762 pParams->nextSampleNumber = pPlatformRequestHandler->frmData.nextSampleNumber;
763
764 // logical buffer starts at the oldest entry
765 logicalBufferStart = ((pPlatformRequestHandler->frmData.nextSampleNumber) % NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_FRM_DATA_SAMPLE_SIZE);
766
767 // Block0 goes from the logical start of the buffer to the physical end of the buffer
768 block0Size = (NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_FRM_DATA_SAMPLE_SIZE - logicalBufferStart);
769
770 portMemCopy(&(pParams->samples[0]), (sizeof(pPlatformRequestHandler->frmData.samples[0]) * block0Size), &(pPlatformRequestHandler->frmData.samples[logicalBufferStart]), (sizeof(pPlatformRequestHandler->frmData.samples[0]) * block0Size));
771
772 //
773 // if the logical buffer is wrapping from the physical end of the buffer back to the beginning,
774 // copy the logical end block to the end of the output buffer
775 //
776 if (0 != logicalBufferStart)
777 {
778 portMemCopy(&(pParams->samples[block0Size]), (sizeof(pPlatformRequestHandler->frmData.samples[0]) * (logicalBufferStart)), &(pPlatformRequestHandler->frmData.samples[0]), (sizeof(pPlatformRequestHandler->frmData.samples[0]) * (logicalBufferStart)));
779 }
780
781 return NV_OK;
782 }
783
784 NV_STATUS
cliresCtrlCmdSystemPfmreqhndlrSetFrmData_IMPL(RmClientResource * pRmCliRes,NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_SET_FRM_DATA_PARAMS * pParams)785 cliresCtrlCmdSystemPfmreqhndlrSetFrmData_IMPL
786 (
787 RmClientResource *pRmCliRes,
788 NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_SET_FRM_DATA_PARAMS *pParams
789 )
790 {
791 OBJSYS *pSys = SYS_GET_INSTANCE();
792 PlatformRequestHandler *pPlatformRequestHandler = SYS_GET_PFM_REQ_HNDLR(pSys);
793 NvU8 sampleNumber = 0;
794
795 if (NULL == pPlatformRequestHandler)
796 {
797 return NV_ERR_NOT_SUPPORTED;
798 }
799
800 sampleNumber = ((pPlatformRequestHandler->frmData.nextSampleNumber) % NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_FRM_DATA_SAMPLE_SIZE);
801 pPlatformRequestHandler->frmData.samples[sampleNumber] = pParams->sampleData;
802 pPlatformRequestHandler->frmData.samples[sampleNumber].sampleNumber = pPlatformRequestHandler->frmData.nextSampleNumber;
803 pPlatformRequestHandler->frmData.nextSampleNumber++;
804
805 return NV_OK;
806 }
807
808 NV_STATUS
cliresCtrlCmdSystemPfmreqhndlrCallAcpi_IMPL(RmClientResource * pRmCliRes,NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_CALL_ACPI_PARAMS * pParams)809 cliresCtrlCmdSystemPfmreqhndlrCallAcpi_IMPL
810 (
811 RmClientResource *pRmCliRes,
812 NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_CALL_ACPI_PARAMS *pParams
813 )
814 {
815 NV_STATUS status;
816 OBJSYS *pSys = SYS_GET_INSTANCE();
817 PlatformRequestHandler *pPlatformRequestHandler = SYS_GET_PFM_REQ_HNDLR(pSys);
818 OBJGPU *pGpu;
819 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS acpiParams;
820
821 if (NULL == pPlatformRequestHandler)
822 {
823 return NV_ERR_NOT_SUPPORTED;
824 }
825 pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
826 if (NULL == pGpu)
827 {
828 return NV_ERR_NOT_SUPPORTED;
829 }
830
831 portMemSet((void *) &acpiParams, 0, sizeof(NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS));
832 acpiParams.ctrl.cmd = pParams->cmd;
833 acpiParams.ctrl.input = pParams->input;
834 acpiParams.output.pBuffer = (NvU8*)&(pParams->result);
835 acpiParams.output.bufferSz = sizeof(pParams->result);
836
837 status = pfmreqhndlrCallACPI(pGpu, &acpiParams);
838
839 if (NV_OK != status)
840 {
841 return status;
842 }
843 if (0 == acpiParams.output.bufferSz)
844 {
845 // we used the result field, not the buffer, copy the results to the buffer
846 // based on the command type.
847 switch(acpiParams.ctrl.cmd)
848 {
849 case NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_SUPPORT:
850 {
851 pParams->result[0] = acpiParams.output.result[0];
852 pParams->result[1] = acpiParams.output.result[1];
853 pParams->resultSz = sizeof(acpiParams.output.result[0]) * 2;
854 break;
855 }
856 case NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_PCONTROL:
857 case NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_PSHARESTATUS:
858 {
859 pParams->result[0] = acpiParams.output.result[0];
860 pParams->resultSz = sizeof(acpiParams.output.result[0]);
861 break;
862 }
863 // anything left is either a command that should have used a buffer, or something we don't recognize.
864 default:
865 {
866 pParams->resultSz = 0;
867 break;
868 }
869 }
870 }
871 else
872 {
873 pParams->resultSz = acpiParams.output.bufferSz;
874 }
875 return status;
876 }
877
878 NV_STATUS
pfmreqhndlrCallACPI(OBJGPU * pGpu,NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS * pParams)879 pfmreqhndlrCallACPI
880 (
881 OBJGPU *pGpu,
882 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS *pParams
883 )
884 {
885 OBJSYS *pSys = SYS_GET_INSTANCE();
886 PlatformRequestHandler *pPlatformRequestHandler = SYS_GET_PFM_REQ_HNDLR(pSys);
887 NV_STATUS status = NV_OK;
888 NvU32 rc;
889 NvU16 paramSize;
890
891 switch (pParams->ctrl.cmd)
892 {
893 case NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_SUPPORT:
894 {
895 // no input parameters
896 pParams->output.result[0] = 0;
897 pParams->output.result[1] = 0;
898 pParams->output.bufferSz = 0;
899 paramSize = sizeof(pParams->output.result);
900
901 if ((rc = osCallACPI_DSM(pGpu,
902 pPlatformRequestHandler->dsmVersion,
903 GPS_FUNC_SUPPORT,
904 pParams->output.result,
905 ¶mSize)) != NV_OK)
906 {
907 NV_PRINTF(LEVEL_ERROR,
908 "Unable to retrieve PFM_REQ_HNDLR_SUPPORT. Possibly not supported/enabled by "
909 "CPU/ACPI? rc = %x\n", rc);
910 status = NV_ERR_NOT_SUPPORTED;
911 RMTRACE_SBIOS (_ACPI_DSM_ERROR, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_SUPPORT, 0, 0, 0, 0, 0);
912 break;
913 }
914 RMTRACE_SBIOS (_ACPI_DSM_METHOD, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_SUPPORT, pParams->output.result[0], pParams->output.result[1], 0, 0, 0);
915 break;
916 }
917 case NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_PCONTROL:
918 {
919 pParams->output.result[0] = pParams->ctrl.input;
920 paramSize = sizeof(pParams->output.result[0]);
921 pParams->output.bufferSz = 0;
922
923 if ((rc = osCallACPI_DSM(pGpu,
924 pPlatformRequestHandler->dsmVersion,
925 GPS_FUNC_PCONTROL,
926 (NvU32 *) &pParams->output.result[0],
927 ¶mSize)) != NV_OK)
928 {
929 NV_PRINTF(LEVEL_ERROR,
930 "Unable to retrieve PFM_REQ_HNDLR_PCONTROL. Possibly not supported/enabled by "
931 "CPU/ACPI? rc = %x\n", rc);
932 status = NV_ERR_NOT_SUPPORTED;
933 RMTRACE_SBIOS (_ACPI_DSM_ERROR, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_PCONTROL, 0, 0, 0, 0, 0);
934 break;
935 }
936 RMTRACE_SBIOS (_ACPI_DSM_METHOD, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_PCONTROL, pParams->ctrl.input, pParams->output.result[0], 0, 0, 0);
937 break;
938 }
939 case NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_PSHARESTATUS:
940 {
941 pParams->output.result[0] = pParams->ctrl.input;
942 paramSize = sizeof(pParams->output.result[0]);
943 pParams->output.bufferSz = 0;
944
945 if ((rc = osCallACPI_DSM(pGpu,
946 pPlatformRequestHandler->dsmVersion,
947 GPS_FUNC_PSHARESTATUS,
948 &pParams->output.result[0],
949 ¶mSize)) != NV_OK)
950 {
951 NV_PRINTF(LEVEL_ERROR,
952 "Unable to retrieve PFM_REQ_HNDLR_PSHARESTATUS. Possibly not supported/enabled by"
953 " CPU/ACPI? rc = %x\n", rc);
954 status = NV_ERR_NOT_SUPPORTED;
955 RMTRACE_SBIOS (_ACPI_DSM_ERROR, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_PSHARESTATUS, 0, 0, 0, 0, 0);
956 break;
957 }
958 RMTRACE_SBIOS (_ACPI_DSM_METHOD, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_PSHARESTATUS, pParams->ctrl.input, pParams->output.result[0], 0, 0, 0);
959 break;
960 }
961 case NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_PSHAREPARAMS:
962 {
963 if (sizeof(PFM_REQ_HNDLR_PSHAREDATA) > pParams->output.bufferSz)
964 {
965 NV_PRINTF(LEVEL_ERROR, "buffer to small to hold output.\n");
966 status = NV_ERR_NOT_SUPPORTED;
967 break;
968 }
969 *((NvU32*)(pParams->output.pBuffer)) = pParams->ctrl.input;
970
971 if ((rc = osCallACPI_DSM(pGpu,
972 pPlatformRequestHandler->dsmVersion,
973 GPS_FUNC_PSHAREPARAMS,
974 (NvU32 *) pParams->output.pBuffer,
975 &pParams->output.bufferSz)) != NV_OK)
976 {
977 NV_PRINTF(LEVEL_ERROR,
978 "Unable to retrieve PFM_REQ_HNDLR_PSHAREPARAMS. Possibly not supported/enabled by"
979 " CPU/ACPI? rc = %x\n", rc);
980 status = NV_ERR_NOT_SUPPORTED;
981 RMTRACE_SBIOS (_ACPI_DSM_ERROR, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_PSHAREPARAMS, 0, 0, 0, 0, 0);
982 break;
983 }
984 RMTRACE_SBIOS (_ACPI_DSM_METHOD, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_PSHAREPARAMS, ((NvU32 *) pParams->output.pBuffer)[0], ((NvU32 *) pParams->output.pBuffer)[3], ((NvU32 *) pParams->output.pBuffer)[6], 0, 0);
985 break;
986 }
987 case NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_GETEDPPLIMIT:
988 {
989 pParams->output.result[0] = pParams->ctrl.input;
990 paramSize = sizeof(pParams->output.result[0]);
991
992 if ((rc = osCallACPI_DSM(pGpu,
993 pPlatformRequestHandler->dsmVersion,
994 GPS_FUNC_GETEDPPLIMIT,
995 &pParams->output.result[0],
996 ¶mSize)) != NV_OK)
997 {
998 NV_PRINTF(LEVEL_ERROR,
999 "Unable to retrieve PFM_REQ_HNDLR_FUNC_GETEDPPLIMIT. Possibly not supported/enabled by "
1000 "ACPI? rc = %x\n", rc);
1001 status = NV_ERR_NOT_SUPPORTED;
1002 RMTRACE_SBIOS (_ACPI_DSM_ERROR, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_GETEDPPLIMIT, 0, 0, 0, 0, 0);
1003 break;
1004 }
1005 RMTRACE_SBIOS (_ACPI_DSM_METHOD, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_GETEDPPLIMIT, pParams->output.result[0], pParams->output.result[1], 0, 0, 0);
1006 break;
1007 }
1008 case NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_SETEDPPLIMITINFO:
1009 {
1010 if ((rc = osCallACPI_DSM(pGpu,
1011 pPlatformRequestHandler->dsmVersion,
1012 GPS_FUNC_SETEDPPLIMITINFO,
1013 (NvU32 *) pParams->output.pBuffer,
1014 &pParams->output.bufferSz)) != NV_OK)
1015 {
1016 NV_PRINTF(LEVEL_ERROR,
1017 "Unable to retrieve PFM_REQ_HNDLR_FUNC_SETEDPPLIMITINFO. Possibly not supported/enabled by "
1018 "ACPI? rc = %x\n", rc);
1019 status = NV_ERR_NOT_SUPPORTED;
1020 RMTRACE_SBIOS (_ACPI_DSM_ERROR, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_SETEDPPLIMITINFO, 0, 0, 0, 0, 0);
1021 break;
1022 }
1023 RMTRACE_SBIOS (_ACPI_DSM_METHOD, pGpu->gpuId, pPlatformRequestHandler->dsmVersion, GPS_FUNC_SETEDPPLIMITINFO, pParams->output.result[0], pParams->output.result[1], 0, 0, 0);
1024 break;
1025 }
1026 default:
1027 {
1028 NV_PRINTF(LEVEL_ERROR, "Unknown request %x\n",
1029 DRF_VAL(0000_CTRL_PFM_REQ_HNDLR, _CALL_ACPI, _CMD_TYPE, pParams->ctrl.cmd));
1030 status = NV_ERR_NOT_SUPPORTED;
1031 break;
1032 }
1033 }
1034 return status;
1035 }
1036
1037 /*!
1038 * EX version of pfmreqhndlrCallACPI used only for PPL and TRL calls, which require
1039 * a greater number of input args.
1040 *
1041 * @param[in] pGpu GPU object pointer
1042 * @param[in, out] pParams Call parameters
1043 *
1044 * Returns NV_OK if handled successfully; otherwise propogates errors.
1045 */
1046 NV_STATUS
pfmreqhndlrCallACPI_EX(OBJGPU * pGpu,NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS_EX * pParams)1047 pfmreqhndlrCallACPI_EX
1048 (
1049 OBJGPU *pGpu,
1050 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS_EX *pParams
1051 )
1052 {
1053 NvU32 idx;
1054 NvU16 paramSize;
1055 NV_STATUS status;
1056 OBJSYS *pSys = SYS_GET_INSTANCE();
1057 PlatformRequestHandler *pPlatformRequestHandler = SYS_GET_PFM_REQ_HNDLR(pSys);
1058
1059 for (idx = 0; idx < NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS_EX_MAX_SZ; ++idx)
1060 {
1061 pParams->output[idx] = pParams->input[idx];
1062 }
1063 paramSize = pParams->outSize;
1064
1065 if ((status = osCallACPI_DSM(pGpu,
1066 pPlatformRequestHandler->dsmVersion,
1067 pParams->pfmreqhndlrFunc,
1068 pParams->output,
1069 ¶mSize)) != NV_OK)
1070 {
1071 status = NV_ERR_NOT_SUPPORTED;
1072 }
1073 return status;
1074 }
1075
1076 //
1077 // pfmreqhndlrInitSensors
1078 //
1079 // This function initialises the PLATFORM REQUEST HANDLER sensor data.
1080 // it initializes all the data, and determines which sensors are available for sampling.
1081 //
1082 NV_STATUS
pfmreqhndlrInitSensors(PlatformRequestHandler * pPlatformRequestHandler)1083 pfmreqhndlrInitSensors
1084 (
1085 PlatformRequestHandler *pPlatformRequestHandler
1086 )
1087 {
1088 NV_STATUS status = NV_OK;
1089 OBJGPU *pGpu = NULL;
1090 NvU32 timeStamp = 0;
1091 PFM_REQ_HNDLR_PSHAREDATA *pPShareParams = NULL;
1092 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData;
1093 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS
1094 acpiParams;
1095
1096 NV_ASSERT_OR_RETURN(NULL != pPlatformRequestHandler, NV_ERR_INVALID_REQUEST);
1097
1098 pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
1099 NV_ASSERT_OR_RETURN(NULL != pGpu, NV_ERR_INVALID_REQUEST);
1100
1101 pPfmreqhndlrData = &(pPlatformRequestHandler->sensorData);
1102
1103 // init the PLATFORM REQUEST HANDLER data cache.
1104 portMemSet((void *)pPfmreqhndlrData, 0, sizeof(PFM_REQ_HNDLR_SENSOR_DATA));
1105
1106 //
1107 // Initialize a logical sw version based of ACPI dsm version
1108 //
1109 if ((pPlatformRequestHandler->getProperty(pPlatformRequestHandler, PDB_PROP_PFMREQHNDLR_IS_PLATFORM_LEGACY)) ||
1110 (pPlatformRequestHandler->dsmVersion == ACPI_DSM_FUNCTION_GPS_2X))
1111 {
1112 pPfmreqhndlrData->PFMREQHNDLRACPIData.acpiVersionSw =
1113 NV0000_CTRL_PFM_REQ_HNDLR_ACPI_REVISION_SW_2X;
1114 }
1115
1116 // Cache the current timestamp
1117 timeStamp = _pfmreqhndlrGetTimeStamp(pPlatformRequestHandler);
1118
1119 pPfmreqhndlrData->counterHoldPeriod =
1120 PFM_REQ_HNDLR_DEFAULT_COUNTER_HOLD_PERIOD_MS;
1121
1122 //
1123 // init the PSHARESTATUS ACPI cache.
1124 // set up the defaults
1125 //
1126 pPfmreqhndlrData->PFMREQHNDLRACPIData.bPfmReqHndlrSupported = NV_FALSE;
1127
1128 //
1129 // Check if PLATFORM REQUEST HANDLER is supported on this platform
1130 // determine if we can call the PLATFORM REQUEST HANDLER ACPI call.
1131 //
1132 portMemSet((void *) &acpiParams, 0, sizeof(NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS));
1133 acpiParams.ctrl.cmd = NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_SUPPORT;
1134 acpiParams.ctrl.input = 0;
1135 acpiParams.output.pBuffer = NULL;
1136 acpiParams.output.bufferSz = 0;
1137 if (NV_OK == pfmreqhndlrCallACPI(pGpu, &acpiParams))
1138 {
1139 // Set up all the control flags based on all the supported subfunctions
1140 status = _pfmreqhndlrSetSupportedStatesFromAcpiParams(pGpu,
1141 pPlatformRequestHandler, acpiParams.output.result[1]);
1142 if (NV_OK != status)
1143 {
1144 NV_ASSERT_FAILED("Get all the supported PlatformRequestHandler subfunctions");
1145 return status;
1146 }
1147 }
1148 if (pPfmreqhndlrData->PFMREQHNDLRACPIData.bPfmReqHndlrSupported)
1149 {
1150 // call PSHARESTATUS to get the initial values.
1151 _pfmreqhndlrCallPshareStatus(pPlatformRequestHandler, NV_TRUE);
1152
1153 // PShare param is available, determine which sensors it is reporting.
1154 pPShareParams = portMemAllocNonPaged(sizeof(PFM_REQ_HNDLR_PSHAREDATA));
1155 if (NULL != pPShareParams)
1156 {
1157 portMemSet((void *)pPShareParams, 0, sizeof(PFM_REQ_HNDLR_PSHAREDATA));
1158 portMemSet((void *)&acpiParams, 0, sizeof(NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS));
1159
1160 acpiParams.ctrl.cmd = NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_PSHAREPARAMS;
1161 acpiParams.ctrl.input =
1162 DRF_DEF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS, _STATUS_QUERY_TYPE, _SUPPORTED_FIELDS) |
1163 DRF_DEF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS, _STATUS_TGPU, _TRUE) |
1164 DRF_DEF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS, _STATUS_PPMD, _TRUE);
1165 acpiParams.output.pBuffer = (void *) pPShareParams;
1166 acpiParams.output.bufferSz = sizeof(PFM_REQ_HNDLR_PSHAREDATA);
1167
1168 if (NV_OK == pfmreqhndlrCallACPI(pGpu, &acpiParams))
1169 {
1170 // Determine the SBP(PFMREQHNDLR) version on this platform
1171 // save the version number
1172 pPfmreqhndlrData->version = pPShareParams->ulVersion;
1173
1174 // save a mask of available counters
1175 pPfmreqhndlrData->PFMREQHNDLRShareParamsAvailMask = pPShareParams->status &
1176 (DRF_DEF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS, _STATUS_TGPU, _TRUE) |
1177 DRF_DEF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS, _STATUS_PPMD, _TRUE));
1178
1179 _pfmreqhndlrInitSupportedCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_AVAIL_SENSOR_MSK, NV_FALSE, timeStamp);
1180 _pfmreqhndlrUpdateCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_AVAIL_SENSOR_MSK, NV_TRUE, pPfmreqhndlrData->PFMREQHNDLRShareParamsAvailMask, timeStamp);
1181
1182 // check each counter & if available, flag current value, limit, & period as available.
1183 if (0 != (DRF_VAL(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS_STATUS, _TGPU, pPShareParams->status)))
1184 {
1185 _pfmreqhndlrInitSupportedCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_TGPU_SENSOR), NV_TRUE, timeStamp);
1186 _pfmreqhndlrInitSupportedCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_PERIOD(PFM_REQ_HNDLR_TGPU_SENSOR), NV_FALSE, timeStamp);
1187 _pfmreqhndlrUpdateCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_PERIOD(PFM_REQ_HNDLR_TGPU_SENSOR), NV_TRUE, pPShareParams->tGpu, timeStamp);
1188 }
1189 if (PFM_REQ_HNDLR_IS_ACPI_VERSION_SW_2X(pPlatformRequestHandler) &&
1190 (0 != (DRF_VAL(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS_STATUS, _PPMD, pPShareParams->status))))
1191 {
1192 // Invalidate Platform Power Mode cache on boot
1193 _pfmreqhndlrPlatformPowerModeStateReset(pPlatformRequestHandler);
1194
1195 // Init PPMD sensor if this is enabled
1196 _pfmreqhndlrInitSupportedCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_PPMD_SENSOR), NV_TRUE, timeStamp);
1197
1198 // Sample the PPMD counter from init time
1199 _pfmreqhndlrUpdatePpmdLimit(pPlatformRequestHandler, pGpu, NV_TRUE);
1200 }
1201 }
1202 portMemFree(pPShareParams);
1203 }
1204
1205 }
1206
1207 // as long as there is an PlatformRequestHandler object, these counters should always be available.
1208 // The following counters are non-Volatile, they are being updated as the corresponding functions change,
1209 // so they do not need to be sampled on request for a current value.
1210 _pfmreqhndlrInitSupportedCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_VPS_PS20_SUPPORT, NV_TRUE, timeStamp);
1211
1212 // The following counters are volatile, and need to be sampled on request for a current value.
1213 _pfmreqhndlrInitSupportedCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_PM1_STATE_AVAIL, NV_TRUE, timeStamp);
1214
1215 // The following counters are dynamically controlled by the Thermal controller.
1216 // they are currently handled as volatile counters, but could be changed to non-volatile counters
1217 // if TC is modified to push the new values to PFMREQHNDLR when they change.
1218 // (note with the current policy of seperating TC & PFMREQHNDLR this is unlikely)
1219 _pfmreqhndlrInitSupportedCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_TC_ENABLE, NV_TRUE, timeStamp);
1220
1221 return status;
1222 }
1223
1224 /*!
1225 * Set/update the value of a specific perf-counter (denoted by id).
1226 *
1227 * @param[in] pPlatformRequestHandler *PlatformRequestHandler pointer
1228 * @param[in] id Identifier of counter to update
1229 * @param[in] value New value to set for the counter
1230 *
1231 * @return NV_OK Upon successful update
1232 * @return NV_ERR_INVALID_ARGUMENT Invalid counter id
1233 * @return NV_ERR_INVALID_REQUEST
1234 * Returned if the provided PlatformRequestHandler pointer was NULL or if the corresponding
1235 * OBJGPU object could not be found.
1236 */
1237 NV_STATUS
pfmreqhndlrUpdatePerfCounter(PlatformRequestHandler * pPlatformRequestHandler,NvU32 id,NvU32 value)1238 pfmreqhndlrUpdatePerfCounter
1239 (
1240 PlatformRequestHandler *pPlatformRequestHandler,
1241 NvU32 id,
1242 NvU32 value
1243 )
1244 {
1245 OBJGPU *pGpu = NULL;
1246 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData;
1247 NvU32 timeStamp;
1248
1249 // is the Id within range?
1250 if (id >= PFM_REQ_HNDLR_NUM_COUNTERS)
1251 {
1252 return NV_ERR_INVALID_ARGUMENT;
1253 }
1254
1255 if (NULL == pPlatformRequestHandler)
1256 {
1257 NV_ASSERT(pPlatformRequestHandler);
1258 return NV_ERR_INVALID_REQUEST;
1259 }
1260
1261 pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
1262 if (NULL == pGpu)
1263 {
1264 return NV_ERR_INVALID_REQUEST;
1265 }
1266 // determine the current ms timestamp.
1267 timeStamp = _pfmreqhndlrGetTimeStamp(pPlatformRequestHandler);
1268
1269 pPfmreqhndlrData = &(pPlatformRequestHandler->sensorData);
1270
1271 _pfmreqhndlrUpdateCounter(pPfmreqhndlrData, id, NV_TRUE, value, timeStamp);
1272
1273 return NV_OK;
1274 }
1275
1276 //
1277 // PfmreqhndlrSampleCounter
1278 //
1279 // This function determines if it is appropriate to update the specified counter & does so if it is.
1280 // Note that this function contains all the code specific to the sampling of each counter.
1281 //
1282 NV_STATUS
pfmreqhndlrSampleCounter(PlatformRequestHandler * pPlatformRequestHandler,NvU32 id,NvU32 timeStamp)1283 pfmreqhndlrSampleCounter
1284 (
1285 PlatformRequestHandler *pPlatformRequestHandler,
1286 NvU32 id,
1287 NvU32 timeStamp
1288 )
1289 {
1290 NV_STATUS status = NV_ERR_NOT_SUPPORTED;
1291 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData = &(pPlatformRequestHandler->sensorData);
1292 PFM_REQ_HNDLR_SENSOR_COUNTER *pCounter = &(pPfmreqhndlrData->PFMREQHNDLRSensorCache[id]);
1293 OBJGPU *pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
1294 NvBool bPM1Available = NV_TRUE;
1295
1296 NV_ASSERT_OR_RETURN(NULL != pPlatformRequestHandler, NV_ERR_INVALID_REQUEST);
1297
1298 if (0 == timeStamp)
1299 {
1300 timeStamp = _pfmreqhndlrGetTimeStamp(pPlatformRequestHandler);
1301 }
1302
1303 // check if we can sample the counter.
1304 // (marked available & can be sampled now.)
1305 if (pCounter->bSupported
1306 && (pCounter->bInvalid || ((timeStamp - pCounter->lastSampled) >= pCounter->minInterval)))
1307 {
1308 // Sample the requested counter.
1309 switch (id)
1310 {
1311 case PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_TGPU_SENSOR):
1312 case PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_PPMD_SENSOR):
1313 {
1314 status = _pfmreqhndlrSampleSensorLimit(pPlatformRequestHandler, id, timeStamp);
1315 break;
1316 }
1317 case PFM_REQ_HNDLR_PM1_STATE_AVAIL:
1318 {
1319 if (!pPlatformRequestHandler->controlData.bPM1ForcedOff)
1320 {
1321 if (pfmreqhndlrHandleCheckPM1Available(pPlatformRequestHandler, pGpu, &bPM1Available) == NV_OK)
1322 {
1323 _pfmreqhndlrUpdateCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_PM1_STATE_AVAIL, NV_TRUE, (NvU32)bPM1Available, timeStamp);
1324 status = NV_OK;
1325 }
1326 }
1327 //If PM1 is forced off or Boost Clocks not available
1328 else
1329 {
1330 status = NV_ERR_NOT_SUPPORTED;
1331 }
1332 break;
1333 }
1334 case PFM_REQ_HNDLR_VPS_PS20_SUPPORT:
1335 {
1336 _pfmreqhndlrUpdateCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_VPS_PS20_SUPPORT, NV_TRUE, pPlatformRequestHandler->vPstateCache.bVpsPs20Supported, timeStamp);
1337 break;
1338 }
1339 case PFM_REQ_HNDLR_TC_ENABLE:
1340 {
1341 _pfmreqhndlrUpdateCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_TC_ENABLE, NV_TRUE, NV_TRUE, timeStamp);
1342 break;
1343 }
1344 default:
1345 {
1346 break;
1347 }
1348 }
1349 }
1350 return status;
1351 }
1352
1353 /*!
1354 * @brief Retrieves the requested counter and returns it if available.
1355 *
1356 * @param[in] pPlatformRequestHandler *PlatformRequestHandler pointer
1357 * @param[in] counterId ID of the requested counter
1358 * @param[out] pCounterVal buffer to hold value of requested counter
1359 *
1360 * @return NV_ERR_INVALID_POINTER NULL pointer passed
1361 * @return NV_ERR_NOT_SUPPORTED various failures (TODO)
1362 * @return NV_ERR_INVALID_DATA counter is not available
1363 * @return NV_OK counter successfully retrieved
1364 */
1365 NV_STATUS
pfmreqhndlrGetPerfSensorCounterById_IMPL(PlatformRequestHandler * pPlatformRequestHandler,NvU16 counterId,NvU32 * pCounterVal)1366 pfmreqhndlrGetPerfSensorCounterById_IMPL
1367 (
1368 PlatformRequestHandler *pPlatformRequestHandler,
1369 NvU16 counterId,
1370 NvU32 *pCounterVal
1371 )
1372 {
1373 OBJSYS *pSys = SYS_GET_INSTANCE();
1374 OBJGPU *pGpu = NULL;
1375 OBJOS *pOs = NULL;
1376 PPFM_REQ_HNDLR_SENSOR_DATA pPfmreqhndlrData = &(pPlatformRequestHandler->sensorData);
1377 NV_STATUS status = NV_ERR_INVALID_DATA;
1378 NvU32 timeStamp;
1379
1380 NV_ASSERT_OR_RETURN(NULL != pCounterVal, NV_ERR_INVALID_POINTER);
1381 NV_ASSERT_OR_RETURN(NULL != pPlatformRequestHandler, NV_ERR_NOT_SUPPORTED);
1382
1383 *pCounterVal = 0;
1384
1385 pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
1386 if(pGpu == NULL){
1387 return NV_ERR_NOT_SUPPORTED;
1388 }
1389
1390 pOs = SYS_GET_OS(pSys);
1391 if(pOs == NULL){
1392 return NV_ERR_NOT_SUPPORTED;
1393 }
1394
1395 timeStamp = _pfmreqhndlrGetTimeStamp(pPlatformRequestHandler);
1396
1397 // Is the Id within range?
1398 if (counterId >= PFM_REQ_HNDLR_NUM_COUNTERS)
1399 {
1400 NV_PRINTF(LEVEL_ERROR,
1401 "Invalid counter Id specified = %d.\n",
1402 counterId);
1403 DBG_BREAKPOINT();
1404 status = NV_ERR_NOT_SUPPORTED;
1405 goto pfmreqhndlrGetPerfSensorCounterById_IMPL_exit;
1406 }
1407 // is the counter available?
1408 if ((!pPfmreqhndlrData->PFMREQHNDLRSensorCache[counterId].bSupported) &&
1409 (!pPfmreqhndlrData->PFMREQHNDLRSensorCache[counterId].bVolatile))
1410 {
1411 goto pfmreqhndlrGetPerfSensorCounterById_IMPL_exit;
1412 }
1413
1414 // Has the counter gone stale since the last sampling?
1415 if (_pfmreqhndlrIsCacheEntryStale(pPfmreqhndlrData, counterId, timeStamp))
1416 {
1417 // sample the counter
1418 if (PFM_REQ_HNDLR_IS_ACPI_VERSION_SW_2X(pPlatformRequestHandler))
1419 {
1420 // 2X path
1421 status = pfmreqhndlrSampleCounter(pPlatformRequestHandler, counterId, timeStamp);
1422 if (status != NV_OK)
1423 {
1424 if (status == NV_ERR_NOT_SUPPORTED)
1425 {
1426 // OK to sample unsupported counters (and fall through).
1427 status = NV_OK;
1428 }
1429 else
1430 {
1431 // Fail for any other error code (and bail)
1432 NV_PRINTF(LEVEL_ERROR,
1433 "Sampling counter failed for counter id = %d.\n",
1434 counterId);
1435 DBG_BREAKPOINT();
1436 goto pfmreqhndlrGetPerfSensorCounterById_IMPL_exit;
1437 }
1438 }
1439 }
1440 else
1441 {
1442 // 1X path
1443 pfmreqhndlrSampleCounter(pPlatformRequestHandler, counterId, timeStamp);
1444 }
1445 }
1446 //
1447 // NOTE per spec, some counters may be reported as available,
1448 // but may not be available under some conditions.
1449 // I.E. pshare params may report a counter as available when supported fields are queried,
1450 // but the limits are only available if the SBIOS wants that particular sensor limited.
1451 // so these sensors may be intermittently available.
1452 // to check for this case, check to see if the counter is still stale.
1453 //
1454 if (!_pfmreqhndlrIsCacheEntryStale(pPfmreqhndlrData, counterId, timeStamp) &&
1455 !pPfmreqhndlrData->PFMREQHNDLRSensorCache[counterId].bInvalid)
1456 {
1457 // the counter is not stale,
1458 // copy it to the output
1459 *pCounterVal = pPfmreqhndlrData->PFMREQHNDLRSensorCache[counterId].value;
1460 status = NV_OK;
1461 goto pfmreqhndlrGetPerfSensorCounterById_IMPL_exit;
1462 }
1463
1464 pfmreqhndlrGetPerfSensorCounterById_IMPL_exit:
1465 return status;
1466 }
1467
1468 NV_STATUS
pfmreqhndlrHandleStatusChangeEvent(PlatformRequestHandler * pPlatformRequestHandler,OBJGPU * pGpu)1469 pfmreqhndlrHandleStatusChangeEvent
1470 (
1471 PlatformRequestHandler *pPlatformRequestHandler,
1472 OBJGPU *pGpu
1473 )
1474 {
1475 NV_STATUS status = NV_OK;
1476 NvU32 data = 0;
1477 NvBool bIsPctrlSupported = NV_TRUE;
1478
1479 NV_ASSERT_OR_RETURN(NULL != pPlatformRequestHandler, NV_ERR_INVALID_REQUEST);
1480
1481 // get the latest pshare status
1482 status = _pfmreqhndlrCallPshareStatus(pPlatformRequestHandler, NV_FALSE);
1483 if (status != NV_OK)
1484 {
1485 NV_ASSERT_OK_FAILED("PshareStatus", status);
1486 }
1487
1488 if (PFM_REQ_HNDLR_IS_ACPI_VERSION_SW_2X(pPlatformRequestHandler))
1489 {
1490 // Additionally if PCONTROL subfunction is supported call it
1491 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS acpiParams;
1492
1493 portMemSet((void *) &acpiParams, 0, sizeof(NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS));
1494 acpiParams.ctrl.cmd = NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_SUPPORT;
1495 acpiParams.ctrl.input = 0;
1496 acpiParams.output.pBuffer = NULL;
1497 acpiParams.output.bufferSz = 0;
1498 status = pfmreqhndlrCallACPI(pGpu, &acpiParams);
1499 if (status != NV_OK)
1500 {
1501 NV_ASSERT_OK_FAILED("supported subfunction", status);
1502 goto pfmreqhndlrHandleStatusChangeEvent_exit;
1503 }
1504 if (0 == (DRF_VAL(0000_CTRL_PFM_REQ_HNDLR, _SUPPORTED, _PCONTROL_AVAIL, acpiParams.output.result[1])))
1505 {
1506 // PCONTTOL is not supported on 2X, can be hard coded
1507 bIsPctrlSupported = NV_FALSE;
1508 }
1509 }
1510
1511 if (bIsPctrlSupported)
1512 {
1513 status = pfmreqhndlrPcontrol(pPlatformRequestHandler, data, NV_TRUE);
1514 if (status != NV_OK)
1515 {
1516 NV_ASSERT_FAILED("Pcontrol command");
1517 goto pfmreqhndlrHandleStatusChangeEvent_exit;
1518 }
1519 }
1520
1521 pfmreqhndlrHandleStatusChangeEvent_exit:
1522 return status;
1523 }
1524
1525 /*!
1526 * Helper routine to check PM1 Available Status
1527 *
1528 * @param[in] pPlatformRequestHandler *PlatformRequestHandler object pointer
1529 * @param[in] pGpu GPU object pointer
1530 * @param[out] bIsPm1Available Status of PM1 Availability
1531 *
1532 * @return NV_OK if RMAPI call was succesful.
1533 * @return bubble up errors from called RMAPI
1534 */
1535
1536 NV_STATUS
pfmreqhndlrHandleCheckPM1Available_IMPL(PlatformRequestHandler * pPlatformRequestHandler,OBJGPU * pGpu,NvBool * pbPM1Available)1537 pfmreqhndlrHandleCheckPM1Available_IMPL
1538 (
1539 PlatformRequestHandler *pPlatformRequestHandler,
1540 OBJGPU *pGpu,
1541 NvBool *pbPM1Available
1542 )
1543 {
1544 NV_STATUS status = NV_ERR_GENERIC;
1545 NV2080_CTRL_CMD_INTERNAL_PERF_PFM_REQ_HNDLR_GET_PM1_STATE_PARAMS params = { 0 };
1546 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
1547
1548 params.flag = NV2080_CTRL_INTERNAL_PFM_REQ_HNDLR_GET_PM1_STATUS;
1549
1550 status = pRmApi->Control(pRmApi,
1551 pGpu->hInternalClient,
1552 pGpu->hInternalSubdevice,
1553 NV2080_CTRL_CMD_INTERNAL_PERF_PFM_REQ_HNDLR_GET_PM1_STATE,
1554 ¶ms,
1555 sizeof(params));
1556
1557 if (status == NV_OK)
1558 {
1559 *pbPM1Available = params.bStatus;
1560 }
1561
1562 return status;
1563 }
1564
1565 /*!
1566 * Handler routine to Update or Reset EDPpeak limit of GPU
1567 *
1568 * @param[in] pPlatformRequestHandler *PlatformRequestHandler object pointer
1569 * @param[in] pGpu GPU object pointer
1570 * @param[in] bEnable Enable or Reset the settings.
1571 *
1572 * @return NV_OK if the update was successful.
1573 * @return NV_ERR_NOT_SUPPORTED if the POR support is not present
1574 * @return NV_ERR_INVALID_STATE for invalid PMU state
1575 * @return bubble up errors triggered by called code
1576 */
1577 NV_STATUS
pfmreqhndlrHandleEdppeakLimitUpdate_IMPL(PlatformRequestHandler * pPlatformRequestHandler,OBJGPU * pGpu,NvBool bEnable)1578 pfmreqhndlrHandleEdppeakLimitUpdate_IMPL
1579 (
1580 PlatformRequestHandler *pPlatformRequestHandler,
1581 OBJGPU *pGpu,
1582 NvBool bEnable
1583 )
1584 {
1585 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
1586 NV_STATUS status = NV_OK;
1587
1588 if (gpuIsGpuFullPower(pGpu))
1589 {
1590 NV2080_CTRL_CMD_INTERNAL_PMGR_PFM_REQ_HNDLR_UPDATE_EDPP_LIMIT_PARAMS params = { 0 };
1591
1592 params.bEnable = bEnable;
1593 status = pRmApi->Control(pRmApi,
1594 pGpu->hInternalClient,
1595 pGpu->hInternalSubdevice,
1596 NV2080_CTRL_CMD_INTERNAL_PMGR_PFM_REQ_HNDLR_UPDATE_EDPP_LIMIT,
1597 ¶ms,
1598 sizeof(params));
1599
1600 if (status != NV_OK)
1601 {
1602 NV_PRINTF(LEVEL_ERROR, "Error updating EDPpeak Limit State: 0x%08x\n", status);
1603 DBG_BREAKPOINT();
1604 }
1605 else
1606 {
1607 // Update the cached enable bit, if everything went well
1608 pPlatformRequestHandler->controlData.bEDPpeakUpdateEnabled = bEnable;
1609 }
1610 }
1611
1612 return status;
1613 }
1614
1615 /*!
1616 * Handler routine to Update or Reset EDPpeak limit from platform
1617 *
1618 * @param[in] pPlatformRequestHandler PlatformRequestHandler object pointer
1619 * @param[in] pGpu GPU object pointer
1620 * @param[in] platformEdppLimit Platform EDPpeak limit value
1621 *
1622 * @return NV_OK if the update was successful.
1623 * @return NV_ERR_NOT_SUPPORTED if the POR support is not present
1624 * @return NV_ERR_INVALID_STATE for invalid PMU state
1625 * @return bubble up errors triggered by called code
1626 */
1627 NV_STATUS
pfmreqhndlrHandlePlatformEdppLimitUpdate_IMPL(PlatformRequestHandler * pPlatformRequestHandler,OBJGPU * pGpu,NvU32 platformEdppLimit)1628 pfmreqhndlrHandlePlatformEdppLimitUpdate_IMPL
1629 (
1630 PlatformRequestHandler *pPlatformRequestHandler,
1631 OBJGPU *pGpu,
1632 NvU32 platformEdppLimit
1633 )
1634 {
1635 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
1636 NV_STATUS status = NV_OK;
1637
1638 if (gpuIsGpuFullPower(pGpu))
1639 {
1640 NV2080_CTRL_CMD_INTERNAL_PMGR_PFM_REQ_HNDLR_UPDATE_EDPP_LIMIT_PARAMS params = { 0 };
1641
1642 params.clientLimit = platformEdppLimit;
1643 params.bEnable = NV_TRUE;
1644
1645 // Platform can remove its EDPp and fall back to GPU default by setting a limit of value 0
1646 if (platformEdppLimit == 0)
1647 {
1648 params.bEnable = NV_FALSE;
1649 }
1650 status = pRmApi->Control(pRmApi,
1651 pGpu->hInternalClient,
1652 pGpu->hInternalSubdevice,
1653 NV2080_CTRL_CMD_INTERNAL_PMGR_PFM_REQ_HNDLR_UPDATE_EDPP_LIMIT,
1654 ¶ms,
1655 sizeof(params));
1656 if (status != NV_OK)
1657 {
1658 NV_PRINTF(LEVEL_ERROR, "Error updating EDPpeak Limit State: 0x%08x\n", status);
1659 DBG_BREAKPOINT();
1660 }
1661 }
1662
1663 return status;
1664 }
1665
1666 /*!
1667 * Handle EDPpeak new limit query from platform
1668 *
1669 * @param[in] pPlatformRequestHandler PlatformRequestHandler object pointer
1670 * @param[in] pGpu GPU object pointer
1671 * @param[in] pPlatformEdppLimit Pointer to Platform EDPpeak limit value
1672 *
1673 * @return NV_OK if the update was successful.
1674 * @return NV_ERR_NOT_SUPPORTED if the POR support is not present
1675 * @return bubble up errors triggered by called code
1676 */
1677 NV_STATUS
pfmreqhndlrHandlePlatformGetEdppLimit_IMPL(PlatformRequestHandler * pPlatformRequestHandler,OBJGPU * pGpu,NvU32 * pPlatformEdppLimit)1678 pfmreqhndlrHandlePlatformGetEdppLimit_IMPL
1679 (
1680 PlatformRequestHandler *pPlatformRequestHandler,
1681 OBJGPU *pGpu,
1682 NvU32 *pPlatformEdppLimit
1683 )
1684 {
1685 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS acpiParams;
1686 NV_STATUS status = NV_OK;
1687
1688 portMemSet((void*)&acpiParams, 0, sizeof(NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS));
1689
1690 acpiParams.ctrl.cmd = NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_GETEDPPLIMIT;
1691
1692 // Input is V1
1693 acpiParams.ctrl.input = NV0000_CTRL_PFM_REQ_HNDLR_EDPP_VERSION_V10;
1694 status = pfmreqhndlrCallACPI(pGpu, &acpiParams);
1695 if (status != NV_OK)
1696 {
1697 NV_PRINTF(LEVEL_ERROR, "Error querying EDPpeak Limit from platform: 0x%08x\n", status);
1698 DBG_BREAKPOINT();
1699 status = NV_ERR_NOT_SUPPORTED;
1700 goto _pfmreqhndlrHandlePlatformGetEdppLimit_IMPL_IMPL_exit;
1701 }
1702
1703 *pPlatformEdppLimit = acpiParams.output.result[0];
1704
1705 _pfmreqhndlrHandlePlatformGetEdppLimit_IMPL_IMPL_exit:
1706 return status;
1707 }
1708
1709 /*!
1710 * Handle send GPU EDPpeak limit info to platform
1711 *
1712 * @param[in] pPlatformRequestHandler PlatformRequestHandler object pointer
1713 * @param[in] pGpu GPU object pointer
1714 *
1715 * @return NV_OK if the update was successful.
1716 * @return bubble up errors triggered by called code
1717 */
1718 NV_STATUS
pfmreqhndlrHandlePlatformSetEdppLimitInfo_IMPL(PlatformRequestHandler * pPlatformRequestHandler,OBJGPU * pGpu)1719 pfmreqhndlrHandlePlatformSetEdppLimitInfo_IMPL
1720 (
1721 PlatformRequestHandler *pPlatformRequestHandler,
1722 OBJGPU *pGpu
1723 )
1724 {
1725
1726 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
1727 NV_STATUS status = NV_OK;
1728 PFM_REQ_HNDLR_EDPP_DATA *pEdppLimit =
1729 &pPlatformRequestHandler->controlData.edppLimit;
1730
1731 if (gpuIsGpuFullPower(pGpu))
1732 {
1733 NV2080_CTRL_CMD_INTERNAL_PMGR_PFM_REQ_HNDLR_GET_EDPP_LIMIT_INFO_PARAMS params = { 0 };
1734
1735 status = pRmApi->Control(pRmApi,
1736 pGpu->hInternalClient,
1737 pGpu->hInternalSubdevice,
1738 NV2080_CTRL_CMD_INTERNAL_PMGR_PFM_REQ_HNDLR_GET_EDPP_LIMIT_INFO,
1739 ¶ms,
1740 sizeof(params));
1741 if (status == NV_OK)
1742 {
1743 pEdppLimit->edppLimitInfo.limitMin = params.limitMin;
1744 pEdppLimit->edppLimitInfo.limitRated = params.limitRated;
1745 pEdppLimit->edppLimitInfo.limitMax = params.limitMax;
1746 pEdppLimit->edppLimitInfo.limitCurr = params.limitCurr;
1747 pEdppLimit->edppLimitInfo.limitBattRated = params.limitBattRated;
1748 pEdppLimit->edppLimitInfo.limitBattMax = params.limitBattMax;
1749 pEdppLimit->edppLimitInfo.rsvd = 0;
1750 pEdppLimit->status = NV_OK;
1751 }
1752 else
1753 {
1754 pEdppLimit->status = NV_ERR_INVALID_ARGUMENT;
1755 }
1756 }
1757 else
1758 {
1759 pEdppLimit->status = NV_ERR_GPU_NOT_FULL_POWER;
1760 }
1761
1762 if (!pEdppLimit->bWorkItemPending)
1763 {
1764 // Queue workitem to send the EDP limit info to platform
1765 status = osQueueWorkItem(pGpu,
1766 _pfmreqhndlrHandlePlatformSetEdppLimitInfoWorkItem, NULL);
1767 if(status == NV_OK)
1768 {
1769 pEdppLimit->bWorkItemPending = NV_TRUE;
1770 }
1771 }
1772
1773 return status;
1774 }
1775
1776 /*!
1777 * Handler routine to enable or Reset GPU User Configurable TGP mode
1778 *
1779 * @param[in] pPlatformRequestHandler *PlatformRequestHandler object pointer
1780 * @param[in] pGpu GPU object pointer
1781 * @param[in] bEnable Enable or Reset the settings.
1782 *
1783 * @return NV_OK if the update was successful.
1784 * @return NV_ERR_NOT_SUPPORTED if the POR support is not present
1785 * @return NV_ERR_INVALID_STATE for invalid PMU state
1786 * @return bubble up errors triggered by called code
1787 */
1788 NV_STATUS
pfmreqhndlrHandleUserConfigurableTgpMode_IMPL(PlatformRequestHandler * pPlatformRequestHandler,OBJGPU * pGpu,NvBool bEnable)1789 pfmreqhndlrHandleUserConfigurableTgpMode_IMPL
1790 (
1791 PlatformRequestHandler *pPlatformRequestHandler,
1792 OBJGPU *pGpu,
1793 NvBool bEnable
1794 )
1795 {
1796 NV_STATUS status = NV_ERR_GENERIC;
1797 NV2080_CTRL_CMD_INTERNAL_PMGR_PFM_REQ_HNDLR_CONFIGURE_TGP_MODE_PARAMS params = { 0 };
1798 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
1799
1800 params.bEnable = bEnable;
1801
1802 status = pRmApi->Control(pRmApi,
1803 pGpu->hInternalClient,
1804 pGpu->hInternalSubdevice,
1805 NV2080_CTRL_CMD_INTERNAL_PMGR_PFM_REQ_HNDLR_CONFIGURE_TGP_MODE,
1806 ¶ms,
1807 sizeof(params));
1808 if (status == NV_OK)
1809 {
1810 // Update the cached enable bit, if everything went well
1811 pPlatformRequestHandler->controlData.bUserConfigTGPmodeEnabled = bEnable;
1812 }
1813
1814 return status;
1815 }
1816
1817 /* ---------------------- Static Functions --------------------------------- */
1818
1819 static NV_STATUS
_handleCmdSystemPfmreqhndlrGetSupportedFunctions(PlatformRequestHandler * pPlatformRequestHandler,NvU16 locale,NvU32 * pData)1820 _handleCmdSystemPfmreqhndlrGetSupportedFunctions
1821 (
1822 PlatformRequestHandler
1823 *pPlatformRequestHandler,
1824 NvU16 locale,
1825 NvU32 *pData
1826 )
1827 {
1828 OBJGPU* pGpu = NULL;
1829
1830 *pData = 0;
1831
1832
1833 if (locale != NV0000_CTRL_CMD_SYSTEM_PFM_REQ_HNDLR_LOCALE_SYSTEM)
1834 {
1835 return NV_ERR_INVALID_COMMAND;
1836 }
1837
1838 pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
1839 if (pGpu == NULL)
1840 {
1841 return NV_ERR_INVALID_STATE;
1842 }
1843
1844 *pData |= (NV_OK == testIfDsmSubFunctionEnabled(pGpu, pPlatformRequestHandler->dsmVersion,
1845 NV_ACPI_ALL_FUNC_SUPPORT)) ?
1846 NV0000_CTRL_CMD_SYSTEM_PFM_REQ_HNDLR_SYS_DEF_FUNC_SUPPORT : 0;
1847
1848 return NV_OK;
1849 }
1850
1851 static NV_STATUS
_handleCmdSystemPfmreqhndlrDataInitUsingSbiosAndAck(PlatformRequestHandler * pPlatformRequestHandler,NvU16 locale,NvU32 * pData)1852 _handleCmdSystemPfmreqhndlrDataInitUsingSbiosAndAck
1853 (
1854 PlatformRequestHandler
1855 *pPlatformRequestHandler,
1856 NvU16 locale,
1857 NvU32 *pData
1858 )
1859 {
1860 OBJGPU *pGpu;
1861 NV_STATUS status = NV_OK;
1862
1863 if (locale != NV0000_CTRL_CMD_SYSTEM_PFM_REQ_HNDLR_LOCALE_SYSTEM)
1864 {
1865 return NV_ERR_INVALID_COMMAND;
1866 }
1867
1868 pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
1869
1870 /* Full GPU check to ensure device is on */
1871 NV_ASSERT_OR_RETURN(FULL_GPU_SANITY_CHECK(pGpu), NV_ERR_INVALID_STATE);
1872
1873 if (pPlatformRequestHandler->getProperty(pPlatformRequestHandler, PDB_PROP_PFMREQHNDLR_SUPPORTED))
1874 {
1875 status = pfmreqhndlrHandleStatusChangeEvent(pPlatformRequestHandler, pGpu);
1876 }
1877 else
1878 {
1879 status = NV_ERR_NOT_SUPPORTED;
1880 }
1881
1882 return status;
1883 }
1884
1885 /*!
1886 * Get a current 32 bit timestamp in MS
1887 *
1888 * @param[in] pPlatformRequestHandler *PlatformRequestHandler pointer
1889 *
1890 * @return 32 bit MS timestamp.
1891 */
1892 static NvU32
_pfmreqhndlrGetTimeStamp(PlatformRequestHandler * pPlatformRequestHandler)1893 _pfmreqhndlrGetTimeStamp
1894 (
1895 PlatformRequestHandler *pPlatformRequestHandler
1896 )
1897 {
1898 OBJGPU *pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
1899 OBJTMR *pTmr = GPU_GET_TIMER(pGpu);
1900 NvU32 timeStamp = 0;
1901
1902 timeStamp = (NvU32)(tmrGetTime_HAL(pGpu, pTmr) / 1000000L);
1903
1904 return timeStamp;
1905 }
1906
1907 /*!
1908 * Configure a counter with an override value.
1909 *
1910 * @param[in] pPfmreqhndlrData pointer to the PlatformRequestHandler data structure
1911 * @param[in] id identifier of counter to whose Override should be canceled.
1912 * @param[in] value new value for the specified counter. All values are accepted as
1913 * unsigned integers, but internally they should be formatted based on the
1914 * type of id/sensor they correspond to.
1915 * @param[in] timeStamp current time stamp in MS used to indicate when the counter was last updated
1916 *
1917 */
1918 static void
_pfmreqhndlrOverrideCounter(PFM_REQ_HNDLR_SENSOR_DATA * pPfmreqhndlrData,NvU32 id,NvU32 value,NvU32 timeStamp)1919 _pfmreqhndlrOverrideCounter
1920 (
1921 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData,
1922 NvU32 id,
1923 NvU32 value,
1924 NvU32 timeStamp
1925 )
1926 {
1927 // update the counter with the new value.
1928 _pfmreqhndlrUpdateCounter(pPfmreqhndlrData, id, NV_TRUE, value, timeStamp);
1929
1930 // lock it in as an overriden value.
1931 pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].bOverridden = NV_TRUE;
1932 }
1933
1934 /*!
1935 * Cancel an override of a specified counter.
1936 *
1937 * @param[in] pPfmreqhndlrData pointer to the PlatformRequestHandler data structure
1938 * @param[in] id Identifier of counter to whose Override should be canceled.
1939 * @param[in] timeStamp current time stamp in MSused to indicate when the caounter was last updated
1940 *
1941 * @note if a non-volatile counter has its override canceled, it may not be refreshed as part of a query,
1942 * it is up to the calling function to ensure that the counter is placed in a valid (I.E. updated) state.
1943 */
1944 static void
_pfmreqhndlrCancelCounterOverride(PFM_REQ_HNDLR_SENSOR_DATA * pPfmreqhndlrData,NvU32 id,NvU32 timeStamp)1945 _pfmreqhndlrCancelCounterOverride
1946 (
1947 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData,
1948 NvU32 id,
1949 NvU32 timeStamp
1950 )
1951 {
1952 if (pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].bOverridden)
1953 {
1954 pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].bOverridden = NV_FALSE;
1955 _pfmreqhndlrResetCounter(pPfmreqhndlrData, id, timeStamp);
1956 }
1957 }
1958
1959 /*!
1960 * place the counter into a reset state where it does not contain a valid value, and the sample is expired.
1961 * it updates the counter so that the value is marked as invalid & the timestamp
1962 * is set so that the counter can be updated
1963 *
1964 * @param[in] pPfmreqhndlrData Pointer to the PlatformRequestHandler data structure
1965 * @param[in] id Identifier of counter to which should be marked invalid.
1966 *
1967 * @note if a non-volatile counter is marked as invalid, it may not be refreshed as part of a query,
1968 * it is up to the calling function to ensure that the counter is placed in a valid (I.E. updated) state.
1969 */
1970 static void
_pfmreqhndlrResetCounter(PFM_REQ_HNDLR_SENSOR_DATA * pPfmreqhndlrData,NvU32 id,NvU32 timeStamp)1971 _pfmreqhndlrResetCounter
1972 (
1973 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData,
1974 NvU32 id,
1975 NvU32 timeStamp
1976 )
1977 {
1978 if (!pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].bOverridden)
1979 {
1980 pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].bInvalid = NV_TRUE;
1981
1982 // use a timestamp that marks the value as stale in order to ensure that
1983 // volatile counters are refreshed prior to being reported.
1984 pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].lastSampled = timeStamp - NV_MAX(pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].minInterval, pPfmreqhndlrData->counterHoldPeriod) - 1;
1985 }
1986 }
1987
1988 /*!
1989 * Update a counter to a specified state (valid/invalid) & value.
1990 * it updates the specified counter based on the result of the sampling
1991 * (as reported in bValid) and the value provided.
1992 *
1993 * @param[in] pPfmreqhndlrData pointer to the PlatformRequestHandler data structure
1994 * @param[in] id identifier of counter to be updated.
1995 * @param[in] bValid a bool indicating a valid value is being provided for the counter.
1996 * @param[in] value new value for the specified counter. All values are accepted as
1997 * unsigned integers, but internally they should be formatted based on the
1998 * type of id/sensor they correspond to.
1999 * @param[in] timeStamp current time stamp in MS used to indicate when the counter was last updated
2000 *
2001 */
2002 static void
_pfmreqhndlrUpdateCounter(PFM_REQ_HNDLR_SENSOR_DATA * pPfmreqhndlrData,NvU32 id,NvBool bValid,NvU32 value,NvU32 timeStamp)2003 _pfmreqhndlrUpdateCounter
2004 (
2005 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData,
2006 NvU32 id,
2007 NvBool bValid,
2008 NvU32 value,
2009 NvU32 timeStamp
2010 )
2011 {
2012 if (bValid || pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].bOverridden)
2013 {
2014 // only update the value if the current value is not an override.
2015 if (!pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].bOverridden)
2016 {
2017 pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].value = value;
2018 }
2019 pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].lastSampled = timeStamp;
2020 pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].bInvalid = NV_FALSE;
2021 }
2022 else
2023 {
2024 // The counter is not valid or overridden, mark it as invalid.
2025 pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].bInvalid = NV_TRUE;
2026 }
2027 }
2028
2029 /*!
2030 * Enables/disables PM1 (boost clocks).
2031 *
2032 * @param[in] pGpu OBJGPU pointer
2033 * @param[in] bEnable Boolean value to turn on/off PM1 (boost clocks)
2034 *
2035 * @return NV_OK PM1 (boost clocks) successfully enabled/disabled
2036 * @return NV_ERR_NOT_SUPPORTED PM1 (boost clocks) not supported
2037 * @return NV_ERR_INVALID_STATE Could not enable/disable PM1
2038 */
2039 static NV_STATUS
_pfmreqhndlrEnablePM1(OBJGPU * pGpu,NvBool bEnable)2040 _pfmreqhndlrEnablePM1
2041 (
2042 OBJGPU *pGpu,
2043 NvBool bEnable
2044 )
2045 {
2046 NV2080_CTRL_CMD_INTERNAL_PERF_PFM_REQ_HNDLR_SET_PM1_STATE_PARAMS params = { 0 };
2047 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
2048
2049 params.bEnable = bEnable;
2050
2051 return pRmApi->Control(pRmApi,
2052 pGpu->hInternalClient,
2053 pGpu->hInternalSubdevice,
2054 NV2080_CTRL_CMD_INTERNAL_PERF_PFM_REQ_HNDLR_SET_PM1_STATE,
2055 ¶ms,
2056 sizeof(params));
2057 }
2058
2059 /*!
2060 * Sample and update the Platform Power Mode data.
2061 *
2062 * @param[in] pPlatformRequestHandler *PlatformRequestHandler object poiner
2063 * @param[in] pGpu OBJGPU object pointer
2064 * @param[in] If called from PlatformRequestHandler init sequence
2065 *
2066 * @return NV_OK on success
2067 * @return Bubble up error otherwise
2068 */
2069
2070 static NV_STATUS
_pfmreqhndlrUpdatePpmdLimit(PlatformRequestHandler * pPlatformRequestHandler,OBJGPU * pGpu,NvBool bInit)2071 _pfmreqhndlrUpdatePpmdLimit
2072 (
2073 PlatformRequestHandler *pPlatformRequestHandler,
2074 OBJGPU *pGpu,
2075 NvBool bInit
2076 )
2077 {
2078 NV_STATUS status = NV_OK;
2079 PFM_REQ_HNDLR_PPM_DATA *pPpmData = NULL;
2080 NvU32 counterVal = 0;
2081 NV2080_PLATFORM_POWER_MODE_CHANGE_STATUS params = { 0 };
2082 NvU32 info32 = 0;
2083
2084 status = pfmreqhndlrGetPerfSensorCounterById(pPlatformRequestHandler,
2085 PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_PPMD_SENSOR),
2086 &counterVal);
2087 if (status != NV_OK)
2088 {
2089 NV_ASSERT_OK_FAILED("PlatformRequestHandler failed to get platform power mode from SBIOS", status);
2090 goto _pfmreqhndlrUpdatePpmdLimit_exit;
2091 }
2092
2093 if (PFM_REQ_HNDLR_IS_COUNTER_VALID(pPlatformRequestHandler, PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_PPMD_SENSOR)))
2094 {
2095 pPpmData = &(pPlatformRequestHandler->ppmData);
2096
2097 // Update the power mode mask as received from the platform
2098 pPpmData->ppmMaskCurrent =
2099 DRF_VAL(0000_CTRL_PFM_REQ_HNDLR, _PPM, _MASK, counterVal);
2100
2101 //
2102 // Cache the platform requested power mode during init time only.
2103 // Runtime, the system request should result in a client notification only.
2104 //
2105 if (bInit)
2106 {
2107 pPpmData->ppmIdxCurrent =
2108 DRF_VAL(0000_CTRL_PFM_REQ_HNDLR, _PPM, _INDEX, counterVal);
2109 }
2110
2111 // Notify clients with the new limits
2112 params.platformPowerModeIndex = DRF_VAL(0000_CTRL_PFM_REQ_HNDLR, _PPM, _INDEX, counterVal);
2113 params.platformPowerModeMask = pPpmData->ppmMaskCurrent;
2114 params.eventReason = NV2080_PLATFORM_POWER_MODE_CHANGE_ACPI_NOTIFICATION;
2115
2116 info32 = (params.platformPowerModeIndex << DRF_SHIFT(NV2080_PLATFORM_POWER_MODE_CHANGE_INFO_INDEX)) |
2117 (params.platformPowerModeMask << DRF_SHIFT(NV2080_PLATFORM_POWER_MODE_CHANGE_INFO_MASK)) |
2118 (params.eventReason << DRF_SHIFT(NV2080_PLATFORM_POWER_MODE_CHANGE_INFO_REASON));
2119
2120 gpuNotifySubDeviceEvent(pGpu, NV2080_NOTIFIERS_PLATFORM_POWER_MODE_CHANGE, ¶ms, sizeof(params), info32, 0);
2121 }
2122
2123 _pfmreqhndlrUpdatePpmdLimit_exit:
2124 return status;
2125 }
2126
2127 static NV_STATUS
_pfmreqhndlrUpdateTgpuLimit(PlatformRequestHandler * pPlatformRequestHandler,OBJGPU * pGpu)2128 _pfmreqhndlrUpdateTgpuLimit
2129 (
2130 PlatformRequestHandler *pPlatformRequestHandler,
2131 OBJGPU *pGpu
2132 )
2133 {
2134 NvU32 counterVal;
2135 NvTemp targetTemp = PFM_REQ_HNDLR_TEMP_0_C;
2136 NV_STATUS status = NV_ERR_NOT_SUPPORTED;
2137 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
2138
2139 // note -- we need to go through the call to ensure any override is honored.
2140 status = pfmreqhndlrGetPerfSensorCounterById(pPlatformRequestHandler,
2141 PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_TGPU_SENSOR),
2142 &counterVal);
2143
2144 if (status != NV_OK)
2145 {
2146 NV_ASSERT_OK_FAILED("PlatformRequestHandler failed to get target temp from SBIOS", status);
2147 return status;
2148 }
2149
2150 targetTemp = NV_TYPES_CELSIUS_TO_NV_TEMP(counterVal);
2151
2152 // 2x operation
2153 if (PFM_REQ_HNDLR_IS_ACPI_VERSION_SW_2X(pPlatformRequestHandler))
2154 {
2155 // 2X operation Will not allow a 0C default value from SBIOS to SWTC interface
2156 if (targetTemp == PFM_REQ_HNDLR_TEMP_0_C)
2157 {
2158 // The VBIOS default limit takes effect
2159 status = NV_OK;
2160 return status;
2161 }
2162 }
2163
2164
2165 NV2080_CTRL_CMD_INTERNAL_THERM_PFM_REQ_HNDLR_UPDATE_TGPU_LIMIT_PARAMS params = { 0 };
2166 params.targetTemp = targetTemp;
2167
2168 status = pRmApi->Control(pRmApi,
2169 pGpu->hInternalClient,
2170 pGpu->hInternalSubdevice,
2171 NV2080_CTRL_CMD_INTERNAL_THERM_PFM_REQ_HNDLR_UPDATE_TGPU_LIMIT,
2172 ¶ms,
2173 sizeof(params));
2174
2175 return status;
2176 }
2177
2178 /*!
2179 * @brief helper function to update each system control parameter.
2180 *
2181 * @param[in] pPlatformRequestHandler *PlatformRequestHandler pointer
2182 * @param[in] id Identifier of counter to update
2183 */
2184 static NV_STATUS
_pfmreqhndlrUpdateSystemParamLimit(PlatformRequestHandler * pPlatformRequestHandler,NvU32 id)2185 _pfmreqhndlrUpdateSystemParamLimit(PlatformRequestHandler *pPlatformRequestHandler, NvU32 id)
2186 {
2187 NV_STATUS status;
2188 OBJGPU *pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
2189
2190 switch (id)
2191 {
2192 case PFM_REQ_HNDLR_TGPU_SENSOR:
2193 {
2194 status = _pfmreqhndlrUpdateTgpuLimit(pPlatformRequestHandler, pGpu);
2195 break;
2196 }
2197 default:
2198 {
2199 status = NV_ERR_NOT_SUPPORTED;
2200 break;
2201 }
2202 }
2203
2204 return status;
2205 }
2206
2207 /*!
2208 * @brief passive worker thread to platform power mode.
2209 *
2210 * @param[in] gpuInstance GPU instance ID
2211 * @param[in] newIndex requested Platform Power Mode Index
2212 */
2213 static void
_pfmreqhndlrUpdatePlatformPowerModeWorkItem(NvU32 gpuInstance,void * pParams)2214 _pfmreqhndlrUpdatePlatformPowerModeWorkItem
2215 (
2216 NvU32 gpuInstance,
2217 void *pParams
2218 )
2219 {
2220 OBJSYS *pSys = SYS_GET_INSTANCE();
2221 PlatformRequestHandler *pPlatformRequestHandler = SYS_GET_PFM_REQ_HNDLR(pSys);
2222 OBJGPU *pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
2223 NvU32 status = NV_OK;
2224 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS_EX acpiParamsEx = {0};
2225 NvU32 gpuLockFlag = GPUS_LOCK_FLAGS_NONE;
2226
2227 if (FULL_GPU_SANITY_CHECK(pGpu))
2228 {
2229 // Attempt to acquire locks/semaphore
2230 if (pfmreqhndlrPassiveModeTransition(NV_TRUE, API_LOCK_FLAGS_NONE,
2231 gpuLockFlag) != NV_OK)
2232 {
2233 NV_PRINTF(LEVEL_ERROR, "Failed to acquire the locks/semaphore!\n");
2234 goto pfmreqhndlrUpdatePlatformPowerModeWorkItemExit;
2235 }
2236
2237 // Call ACPI to set the new platform power mode
2238 acpiParamsEx.inSize = NV0000_CTRL_PFM_REQ_HNDLR_PPM_ARGS_COUNT * sizeof(NvU32);
2239 acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_PPM_ARGS_VERSION_IDX] =
2240 FLD_SET_DRF(0000_CTRL_PFM_REQ_HNDLR, _PPM_ARG0_VERSION, _MAJOR, _V1,
2241 acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_PPM_ARGS_VERSION_IDX]);
2242 acpiParamsEx.outSize = NV0000_CTRL_PFM_REQ_HNDLR_PPM_ARGS_COUNT * sizeof(NvU32);
2243 acpiParamsEx.pfmreqhndlrFunc = GPS_FUNC_SETPPM;
2244 acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_PPM_ARGS_IDX] =
2245 FLD_SET_DRF_NUM(0000_CTRL_PFM_REQ_HNDLR, _PPM_ARGS, _INDEX,
2246 pPlatformRequestHandler->ppmData.ppmIdxRequested, acpiParamsEx.input[NV0000_CTRL_PFM_REQ_HNDLR_PPM_ARGS_IDX]);
2247
2248 status = pfmreqhndlrCallACPI_EX(pGpu, &acpiParamsEx);
2249
2250 //
2251 // If ACPI call is successful, cache the new Index for future Get PPM calls
2252 // and notify NvCPL
2253 //
2254 if (NV_OK == status)
2255 {
2256 NV2080_PLATFORM_POWER_MODE_CHANGE_STATUS params = {0};
2257 NvU32 info32 = 0;
2258 pPlatformRequestHandler->ppmData.ppmIdxCurrent = pPlatformRequestHandler->ppmData.ppmIdxRequested;
2259 params.platformPowerModeIndex = pPlatformRequestHandler->ppmData.ppmIdxCurrent;
2260 params.platformPowerModeMask = pPlatformRequestHandler->ppmData.ppmMaskCurrent;
2261 params.eventReason = NV2080_PLATFORM_POWER_MODE_CHANGE_COMPLETION;
2262
2263 info32 = (params.platformPowerModeIndex << DRF_SHIFT(NV2080_PLATFORM_POWER_MODE_CHANGE_INFO_INDEX)) |
2264 (params.platformPowerModeMask << DRF_SHIFT(NV2080_PLATFORM_POWER_MODE_CHANGE_INFO_MASK)) |
2265 (params.eventReason << DRF_SHIFT(NV2080_PLATFORM_POWER_MODE_CHANGE_INFO_REASON));
2266
2267 gpuNotifySubDeviceEvent(pGpu, NV2080_NOTIFIERS_PLATFORM_POWER_MODE_CHANGE, ¶ms, sizeof(params), info32, 0);
2268 }
2269
2270 // Release locks/semaphore
2271 pfmreqhndlrPassiveModeTransition(NV_FALSE, API_LOCK_FLAGS_NONE, gpuLockFlag);
2272 }
2273
2274 pfmreqhndlrUpdatePlatformPowerModeWorkItemExit:
2275 // Reset on exit
2276 pPlatformRequestHandler->ppmData.ppmIdxRequested = NV0000_CTRL_PFM_REQ_HNDLR_PPM_INDEX_INVALID;
2277 pPlatformRequestHandler->ppmData.bWorkItemPending = NV_FALSE;
2278 }
2279
2280 /*!
2281 * @brief passive worker thread to update the system control parameters.
2282 *
2283 * @param[in] gpuInstance GPU instance ID
2284 * @param[in] pParam unused
2285 */
2286 static void
_pfmreqhndlrUpdateSystemParamLimitWorkItem(NvU32 gpuInstance,void * pParams)2287 _pfmreqhndlrUpdateSystemParamLimitWorkItem
2288 (
2289 NvU32 gpuInstance,
2290 void *pParams
2291 )
2292 {
2293 OBJSYS *pSys = SYS_GET_INSTANCE();
2294 PlatformRequestHandler *pPlatformRequestHandler = SYS_GET_PFM_REQ_HNDLR(pSys);
2295 NvU32 id;
2296
2297 // Attempt to acquire locks/semaphore
2298 if (pfmreqhndlrPassiveModeTransition(NV_TRUE, API_LOCK_FLAGS_NONE, GPUS_LOCK_FLAGS_NONE) != NV_OK)
2299 {
2300 NV_PRINTF(LEVEL_ERROR, "Failed to acquire the locks/semaphore!\n");
2301
2302 pPlatformRequestHandler->sysControlData.bWorkItemPending = NV_FALSE;
2303 return;
2304 }
2305
2306 FOR_EACH_INDEX_IN_MASK(32, id, pPlatformRequestHandler->sysControlData.queuedCounterMask)
2307 {
2308 _pfmreqhndlrUpdateSystemParamLimit(pPlatformRequestHandler, id);
2309 }
2310 FOR_EACH_INDEX_IN_MASK_END;
2311
2312 pPlatformRequestHandler->sysControlData.bWorkItemPending = NV_FALSE;
2313 pPlatformRequestHandler->sysControlData.queuedCounterMask = 0;
2314
2315 // Release locks/semaphore
2316 pfmreqhndlrPassiveModeTransition(NV_FALSE, API_LOCK_FLAGS_NONE, GPUS_LOCK_FLAGS_NONE);
2317 }
2318
2319 /*!
2320 *
2321 * _pfmreqhndlrCallPshareStatus
2322 *
2323 * This function makes the PSHARESTATUS ACPI call. It sets up the call based on
2324 * the ACPI cache & updates the cache with the results.
2325 *
2326 * @param[in] pPlatformRequestHandler *PlatformRequestHandler object pointer
2327 * @param[in] bInit If called from PlatformRequestHandler init sequence
2328 *
2329 * @return NV_OK if the update was successful.
2330 * @return NV_ERR_INVALID_STATE for invalid PMU state
2331 * @return bubble up errors triggered by called code
2332 */
2333 static NV_STATUS
_pfmreqhndlrCallPshareStatus(PlatformRequestHandler * pPlatformRequestHandler,NvBool bInit)2334 _pfmreqhndlrCallPshareStatus
2335 (
2336 PlatformRequestHandler *pPlatformRequestHandler,
2337 NvBool bInit
2338 )
2339 {
2340 OBJGPU *pGpu = NULL;
2341 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData = NULL;
2342 NV_STATUS status = NV_OK;
2343 NV_STATUS lclStatus = NV_OK;
2344 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS
2345 acpiParams;
2346 NvU32 timeStamp;
2347
2348 NV_ASSERT_OR_RETURN(NULL != pPlatformRequestHandler, NV_ERR_INVALID_REQUEST);
2349
2350 pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
2351 pPfmreqhndlrData = &pPlatformRequestHandler->sensorData;
2352
2353 acpiParams.ctrl.cmd = NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_PSHARESTATUS;
2354 acpiParams.ctrl.input = 0;
2355 acpiParams.output.pBuffer = NULL;
2356 acpiParams.output.bufferSz = 0;
2357
2358 status = pfmreqhndlrCallACPI(pGpu, &acpiParams);
2359
2360 if (NV_OK == status)
2361 {
2362 NvBool bQueryEdppRequired = NV_FALSE;
2363 NvBool bPlatformEdpUpdate = NV_FALSE;
2364
2365 // Platform EDPp limit handling check
2366 bQueryEdppRequired = FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PSHARESTATUS, _PLATFORM_GETEDPPEAKLIMIT_SET, _TRUE, acpiParams.output.result[0]);
2367 bPlatformEdpUpdate = FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PSHARESTATUS, _PLATFORM_SETEDPPEAKLIMITINFO_SET, _TRUE, acpiParams.output.result[0]);
2368
2369 // update the cache values
2370 pPfmreqhndlrData->PFMREQHNDLRACPIData.bSystemParamLimitUpdate = FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PSHARESTATUS, _UPDATE_LIMIT, _PENDING, acpiParams.output.result[0]);
2371
2372 pPfmreqhndlrData->PFMREQHNDLRACPIData.bEDPpeakLimitUpdateRequest =
2373 FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PSHARESTATUS, _EDPPEAK_LIMIT_UPDATE, _TRUE, acpiParams.output.result[0]);
2374 pPfmreqhndlrData->PFMREQHNDLRACPIData.bUserConfigTGPmodeRequest =
2375 FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PSHARESTATUS, _USER_CONFIG_TGP_MODE, _ENABLE, acpiParams.output.result[0]);
2376 pPfmreqhndlrData->PFMREQHNDLRACPIData.bPlatformUserConfigTGPSupport =
2377 FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PSHARESTATUS, _PLAT_USER_CONFIG_TGP_MODE_SUPPORT, _ENABLE, acpiParams.output.result[0]);
2378
2379 //
2380 // 1.A. EDPpeak limit update: Handle the legacy way where a VBIOS static limit is applied
2381 // Update only if in reset state and Reset only if is in enabled state
2382 //
2383 if (PFM_REQ_HNDLR_IS_EDPPEAK_UPDATE_REQUIRED(pPfmreqhndlrData->PFMREQHNDLRACPIData.bEDPpeakLimitUpdateRequest,
2384 pPlatformRequestHandler->controlData.bEDPpeakUpdateEnabled) && !bInit)
2385 {
2386 // Update or Reset the EDPp limit if needed
2387 lclStatus = pfmreqhndlrHandleEdppeakLimitUpdate(pPlatformRequestHandler, pGpu,
2388 pPfmreqhndlrData->PFMREQHNDLRACPIData.bEDPpeakLimitUpdateRequest);
2389 if ((NV_OK != lclStatus) &&
2390 (NV_ERR_NOT_SUPPORTED != lclStatus))
2391 {
2392 status = lclStatus;
2393 }
2394 }
2395
2396 //
2397 // 1.B. EDPpeak limit update : Handle platform supplied limit
2398 //
2399 if (bQueryEdppRequired)
2400 {
2401 NvU32 platformEdppLimit = 0;
2402
2403 // Query platform for the new EDPp value
2404 lclStatus = pfmreqhndlrHandlePlatformGetEdppLimit(pPlatformRequestHandler, pGpu, &platformEdppLimit);
2405 if ((NV_OK != lclStatus) &&
2406 (NV_ERR_NOT_SUPPORTED != lclStatus))
2407 {
2408 status = lclStatus;
2409 }
2410 else
2411 {
2412 // Cache the EDPp limit from platform request
2413 pPfmreqhndlrData->PFMREQHNDLRACPIData.platformEdppLimit = platformEdppLimit;
2414 }
2415
2416 if (bInit)
2417 {
2418 // Defer init time EDPp update after prereq is satisfied
2419 pPlatformRequestHandler->controlData.edppLimit.bDifferPlatformEdppLimit = NV_TRUE;
2420 }
2421 else
2422 {
2423 // Followed by apply the platform limit on the GPU
2424 lclStatus = pfmreqhndlrHandlePlatformEdppLimitUpdate(pPlatformRequestHandler, pGpu,
2425 pPfmreqhndlrData->PFMREQHNDLRACPIData.platformEdppLimit);
2426 if ((NV_OK != lclStatus) &&
2427 (NV_ERR_NOT_SUPPORTED != lclStatus))
2428 {
2429 status = lclStatus;
2430 }
2431 }
2432 }
2433
2434 //
2435 // 2. User configurable TGP mode (Turbo) Update
2436 // Enable only if in reset state and Reset only if in enabled state
2437 //
2438 if (PFM_REQ_HNDLR_IS_USER_CONFIG_TGP_MODE_UPDATE_REQUIRED(pPfmreqhndlrData->PFMREQHNDLRACPIData.bUserConfigTGPmodeRequest,
2439 pPlatformRequestHandler->controlData.bUserConfigTGPmodeEnabled) && !bInit)
2440 {
2441 // Enable or Reset the configurable TGP mode if needed
2442 lclStatus = pfmreqhndlrHandleUserConfigurableTgpMode(pPlatformRequestHandler, pGpu,
2443 pPfmreqhndlrData->PFMREQHNDLRACPIData.bUserConfigTGPmodeRequest);
2444 if ((NV_OK != lclStatus) &&
2445 (NV_ERR_NOT_SUPPORTED != lclStatus))
2446 {
2447 status = lclStatus;
2448 }
2449 }
2450
2451 // 3. Platform static customization for user config TGP can be handled here one time
2452 if ((pPfmreqhndlrData->PFMREQHNDLRACPIData.bPlatformUserConfigTGPSupport) &&
2453 (!pPlatformRequestHandler->controlData.bPlatformUserConfigTGPmodeEnabled) &&
2454 (bInit))
2455 {
2456 lclStatus = _pfmreqhndlrHandleUserConfigurableTgpModePlatformCustomization(pPlatformRequestHandler, pGpu);
2457 if ((NV_OK != lclStatus) &&
2458 (NV_ERR_NOT_SUPPORTED != lclStatus))
2459 {
2460 status = lclStatus;
2461 }
2462 }
2463
2464 if (pPfmreqhndlrData->PFMREQHNDLRACPIData.bSystemParamLimitUpdate)
2465 {
2466 timeStamp = _pfmreqhndlrGetTimeStamp(pPlatformRequestHandler);
2467 _pfmreqhndlrResetCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_TGPU_SENSOR), timeStamp);
2468 _pfmreqhndlrResetCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_PPMD_SENSOR), timeStamp);
2469
2470 lclStatus = _pfmreqhndlrUpdateTgpuLimit(pPlatformRequestHandler, pGpu);
2471 if ((NV_OK == status) && (NV_ERR_NOT_SUPPORTED != lclStatus))
2472 {
2473 status = lclStatus;
2474 }
2475
2476 if (PFM_REQ_HNDLR_IS_ACPI_VERSION_SW_2X(pPlatformRequestHandler))
2477 {
2478 // Run time PPMD update from the system
2479 lclStatus = _pfmreqhndlrUpdatePpmdLimit(pPlatformRequestHandler, pGpu, NV_FALSE);
2480 if ((NV_OK == status) && (NV_ERR_NOT_SUPPORTED != lclStatus))
2481 {
2482 status = lclStatus;
2483 }
2484 }
2485
2486 // Reset the system parameter update flag
2487 pPfmreqhndlrData->PFMREQHNDLRACPIData.bSystemParamLimitUpdate = NV_FALSE;
2488 }
2489
2490 if (bPlatformEdpUpdate)
2491 {
2492 lclStatus = pfmreqhndlrHandlePlatformSetEdppLimitInfo(pPlatformRequestHandler, pGpu);
2493 if ((NV_OK != lclStatus) && (NV_ERR_NOT_SUPPORTED != lclStatus))
2494 {
2495 status = lclStatus;
2496 }
2497 }
2498 }
2499
2500 return status;
2501 }
2502
2503 /*!
2504 * Setup the initial state for the given counter as a supported counter.
2505 *
2506 * @param[in] pPfmreqhndlrData Pointer to the Sensor Data cache.
2507 * @param[in] id Identifier of counter to be updated.
2508 * @param[in] bVolatile bool indicating if the counter is volatile or not.
2509 * Volatile counters can go stale & will be sampled
2510 * on request for a sampling, whereas it is the
2511 * responsability of the code associated with controlling
2512 * the counter value to update a non-volatile counter.
2513 * @param[in] timeStamp current time stamp in MS used to create a stale
2514 * timestamp if needed to ensure that the first time
2515 * the counter is querried we try to sample it.
2516 *
2517 */
2518 static void
_pfmreqhndlrInitSupportedCounter(PFM_REQ_HNDLR_SENSOR_DATA * pPfmreqhndlrData,NvU32 id,NvBool bVolatile,NvU32 timeStamp)2519 _pfmreqhndlrInitSupportedCounter
2520 (
2521 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData,
2522 NvU32 id,
2523 NvBool bVolatile,
2524 NvU32 timeStamp
2525 )
2526 {
2527 pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].bSupported = NV_TRUE;
2528 pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].bVolatile = bVolatile;
2529 pPfmreqhndlrData->PFMREQHNDLRSensorCache[id].minInterval = PFM_REQ_HNDLR_DEFAULT_COUNTER_HOLD_PERIOD_MS;
2530 _pfmreqhndlrResetCounter(pPfmreqhndlrData, id, timeStamp);
2531 }
2532
2533 //
2534 // _pfmreqhndlrGetPerfSensorCounters
2535 //
2536 // This function collects the requested counters and returns those that are actually available.
2537 //
2538 NV_STATUS
pfmreqhndlrGetPerfSensorCounters(NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_GET_PERF_SENSOR_COUNTERS_PARAMS * pParams,NvU16 mapFlags)2539 pfmreqhndlrGetPerfSensorCounters
2540 (
2541 NV0000_CTRL_SYSTEM_PFM_REQ_HNDLR_GET_PERF_SENSOR_COUNTERS_PARAMS *pParams,
2542 NvU16 mapFlags
2543 )
2544 {
2545 OBJSYS *pSys = SYS_GET_INSTANCE();
2546 PlatformRequestHandler *pPlatformRequestHandler = SYS_GET_PFM_REQ_HNDLR(pSys);
2547 NvU32 counterMask;
2548 NvU32 counterVal;
2549 NvU16 idx;
2550
2551 NV_ASSERT_OR_RETURN(NULL != pPlatformRequestHandler, NV_ERR_NOT_SUPPORTED);
2552
2553 // is the block Id within range?
2554 if (pParams->blockId >= PFM_REQ_HNDLR_AVAILABLE_SENSOR_BLOCKS)
2555 {
2556 return NV_ERR_NOT_SUPPORTED;
2557 }
2558
2559 // run thru & get each counter specified in the request mask.
2560 for (idx = 0; idx < PFM_REQ_HNDLR_MAX_SENSORS_IN_BLOCK; ++idx)
2561 {
2562 pParams->counterBlock[idx] = 0;
2563 counterMask = (1 << idx);
2564
2565 // are we interested in this counter?
2566 if (((pParams->countersReq & counterMask) != 0) &&
2567 ((PerfSensorBlockMap[pParams->blockId][idx] & mapFlags) == mapFlags))
2568 {
2569 if (NV_OK == pfmreqhndlrGetPerfSensorCounterById(pPlatformRequestHandler,
2570 PFM_REQ_HNDLR_PSR_ID(PerfSensorBlockMap[pParams->blockId][idx]),
2571 &counterVal))
2572 {
2573 pParams->counterBlock[idx] = counterVal;
2574 pParams->countersReturned |= counterMask;
2575 }
2576 }
2577 }
2578
2579 return NV_OK;
2580 }
2581
2582 //
2583 // _pfmreqhndlrIsCacheEntryStale
2584 //
2585 // This function returns a bool indicating if the specified cache entry is stale.
2586 //
2587 static NvBool
_pfmreqhndlrIsCacheEntryStale(PFM_REQ_HNDLR_SENSOR_DATA * pPfmreqhndlrData,NvU32 counterId,NvU32 timeStamp)2588 _pfmreqhndlrIsCacheEntryStale
2589 (
2590 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData,
2591 NvU32 counterId,
2592 NvU32 timeStamp
2593 )
2594 {
2595 NvU32 age;
2596 NvBool bStale = NV_FALSE;
2597
2598 // if the counter is Volatile, check to see if it has aged out.
2599 if ((pPfmreqhndlrData->PFMREQHNDLRSensorCache[counterId].bVolatile) &&
2600 (!pPfmreqhndlrData->PFMREQHNDLRSensorCache[counterId].bOverridden))
2601 {
2602 // calculate the age allowing for wrap.
2603 age = timeStamp - pPfmreqhndlrData->PFMREQHNDLRSensorCache[counterId].lastSampled;
2604
2605 // if the age went negitive, make the age 0.
2606 if ((NvS32)age < 0)
2607 {
2608 age = 0;
2609 }
2610 bStale = ((pPfmreqhndlrData->counterHoldPeriod < age) && (pPfmreqhndlrData->PFMREQHNDLRSensorCache[counterId].minInterval < age));
2611 }
2612 return bStale;
2613 }
2614
2615 static NV_STATUS
_pfmreqhndlrSampleSensorLimit(PlatformRequestHandler * pPlatformRequestHandler,NvU32 id,NvU32 timeStamp)2616 _pfmreqhndlrSampleSensorLimit
2617 (
2618 PlatformRequestHandler *pPlatformRequestHandler,
2619 NvU32 id,
2620 NvU32 timeStamp
2621 )
2622 {
2623 NV_STATUS status = NV_ERR_NOT_SUPPORTED;
2624
2625 if (!PFM_REQ_HNDLR_VALID_LIMIT_ID(id))
2626 {
2627 return NV_ERR_NOT_SUPPORTED;
2628 }
2629
2630 // Use ACPI only
2631 status = _pfmreqhndlrSampleSensorLimit_ACPI(pPlatformRequestHandler, id, timeStamp);
2632
2633 return status;
2634 }
2635
2636 static NV_STATUS
_pfmreqhndlrSampleSensorLimit_ACPI(PlatformRequestHandler * pPlatformRequestHandler,NvU32 id,NvU32 timeStamp)2637 _pfmreqhndlrSampleSensorLimit_ACPI
2638 (
2639 PlatformRequestHandler *pPlatformRequestHandler,
2640 NvU32 id,
2641 NvU32 timeStamp
2642 )
2643 {
2644 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData = &pPlatformRequestHandler->sensorData;
2645 OBJGPU *pGpu = pfmreqhndlrGetGpu(pPlatformRequestHandler);
2646 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS acpiParams = {{ 0 }};
2647 PFM_REQ_HNDLR_PSHAREDATA pshareParams = { 0 };
2648 NV_STATUS status;
2649 NvU8 i;
2650
2651 // all the counters for this case are read in a single block
2652 acpiParams.ctrl.cmd = NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_PSHAREPARAMS;
2653 acpiParams.ctrl.input = pPfmreqhndlrData->PFMREQHNDLRShareParamsAvailMask |
2654 DRF_DEF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS, _STATUS_QUERY_TYPE, _CURRENT_LIMITS);
2655
2656 // exclude counters that are up-to-date or have forced overrides
2657 for (i = 0; i < PFM_REQ_HNDLR_PSHAREPARAMS_COUNT; i++)
2658 {
2659 if (((timeStamp - pPfmreqhndlrData->PFMREQHNDLRSensorCache[PFM_REQ_HNDLR_LIMIT(i)].lastSampled) <
2660 pPfmreqhndlrData->PFMREQHNDLRSensorCache[PFM_REQ_HNDLR_LIMIT(i)].minInterval) ||
2661 pPfmreqhndlrData->PFMREQHNDLRSensorCache[PFM_REQ_HNDLR_LIMIT(i)].bOverridden)
2662 {
2663 acpiParams.ctrl.input &= ~NVBIT(i + DRF_BASE(NV0000_CTRL_PFM_REQ_HNDLR_PSHARE_PARAMS_STATUS_TGPU));
2664 }
2665 }
2666
2667 // bail-out if everything is already up-to-date
2668 if (acpiParams.ctrl.input == 0)
2669 {
2670 return NV_OK;
2671 }
2672
2673 acpiParams.output.pBuffer = (NvU8 *)&pshareParams;
2674 acpiParams.output.bufferSz = sizeof(pshareParams);
2675 status = pfmreqhndlrCallACPI(pGpu, &acpiParams);
2676 if (status == NV_OK)
2677 {
2678 if (FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS_STATUS, _TGPU, _TRUE, acpiParams.ctrl.input))
2679 {
2680 _pfmreqhndlrUpdateCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_TGPU_SENSOR), FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS_STATUS, _TGPU, _TRUE, pshareParams.status), pshareParams.tGpu, timeStamp);
2681 }
2682 if (FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS_STATUS, _PPMD, _TRUE, acpiParams.ctrl.input))
2683 {
2684 _pfmreqhndlrUpdateCounter(pPfmreqhndlrData, PFM_REQ_HNDLR_LIMIT(PFM_REQ_HNDLR_PPMD_SENSOR), FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS_STATUS, _PPMD, _TRUE, pshareParams.status), pshareParams.ppmd, timeStamp);
2685 }
2686 }
2687 return status;
2688 }
2689
2690 /*!
2691 * Set up PlatformRequestHandler control flags based on the ACPI supported subfunction lists.
2692 *
2693 * @param[in] pGpu OBJGPU pointer
2694 * @param[in] pPlatformRequestHandler *PlatformRequestHandler pointer
2695 * @param[in] supportedSubfuncs NvU32 supported subfunctions list from SBIOS
2696 *
2697 * @return NV_OK always succeeds
2698 *
2699 */
2700 static NV_STATUS
_pfmreqhndlrSetSupportedStatesFromAcpiParams(OBJGPU * pGpu,PlatformRequestHandler * pPlatformRequestHandler,NvU32 supportedSubfuncs)2701 _pfmreqhndlrSetSupportedStatesFromAcpiParams
2702 (
2703 OBJGPU *pGpu,
2704 PlatformRequestHandler
2705 *pPlatformRequestHandler,
2706 NvU32 supportedSubfuncs
2707
2708 )
2709 {
2710 PFM_REQ_HNDLR_SENSOR_DATA *pPfmreqhndlrData = &(pPlatformRequestHandler->sensorData);
2711
2712 pPfmreqhndlrData->PFMREQHNDLRACPIData.bPfmReqHndlrSupported =
2713 ((0 != (DRF_VAL(0000_CTRL_PFM_REQ_HNDLR, _SUPPORTED, _PSHARESTATUS_AVAIL, supportedSubfuncs))) &&
2714 (0 != (DRF_VAL(0000_CTRL_PFM_REQ_HNDLR, _SUPPORTED, _PSHAREPARAMS_AVAIL, supportedSubfuncs))));
2715
2716 return NV_OK;
2717 }
2718
2719 /*!
2720 * Handler routine to platform costumization to user mode TGP
2721 *
2722 * @param[in] pPlatformRequestHandler *PlatformRequestHandler object pointer
2723 *
2724 * @return NV_OK if the update was successful.
2725 * @return NV_ERR_NOT_SUPPORTED if the POR support is not present
2726 * @return bubble up errors triggered by called code
2727 */
2728 static NV_STATUS
_pfmreqhndlrHandleUserConfigurableTgpModePlatformCustomization(PlatformRequestHandler * pPlatformRequestHandler,OBJGPU * pGpu)2729 _pfmreqhndlrHandleUserConfigurableTgpModePlatformCustomization
2730 (
2731 PlatformRequestHandler *pPlatformRequestHandler,
2732 OBJGPU *pGpu
2733 )
2734 {
2735 NV_STATUS status = NV_OK;
2736 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS acpiParams;
2737 PFM_REQ_HNDLR_PSHAREDATA pshareParams;
2738
2739 portMemSet((void *) &acpiParams, 0, sizeof(NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS));
2740 portMemSet((void *) &pshareParams, 0, sizeof(PFM_REQ_HNDLR_PSHAREDATA));
2741
2742 acpiParams.ctrl.cmd = NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_PSHAREPARAMS;
2743 acpiParams.ctrl.input = DRF_DEF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS, _STATUS_CTGP, _TRUE) |
2744 DRF_DEF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS, _STATUS_QUERY_TYPE, _CURRENT_LIMITS);
2745 acpiParams.output.pBuffer = (NvU8*)&pshareParams;
2746 acpiParams.output.bufferSz = sizeof(pshareParams);
2747 status = pfmreqhndlrCallACPI(pGpu, &acpiParams);
2748 if (status != NV_OK)
2749 {
2750 DBG_BREAKPOINT();
2751 status = NV_ERR_NOT_SUPPORTED;
2752 goto _pfmreqhndlrHandleUserConfigurableTgpModePlatfromCustomization_exit;
2753 }
2754
2755 //Set the customization config tgp delta
2756 if (FLD_TEST_DRF(0000_CTRL_PFM_REQ_HNDLR, _PSHARE_PARAMS_STATUS, _CTGP, _TRUE, pshareParams.status))
2757 {
2758 // Cached the platform limit delta in the PlatformRequestHandler ACPI cache
2759 pPlatformRequestHandler->sensorData.PFMREQHNDLRACPIData.platformLimitDeltamW = pshareParams.ctgp;
2760
2761 // Config TGP from platform is enabled
2762 pPlatformRequestHandler->controlData.bPlatformUserConfigTGPmodeEnabled = NV_TRUE;
2763
2764 NV2080_CTRL_CMD_INTERNAL_PMGR_PFM_REQ_HNDLR_CONFIGURE_TURBO_V2_PARAMS params = { 0 };
2765 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
2766
2767 params.ctgpOffsetmW = pshareParams.ctgp;
2768
2769 pRmApi->Control(pRmApi,
2770 pGpu->hInternalClient,
2771 pGpu->hInternalSubdevice,
2772 NV2080_CTRL_CMD_INTERNAL_PMGR_PFM_REQ_HNDLR_CONFIGURE_TURBO_V2,
2773 ¶ms,
2774 sizeof(params));
2775 }
2776
2777 _pfmreqhndlrHandleUserConfigurableTgpModePlatfromCustomization_exit:
2778 return status;
2779 }
2780
2781 /*!
2782 * Reset Platform Power Mode cache on PlatformRequestHandler init and PlatformRequestHandler state unload
2783 *
2784 * @param[in] pPlatformRequestHandler *PlatformRequestHandler pointer
2785 *
2786 */
2787 static void
_pfmreqhndlrPlatformPowerModeStateReset(PlatformRequestHandler * pPlatformRequestHandler)2788 _pfmreqhndlrPlatformPowerModeStateReset
2789 (
2790 PlatformRequestHandler *pPlatformRequestHandler
2791 )
2792 {
2793 PFM_REQ_HNDLR_PPM_DATA *pPpmData = NULL;
2794
2795 pPpmData = &(pPlatformRequestHandler->ppmData);
2796
2797 // Init the PPM Cache Data
2798 pPpmData->ppmMaskCurrent = NV0000_CTRL_PFM_REQ_HNDLR_PPM_MASK_INVALID;
2799 pPpmData->ppmIdxCurrent = NV0000_CTRL_PFM_REQ_HNDLR_PPM_INDEX_INVALID;
2800 pPpmData->bWorkItemPending = NV_FALSE;
2801 pPpmData->ppmIdxRequested = NV0000_CTRL_PFM_REQ_HNDLR_PPM_INDEX_INVALID;
2802 }
2803
2804 /*!
2805 * @brief passive worker thread to communcate EDPpeak info to platform.
2806 *
2807 * @param[in] gpuInstance GPU instance ID
2808 * @param[in] pParams unused
2809 */
2810 static void
_pfmreqhndlrHandlePlatformSetEdppLimitInfoWorkItem(NvU32 gpuInstance,void * pParams)2811 _pfmreqhndlrHandlePlatformSetEdppLimitInfoWorkItem
2812 (
2813 NvU32 gpuInstance,
2814 void *pParams
2815 )
2816 {
2817 OBJSYS *pSys = SYS_GET_INSTANCE();
2818 PlatformRequestHandler *pPlatformRequestHandler = SYS_GET_PFM_REQ_HNDLR(pSys);
2819 OBJGPU *pGpu =
2820 pfmreqhndlrGetGpu(pPlatformRequestHandler);
2821 PFM_REQ_HNDLR_EDPP_DATA *pEdppLimit =
2822 &pPlatformRequestHandler->controlData.edppLimit;
2823 NvU32 status = NV_OK;
2824 NvU32 gpuLockFlag = GPUS_LOCK_FLAGS_NONE;
2825 NvBool lockAcquired = NV_FALSE;
2826 NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS
2827 acpiParams;
2828 NV0000_CTRL_PFM_REQ_HNDLR_EDPP_LIMIT_INFO_V1
2829 edppLimitInfo;
2830
2831 if (FULL_GPU_SANITY_CHECK(pGpu))
2832 {
2833 // Attempt to acquire locks/semaphore
2834 if (pfmreqhndlrPassiveModeTransition(NV_TRUE, API_LOCK_FLAGS_NONE,
2835 gpuLockFlag) != NV_OK)
2836 {
2837 NV_PRINTF(LEVEL_ERROR, "Failed to acquire the locks/semaphore!\n");
2838 goto _pfmreqhndlrHandlePlatformSetEdppLimitInfoWorkItem_exit;
2839 }
2840 lockAcquired = NV_TRUE;
2841
2842 portMemSet((void*)&acpiParams, 0, sizeof(NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_PARAMS));
2843 portMemSet((void*)&edppLimitInfo, 0, sizeof(NV0000_CTRL_PFM_REQ_HNDLR_EDPP_LIMIT_INFO_V1));
2844
2845 edppLimitInfo.ulVersion = NV0000_CTRL_PFM_REQ_HNDLR_EDPP_VERSION_V10;
2846 edppLimitInfo.limitLast =
2847 pPlatformRequestHandler->sensorData.PFMREQHNDLRACPIData.platformEdppLimit;
2848
2849 // Fill in the other EDPpeak data if we received them from GPU successfully
2850 if (pEdppLimit->status == NV_OK)
2851 {
2852 edppLimitInfo.limitMin = pEdppLimit->edppLimitInfo.limitMin;
2853 edppLimitInfo.limitRated = pEdppLimit->edppLimitInfo.limitRated;
2854 edppLimitInfo.limitMax = pEdppLimit->edppLimitInfo.limitMax;
2855 edppLimitInfo.limitCurr = pEdppLimit->edppLimitInfo.limitCurr;
2856 edppLimitInfo.limitBattRated = pEdppLimit->edppLimitInfo.limitBattRated;
2857 edppLimitInfo.limitBattMax = pEdppLimit->edppLimitInfo.limitBattMax;
2858 }
2859
2860 // Call the platform and communicate the EDPp info
2861 acpiParams.ctrl.cmd = NV0000_CTRL_PFM_REQ_HNDLR_CALL_ACPI_CMD_SETEDPPLIMITINFO;
2862
2863 acpiParams.output.pBuffer = (NvU8*)&edppLimitInfo;
2864 acpiParams.output.bufferSz = sizeof(edppLimitInfo);
2865
2866 status = pfmreqhndlrCallACPI(pGpu, &acpiParams);
2867 if (status != NV_OK)
2868 {
2869 DBG_BREAKPOINT();
2870 goto _pfmreqhndlrHandlePlatformSetEdppLimitInfoWorkItem_exit;
2871 }
2872
2873 }
2874
2875 _pfmreqhndlrHandlePlatformSetEdppLimitInfoWorkItem_exit:
2876
2877 // Make workitem available
2878 pEdppLimit->bWorkItemPending = NV_FALSE;
2879 if (lockAcquired)
2880 {
2881 // Release locks/semaphore
2882 pfmreqhndlrPassiveModeTransition(NV_FALSE, API_LOCK_FLAGS_NONE, gpuLockFlag);
2883 }
2884 return;
2885 }
2886
2887 /*
2888 * NOTE. HOSUNGK. These functions are for backwards compatibility with KMD and NvAPI
2889 * These will be removed after promotion from bugfix_main
2890 */
2891 NV_STATUS
cliresCtrlCmdSystemGpsCtrl_IMPL(RmClientResource * pRmCliRes,NV0000_CTRL_SYSTEM_GPS_CTRL_PARAMS * pParams)2892 cliresCtrlCmdSystemGpsCtrl_IMPL
2893 (
2894 RmClientResource *pRmCliRes,
2895 NV0000_CTRL_SYSTEM_GPS_CTRL_PARAMS *pParams
2896 )
2897 {
2898 return NV_OK;
2899 }
2900
2901 NV_STATUS
cliresCtrlCmdSystemGpsGetFrmData_IMPL(RmClientResource * pRmCliRes,NV0000_CTRL_SYSTEM_GPS_GET_FRM_DATA_PARAMS * pParams)2902 cliresCtrlCmdSystemGpsGetFrmData_IMPL
2903 (
2904 RmClientResource *pRmCliRes,
2905 NV0000_CTRL_SYSTEM_GPS_GET_FRM_DATA_PARAMS *pParams
2906 )
2907 {
2908 return NV_OK;
2909 }
2910
2911 NV_STATUS
cliresCtrlCmdSystemGpsSetFrmData_IMPL(RmClientResource * pRmCliRes,NV0000_CTRL_SYSTEM_GPS_SET_FRM_DATA_PARAMS * pParams)2912 cliresCtrlCmdSystemGpsSetFrmData_IMPL
2913 (
2914 RmClientResource *pRmCliRes,
2915 NV0000_CTRL_SYSTEM_GPS_SET_FRM_DATA_PARAMS *pParams
2916 )
2917 {
2918 return NV_OK;
2919 }
2920
2921 NV_STATUS
cliresCtrlCmdSystemGpsCallAcpi_IMPL(RmClientResource * pRmCliRes,NV0000_CTRL_SYSTEM_GPS_CALL_ACPI_PARAMS * pParams)2922 cliresCtrlCmdSystemGpsCallAcpi_IMPL
2923 (
2924 RmClientResource *pRmCliRes,
2925 NV0000_CTRL_SYSTEM_GPS_CALL_ACPI_PARAMS *pParams
2926 )
2927 {
2928 return NV_OK;
2929 }
2930