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