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                                                  &params,
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                             &paramSize)) != 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                             &paramSize)) != 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                             &paramSize)) != 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                         &paramSize)) != 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                                  &paramSize)) != 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                              &params,
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                                  &params,
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                                  &params,
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             &params,
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                              &params,
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                            &params,
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, &params, 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                              &params,
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, &params, 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                         &params,
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