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