1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 1993-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 /********************* Non-Chip Specific HAL TMR Routines ******************\
25 *                                                                           *
26 *   This file contains TMR method implementations using OSTIMER             *
27 *                                                                           *
28 \***************************************************************************/
29 
30 #include "objtmr.h"
31 
32 //
33 // This function returns current time from OS timer
34 //
35 NvU64
tmrGetTimeEx_OSTIMER(OBJGPU * pGpu,OBJTMR * pTmr,THREAD_STATE_NODE * pThreadState)36 tmrGetTimeEx_OSTIMER
37 (
38     OBJGPU             *pGpu,
39     OBJTMR             *pTmr,
40     THREAD_STATE_NODE  *pThreadState
41 )
42 {
43     NvU32   seconds;                // Time since 1970 in seconds
44     NvU32   useconds;               //  and uSeconds.
45     NvU64 timeNs; // Time since 1970 in ns.
46 
47     //
48     // Get current time from operating system.
49     //
50     // We get the time in seconds and microseconds since 1970
51     // Note that we don't really need the real time of day
52     //
53     osGetCurrentTime(&seconds, &useconds);
54 
55     //
56     // Calculate ns since 1970.
57     //
58     timeNs = ((NvU64)seconds * 1000000 + useconds) * 1000;
59 
60     return timeNs;
61 }
62 
63 /*!
64  *  Creates OS timer event
65  *
66  *  @param[in]  pTmr Pointer to Timer Object
67  *  @param[in]  pEvent pointer to timer event information
68  *  @param[out]  NV_STATUS
69  */
tmrEventCreateOSTimer_OSTIMER(OBJTMR * pTmr,PTMR_EVENT pEventPublic)70 NV_STATUS tmrEventCreateOSTimer_OSTIMER
71 (
72     OBJTMR     *pTmr,
73     PTMR_EVENT  pEventPublic
74 )
75 {
76     NV_STATUS status = NV_OK;
77     OBJGPU *pGpu = ENG_GET_GPU(pTmr);
78     PTMR_EVENT_PVT pEvent = (PTMR_EVENT_PVT)pEventPublic;
79 
80     status = osCreateNanoTimer(pGpu->pOsGpuInfo, pEvent, &(pEvent->super.pOSTmrCBdata));
81 
82     if (status != NV_OK)
83     {
84         pEvent->super.pOSTmrCBdata = NULL;
85         NV_PRINTF(LEVEL_ERROR, "OS create timer failed\n");
86     }
87 
88     return status;
89 }
90 
91 /*!
92  * This function Starts or Schedules OS Timer
93  *
94  *   @param[in]  pTmr Pointer to Timer Object
95  *   @param[in]  pEvent pointer to timer event information
96  *   @param[in]  relative time in nano seconds
97  *
98  *  @returns  NV_ERR_INVALID_REQUEST failed to create timer
99 */
tmrEventScheduleRelOSTimer_OSTIMER(OBJTMR * pTmr,PTMR_EVENT pPublicEvent,NvU64 timeRelNs)100 NV_STATUS tmrEventScheduleRelOSTimer_OSTIMER
101 (
102     OBJTMR     *pTmr,
103     PTMR_EVENT  pPublicEvent,
104     NvU64       timeRelNs
105 )
106 {
107     NV_STATUS status= NV_OK;
108     OBJGPU *pGpu = ENG_GET_GPU(pTmr);
109     PTMR_EVENT_PVT pEvent = (PTMR_EVENT_PVT) pPublicEvent;
110 
111     if (pEvent->super.pOSTmrCBdata == NULL)
112     {
113         NV_PRINTF(LEVEL_ERROR, "OS Timer not created\n");
114         return NV_ERR_INVALID_REQUEST;
115     }
116 
117     status = osStartNanoTimer(pGpu->pOsGpuInfo, pEvent->super.pOSTmrCBdata, timeRelNs);
118 
119     if (status != NV_OK)
120     {
121         NV_PRINTF(LEVEL_ERROR, "OS Start timer FAILED!\n");
122     }
123 
124     pEvent->super.flags |= TMR_FLAG_OS_TIMER_QUEUED;
125     return status;
126 }
127 
128 /*!
129  * This function runs OS timer callback
130  *
131 *   @param[in]  pGpu Pointer to GPU object
132 *   @param[in]  pTmr Pointer to Timer Object
133 *   @param[in]  pEvent pointer to timer event information
134 *
135  *  @returns  NV_ERR_INVALID_REQUEST if callback not found
136  */
tmrEventServiceOSTimerCallback_OSTIMER(OBJGPU * pGpu,OBJTMR * pTmr,PTMR_EVENT pPublicEvent)137 NV_STATUS tmrEventServiceOSTimerCallback_OSTIMER
138 (
139     OBJGPU             *pGpu,
140     OBJTMR             *pTmr,
141     PTMR_EVENT          pPublicEvent
142 )
143 {
144     PTMR_EVENT_PVT  pEvent = (PTMR_EVENT_PVT)pPublicEvent;
145     NV_STATUS status = NV_OK;
146 
147     if (pEvent && (pEvent->super.pTimeProc != NULL))
148     {
149         pEvent->super.pTimeProc(pGpu, pTmr, (PTMR_EVENT)pEvent);
150         pEvent->super.flags &= ~TMR_FLAG_OS_TIMER_QUEUED;
151     }
152     else
153     {
154         NV_PRINTF(LEVEL_ERROR,
155                   "ERROR No Timer event callback found, invalid timer SW state\n");
156         status = NV_ERR_INVALID_REQUEST;
157     }
158 
159     return status;
160 }
161 
162 /*!
163  * This function cancels OS timer callback
164  *
165  *   @param[in]  pTmr Pointer to Timer Object
166  *   @param[in]  pEvent pointer to timer event information
167  *   @returns  NV_ERR_INVALID_REQUEST if callback entry not found
168  */
tmrEventCancelOSTimer_OSTIMER(OBJTMR * pTmr,PTMR_EVENT pPublicEvent)169 NV_STATUS tmrEventCancelOSTimer_OSTIMER
170 (
171     OBJTMR             *pTmr,
172     PTMR_EVENT          pPublicEvent
173 )
174 {
175     NV_STATUS status= NV_OK;
176     OBJGPU *pGpu = ENG_GET_GPU(pTmr);
177     PTMR_EVENT_PVT  pTmrEvent = (PTMR_EVENT_PVT) pPublicEvent;
178 
179     if (pTmrEvent != NULL && pTmrEvent->super.pOSTmrCBdata != NULL)
180     {
181         // Cancel the callback of OS timer
182         status = osCancelNanoTimer(pGpu->pOsGpuInfo, pTmrEvent->super.pOSTmrCBdata);
183         pTmrEvent->super.flags &= ~TMR_FLAG_OS_TIMER_QUEUED;
184     }
185     else
186     {
187         NV_PRINTF(LEVEL_ERROR,
188                   "ERROR No Timer event callback found, invalid timer SW state\n");
189         status = NV_ERR_INVALID_REQUEST;
190     }
191 
192     return status;
193 }
194 
195 /*!
196  * This function cancels OS timer callback
197  *
198  *   @param[in]  pTmr Pointer to Timer Object
199  *   @param[in]  pEvent pointer to timer event information
200  *
201  *  @returns  NV_ERR_INVALID_REQUEST if callback entry not found
202  */
tmrEventDestroyOSTimer_OSTIMER(OBJTMR * pTmr,PTMR_EVENT pPublicEvent)203 NV_STATUS tmrEventDestroyOSTimer_OSTIMER
204 (
205     OBJTMR             *pTmr,
206     PTMR_EVENT          pPublicEvent
207 )
208 {
209     NV_STATUS status= NV_OK;
210     OBJGPU *pGpu = ENG_GET_GPU(pTmr);
211     PTMR_EVENT_PVT  pTmrEvent = (PTMR_EVENT_PVT) pPublicEvent;
212 
213     if (pTmrEvent != NULL && pTmrEvent->super.pOSTmrCBdata != NULL)
214     {
215         // Cancel the callback of OS timer
216         status = osDestroyNanoTimer(pGpu->pOsGpuInfo, pTmrEvent->super.pOSTmrCBdata);
217         pTmrEvent->super.flags &= ~TMR_FLAG_OS_TIMER_QUEUED;
218     }
219     else
220     {
221         NV_PRINTF(LEVEL_ERROR,
222                   "No Timer event callback found, invalid timer SW state\n");
223         status = NV_ERR_INVALID_REQUEST;
224     }
225 
226     return status;
227 }
228 
229 NV_STATUS
tmrGetIntrStatus_OSTIMER(OBJGPU * pGpu,OBJTMR * pTmr,NvU32 * pStatus,THREAD_STATE_NODE * pThreadState)230 tmrGetIntrStatus_OSTIMER
231 (
232     OBJGPU             *pGpu,
233     OBJTMR             *pTmr,
234     NvU32              *pStatus,
235     THREAD_STATE_NODE  *pThreadState
236 )
237 {
238     *pStatus = 0;
239     return NV_OK;
240 }
241 
242 //
243 // For functions that only need a short delta of time elapsed (~ 4.29 seconds)
244 // NOTE: Since it wraps around every 4.29 seconds, for general GetTime purposes,
245 //       it's better to use tmrGetTime().
246 //
247 NvU32
tmrGetTimeLo_OSTIMER(OBJGPU * pGpu,OBJTMR * pTmr)248 tmrGetTimeLo_OSTIMER
249 (
250     OBJGPU *pGpu,
251     OBJTMR *pTmr
252 )
253 {
254     return NvU64_LO32(tmrGetTimeEx_HAL(pGpu, pTmr, NULL));
255 }
256 
257 NvU64
tmrGetTime_OSTIMER(OBJGPU * pGpu,OBJTMR * pTmr)258 tmrGetTime_OSTIMER
259 (
260     OBJGPU             *pGpu,
261     OBJTMR             *pTmr
262 )
263 {
264     return tmrGetTimeEx_HAL(pGpu, pTmr, NULL);
265 }
266 
267 NvU32
tmrReadTimeLoReg_OSTIMER(OBJGPU * pGpu,OBJTMR * pTmr,THREAD_STATE_NODE * pThreadState)268 tmrReadTimeLoReg_OSTIMER
269 (
270     OBJGPU             *pGpu,
271     OBJTMR             *pTmr,
272     THREAD_STATE_NODE  *pThreadState
273 )
274 {
275     return NvU64_LO32(tmrGetTimeEx_HAL(pGpu, pTmr, pThreadState));
276 }
277 
278 NvU32
tmrReadTimeHiReg_OSTIMER(OBJGPU * pGpu,OBJTMR * pTmr,THREAD_STATE_NODE * pThreadState)279 tmrReadTimeHiReg_OSTIMER
280 (
281     OBJGPU             *pGpu,
282     OBJTMR             *pTmr,
283     THREAD_STATE_NODE  *pThreadState
284 )
285 {
286     return NvU64_HI32(tmrGetTimeEx_HAL(pGpu, pTmr, pThreadState));
287 }
288 
289 NV_STATUS
tmrGetGpuAndCpuTimestampPair_OSTIMER(OBJGPU * pGpu,OBJTMR * pTmr,NvU64 * pGpuTime,NvU64 * pCpuTime)290 tmrGetGpuAndCpuTimestampPair_OSTIMER
291 (
292     OBJGPU  *pGpu,
293     OBJTMR  *pTmr,
294     NvU64   *pGpuTime,
295     NvU64   *pCpuTime
296 )
297 {
298 #if PORT_IS_FUNC_SUPPORTED(portUtilExReadTimestampCounter)
299     *pGpuTime = tmrGetTimeEx_HAL(pGpu, pTmr, NULL);
300     *pCpuTime = portUtilExReadTimestampCounter();
301     return NV_OK;
302 #else
303     return NV_ERR_NOT_SUPPORTED;
304 #endif
305 }
306 
307 NV_STATUS
tmrDelay_OSTIMER(OBJTMR * pTmr,NvU32 nsec)308 tmrDelay_OSTIMER
309 (
310      OBJTMR    *pTmr,
311      NvU32      nsec
312 )
313 {
314     if (nsec > 50000000)    // 50 ms.
315     {
316         osDelay(nsec / 1000000);
317     }
318     else if (nsec > 0)
319     {
320         osDelayNs(nsec);
321     }
322 
323     return NV_OK;
324 }
325 
326