1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2014-2015 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 #ifndef __NVKMS_UTILS_H__
25 #define __NVKMS_UTILS_H__
26
27 #include "nvkms-types.h"
28
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32
33 #include "nvidia-modeset-os-interface.h"
34
35 /*!
36 * Subtract B from A, and handle wrap around.
37 *
38 * This is useful for cases where A is a number that is incremented and wrapped;
39 * e.g.,
40 *
41 * a = (a + 1) % max;
42 *
43 * and we want to subtract some amount from A to get one of its previous values.
44 */
A_minus_b_with_wrap_U8(NvU8 a,NvU8 b,NvU8 max)45 static inline NvU8 A_minus_b_with_wrap_U8(NvU8 a, NvU8 b, NvU8 max)
46 {
47 return (a + max - b) % max;
48 }
49
50 /*!
51 * Return whether (A + B) > C, avoiding integer overflow in the addition.
52 */
A_plus_B_greater_than_C_U16(NvU16 a,NvU16 b,NvU16 c)53 static inline NvBool A_plus_B_greater_than_C_U16(NvU16 a, NvU16 b, NvU16 c)
54 {
55 return (NV_U16_MAX - a < b) || ((a + b) > c);
56 }
57
A_plus_B_greater_than_C_U64(NvU64 a,NvU64 b,NvU64 c)58 static inline NvBool A_plus_B_greater_than_C_U64(NvU64 a, NvU64 b, NvU64 c)
59 {
60 return (NV_U64_MAX - a < b) || ((a + b) > c);
61 }
62
clamp_S32(NvS32 val,NvS32 lo,NvS32 hi)63 static inline NvS32 clamp_S32(NvS32 val, NvS32 lo, NvS32 hi)
64 {
65 if (val < lo) {
66 return lo;
67 } else if (val > hi) {
68 return hi;
69 } else {
70 return val;
71 }
72 }
73
74 /*!
75 * Return whether the bitmask contains bits greater than or equal to
76 * the maximum.
77 */
nvHasBitAboveMax(NvU32 bitmask,NvU8 max)78 static inline NvBool nvHasBitAboveMax(NvU32 bitmask, NvU8 max)
79 {
80 nvAssert(max <= 32);
81 if (max == 32) {
82 return FALSE;
83 }
84 return (bitmask & ~((1 << max) - 1)) != 0;
85 }
86
87 /*!
88 * Check if a timeout is exceeded.
89 *
90 * This is intended to be used when busy waiting in a loop, like this:
91 *
92 * NvU64 startTime = 0;
93 *
94 * do {
95 * if (SOME-CONDITION) {
96 * break;
97 * }
98 *
99 * if (nvExceedsTimeoutUSec(pDevEvo, &startTime, TIMEOUT-IN-USEC)) {
100 * break;
101 * }
102 *
103 * nvkms_yield();
104 *
105 * } while (TRUE);
106 *
107 * The caller should zero-initialize startTime, and nvExceedsTimeoutUSec() will
108 * set startTime to the starting time on the first call. This is structured
109 * this way to avoid the nvkms_get_usec() call in the common case where
110 * SOME-CONDITION is true on the first iteration (nvkms_get_usec() is not
111 * expected to be a large penalty, but it still seems nice to avoid it when not
112 * needed).
113 */
nvExceedsTimeoutUSec(const NVDevEvoRec * pDevEvo,NvU64 * pStartTime,NvU64 timeoutPeriod)114 static inline NvBool nvExceedsTimeoutUSec(
115 const NVDevEvoRec *pDevEvo,
116 NvU64 *pStartTime,
117 NvU64 timeoutPeriod)
118 {
119 const NvU64 currentTime = nvkms_get_usec();
120
121 if (nvIsEmulationEvo(pDevEvo)) {
122 return FALSE;
123 }
124
125 if (*pStartTime == 0) {
126 *pStartTime = currentTime;
127 return FALSE;
128 }
129
130 if (currentTime < *pStartTime) { /* wraparound?! */
131 return TRUE;
132 }
133
134 return (currentTime - *pStartTime) > timeoutPeriod;
135 }
136
137 /*!
138 * Return a non-NULL string.
139 *
140 * The first argument, stringMightBeNull, could be NULL. In which
141 * case, return the second argument, safeString, which the caller
142 * should ensure is not NULL (e.g., by providing a literal).
143 *
144 * This is intended as a convenience for situations like this:
145 *
146 * char *s = FunctionThatMightReturnNull();
147 * printf("%s\n", nvSafeString(s, "stringLiteral"));
148 */
nvSafeString(char * stringMightBeNull,const char * safeString)149 static inline const char *nvSafeString(char *stringMightBeNull,
150 const char *safeString)
151 {
152 return (stringMightBeNull != NULL) ? stringMightBeNull : safeString;
153 }
154
nvCtxDmaOffsetFromBytes(NvU64 ctxDmaOffset)155 static inline NvU64 nvCtxDmaOffsetFromBytes(NvU64 ctxDmaOffset)
156 {
157 nvAssert((ctxDmaOffset & ((1 << NV_SURFACE_OFFSET_ALIGNMENT_SHIFT) - 1))
158 == 0);
159
160 return (ctxDmaOffset >> 8);
161 }
162
163 NvU8 nvPixelDepthToBitsPerComponent(enum nvKmsPixelDepth pixelDepth);
164
165 typedef enum {
166 EVO_LOG_WARN,
167 EVO_LOG_ERROR,
168 EVO_LOG_INFO,
169 } NVEvoLogType;
170
171 void *nvInternalAlloc(size_t size, NvBool zero);
172 void *nvInternalRealloc(void *ptr, size_t size);
173 void nvInternalFree(void *ptr);
174 char *nvInternalStrDup(const char *str);
175 NvBool nvGetRegkeyValue(const NVDevEvoRec *pDevEvo,
176 const char *key, NvU32 *val);
177
178 #if defined(DEBUG)
179
180 void nvReportUnfreedAllocations(void);
181
182 void *nvDebugAlloc(size_t size, int line, const char *file);
183 void *nvDebugCalloc(size_t nmemb, size_t size, int line, const char *file);
184 void *nvDebugRealloc(void *ptr, size_t size, int line, const char *file);
185 void nvDebugFree(void *ptr);
186 char *nvDebugStrDup(const char *str, int line, const char *file);
187
188 #define nvAlloc(s) nvDebugAlloc((s), __LINE__, __FILE__)
189 #define nvCalloc(n,s) nvDebugCalloc((n), (s), __LINE__, __FILE__)
190 #define nvFree(p) nvDebugFree(p)
191 #define nvRealloc(p,s) nvDebugRealloc((p), (s), __LINE__, __FILE__)
192 #define nvStrDup(s) nvDebugStrDup((s), __LINE__, __FILE__)
193
194 #else
195
196 #define nvAlloc(s) nvInternalAlloc((s), FALSE)
197 #define nvCalloc(n,s) nvInternalAlloc((n)*(s), TRUE)
198 #define nvRealloc(p,s) nvInternalRealloc((p),(s))
199 #define nvFree(s) nvInternalFree(s)
200 #define nvStrDup(s) nvInternalStrDup(s)
201
202 #endif
203
204 void nvVEvoLog(NVEvoLogType logType, NvU8 gpuLogIndex,
205 const char *fmt, va_list ap);
206
207 void nvEvoLogDev(const NVDevEvoRec *pDevEvo, NVEvoLogType logType,
208 const char *fmt, ...)
209 __attribute__((format (printf, 3, 4)));
210
211 void nvEvoLogDisp(const NVDispEvoRec *pDispEvo, NVEvoLogType logType,
212 const char *fmt, ...)
213 __attribute__((format (printf, 3, 4)));
214
215 void nvEvoLog(NVEvoLogType logType, const char *fmt, ...)
216 __attribute__((format (printf, 2, 3)));
217
218
219
220 #if defined(DEBUG)
221
222 void nvEvoLogDebug(NVEvoLogType logType, const char *fmt, ...)
223 __attribute__((format (printf, 2, 3)));
224
225 void nvEvoLogDevDebug(const NVDevEvoRec *pDevEvo, NVEvoLogType logType,
226 const char *fmt, ...)
227 __attribute__((format (printf, 3, 4)));
228
229 void nvEvoLogDispDebug(const NVDispEvoRec *pDispEvo, NVEvoLogType logType,
230 const char *fmt, ...)
231 __attribute__((format (printf, 3, 4)));
232
233 #else
234
235 # define nvEvoLogDebug(...)
236 # define nvEvoLogDevDebug(pDevEvo, ...)
237 # define nvEvoLogDispDebug(pDispEvo, ...)
238
239 #endif /* DEBUG */
240
241 void nvInitInfoString(NVEvoInfoStringPtr pInfoString,
242 char *s, NvU16 totalLength);
243
244 void nvEvoLogInfoStringRaw(NVEvoInfoStringPtr pInfoString,
245 const char *format, ...)
246 __attribute__((format (printf, 2, 3)));
247 void nvEvoLogInfoString(NVEvoInfoStringPtr pInfoString,
248 const char *format, ...)
249 __attribute__((format (printf, 2, 3)));
250
251
252 typedef NvU32 NvKmsGenericHandle;
253
254 NvBool nvEvoApiHandlePointerIsPresent(NVEvoApiHandlesPtr pEvoApiHandles,
255 void *pointer);
256 NvKmsGenericHandle nvEvoCreateApiHandle(NVEvoApiHandlesPtr pEvoApiHandles,
257 void *pointer);
258 void *nvEvoGetPointerFromApiHandle(const NVEvoApiHandlesRec *pEvoApiHandles,
259 NvKmsGenericHandle handle);
260 void *nvEvoGetPointerFromApiHandleNext(const NVEvoApiHandlesRec *pEvoApiHandles,
261 NvKmsGenericHandle *pHandle);
262 void nvEvoDestroyApiHandle(NVEvoApiHandlesPtr pEvoApiHandles,
263 NvKmsGenericHandle handle);
264 NvBool nvEvoInitApiHandles(NVEvoApiHandlesPtr pEvoApiHandles,
265 NvU32 defaultSize);
266 void nvEvoDestroyApiHandles(NVEvoApiHandlesPtr pEvoApiHandles);
267
268 #define FOR_ALL_POINTERS_IN_EVO_API_HANDLES(_pEvoApiHandles, \
269 _pointer, _handle) \
270 for ((_handle) = 0, \
271 (_pointer) = nvEvoGetPointerFromApiHandleNext(_pEvoApiHandles, \
272 &(_handle)); \
273 (_pointer) != NULL; \
274 (_pointer) = nvEvoGetPointerFromApiHandleNext(_pEvoApiHandles, \
275 &(_handle)))
276
277
278
279 #ifdef __cplusplus
280 };
281 #endif
282
283 #endif /* __NVKMS_UTILS_H__ */
284