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