515.43.04

This commit is contained in:
Andy Ritger
2022-05-09 13:18:59 -07:00
commit 1739a20efc
2519 changed files with 1060036 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#if !defined(NV_FLOAT_H)
#define NV_FLOAT_H
/* Floating-point constants, expressed as integer constants */
#define NV_FLOAT_NEG_ONE 0xBF800000 /* -1.00f */
#define NV_FLOAT_NEG_QUARTER 0xBE800000 /* -0.25f */
#define NV_FLOAT_ZERO 0x00000000 /* 0.00f */
#define NV_FLOAT_QUARTER 0x3E800000 /* 0.25f */
#define NV_FLOAT_HALF 0x3F000000 /* 0.50f */
#define NV_FLOAT_ONE 0x3F800000 /* 1.00f */
#define NV_FLOAT_TWO 0x40000000 /* 2.00f */
#define NV_FLOAT_255 0x437F0000 /* 255.00f */
#define NV_FLOAT_1024 0x44800000 /* 1024.00f */
#define NV_FLOAT_65536 0x47800000 /* 65536.00f */
#endif

View File

@@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NV_ASSERT_H__
#define __NV_ASSERT_H__
#ifdef __cplusplus
extern "C" {
#endif
/*
* nvAssert() has three possible configurations: __COVERITY__, DEBUG,
* and non-DEBUG. In DEBUG builds, the includer should provide an
* implementation of nvDebugAssert().
*/
#if defined(__COVERITY__)
/*
* Coverity assert handling -- basically inform coverity that the
* condition is verified independently and coverity can assume that
* it is true.
*/
void __coverity_panic__(void);
#define nvAssert(exp) \
do { \
if (exp) { \
} else { \
__coverity_panic__(); \
} \
} while (0)
#elif defined(DEBUG)
void nvDebugAssert(const char *expString, const char *filenameString,
const char *funcString, const unsigned int lineNumber);
/*
* Assert that (exp) is TRUE. We use 'if (exp) { } else { fail }'
* instead of 'if (!(exp)) { fail }' to cause warnings when people
* accidentally write nvAssert(foo = bar) instead of nvAssert(foo ==
* bar).
*/
#define nvAssert(exp) \
do { \
if (exp) { \
} else { \
nvDebugAssert(#exp, __FILE__, __FUNCTION__, __LINE__); \
} \
} while (0)
#else
#define nvAssert(exp) {}
#endif
#ifdef __cplusplus
};
#endif
#endif /* __NV_ASSERT_H__ */

View File

@@ -0,0 +1,98 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NV_COMMON_UTILS_H__
#define __NV_COMMON_UTILS_H__
#include "nvtypes.h"
#if !defined(TRUE)
#define TRUE NV_TRUE
#endif
#if !defined(FALSE)
#define FALSE NV_FALSE
#endif
#define NV_IS_UNSIGNED(x) ((__typeof__(x))-1 > 0)
/* Get the length of a statically-sized array. */
#define ARRAY_LEN(_arr) (sizeof(_arr) / sizeof(_arr[0]))
#define NV_INVALID_HEAD 0xFFFFFFFF
#define NV_INVALID_CONNECTOR_PHYSICAL_INFORMATION (~0)
#if !defined(NV_MIN)
# define NV_MIN(a,b) (((a)<(b))?(a):(b))
#endif
#define NV_MIN3(a,b,c) NV_MIN(NV_MIN(a, b), c)
#define NV_MIN4(a,b,c,d) NV_MIN3(NV_MIN(a,b),c,d)
#if !defined(NV_MAX)
# define NV_MAX(a,b) (((a)>(b))?(a):(b))
#endif
#define NV_MAX3(a,b,c) NV_MAX(NV_MAX(a, b), c)
#define NV_MAX4(a,b,c,d) NV_MAX3(NV_MAX(a,b),c,d)
static inline int NV_LIMIT_VAL_TO_MIN_MAX(int val, int min, int max)
{
if (val < min) {
return min;
}
if (val > max) {
return max;
}
return val;
}
#define NV_ROUNDUP_DIV(x,y) ((x) / (y) + (((x) % (y)) ? 1 : 0))
/*
* Macros used for computing palette entries:
*
* NV_UNDER_REPLICATE(val, source_size, result_size) expands a value
* of source_size bits into a value of target_size bits by shifting
* the source value into the high bits and replicating the high bits
* of the value into the low bits of the result.
*
* PALETTE_DEPTH_SHIFT(val, w) maps a colormap entry for a component
* that has w bits to an appropriate entry in a LUT of 256 entries.
*/
static inline unsigned int NV_UNDER_REPLICATE(unsigned short val,
int source_size,
int result_size)
{
return (val << (result_size - source_size)) |
(val >> ((source_size << 1) - result_size));
}
static inline unsigned short PALETTE_DEPTH_SHIFT(unsigned short val, int depth)
{
return NV_UNDER_REPLICATE(val, depth, 8);
}
#endif /* __NV_COMMON_UTILS_H__ */

View File

@@ -0,0 +1,369 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2010-2014 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/*
* This header file defines the types NVDpyId and NVDpyIdList, as well
* as inline functions to manipulate these types. NVDpyId and
* NVDpyIdList should be treated as opaque by includers of this header
* file.
*/
#ifndef __NV_DPY_ID_H__
#define __NV_DPY_ID_H__
#include "nvtypes.h"
#include "nvmisc.h"
#include <nvlimits.h> /* NV_MAX_SUBDEVICES */
typedef struct {
NvU32 opaqueDpyId;
} NVDpyId;
typedef struct {
NvU32 opaqueDpyIdList;
} NVDpyIdList;
#define NV_DPY_ID_MAX_SUBDEVICES NV_MAX_SUBDEVICES
#define NV_DPY_ID_MAX_DPYS_IN_LIST 32
/*
* For use in combination with nvDpyIdToPrintFormat(); e.g.,
*
* printf("dpy id: " NV_DPY_ID_PRINT_FORMAT "\n",
* nvDpyIdToPrintFormat(dpyId));
*
* The includer should not make assumptions about the return type of
* nvDpyIdToPrintFormat().
*/
#define NV_DPY_ID_PRINT_FORMAT "0x%08x"
/* functions to return an invalid DpyId and empty DpyIdList */
static inline NVDpyId nvInvalidDpyId(void)
{
NVDpyId dpyId = { 0 };
return dpyId;
}
static inline NVDpyIdList nvEmptyDpyIdList(void)
{
NVDpyIdList dpyIdList = { 0 };
return dpyIdList;
}
static inline NVDpyIdList nvAllDpyIdList(void)
{
NVDpyIdList dpyIdList = { ~0U };
return dpyIdList;
}
static inline void
nvEmptyDpyIdListSubDeviceArray(NVDpyIdList dpyIdList[NV_DPY_ID_MAX_SUBDEVICES])
{
int dispIndex;
for (dispIndex = 0; dispIndex < NV_DPY_ID_MAX_SUBDEVICES; dispIndex++) {
dpyIdList[dispIndex] = nvEmptyDpyIdList();
}
}
/* set operations on DpyIds and DpyIdLists: Add, Subtract, Intersect, Xor */
static inline __attribute__ ((warn_unused_result))
NVDpyIdList nvAddDpyIdToDpyIdList(NVDpyId dpyId, NVDpyIdList dpyIdList)
{
NVDpyIdList tmpDpyIdList;
tmpDpyIdList.opaqueDpyIdList = dpyIdList.opaqueDpyIdList |
dpyId.opaqueDpyId;
return tmpDpyIdList;
}
/* Passing an invalid display ID makes this function return an empty list. */
static inline __attribute__ ((warn_unused_result))
NVDpyIdList nvAddDpyIdToEmptyDpyIdList(NVDpyId dpyId)
{
NVDpyIdList tmpDpyIdList;
tmpDpyIdList.opaqueDpyIdList = dpyId.opaqueDpyId;
return tmpDpyIdList;
}
static inline __attribute__ ((warn_unused_result))
NVDpyIdList nvAddDpyIdListToDpyIdList(NVDpyIdList dpyIdListA,
NVDpyIdList dpyIdListB)
{
NVDpyIdList tmpDpyIdList;
tmpDpyIdList.opaqueDpyIdList = dpyIdListB.opaqueDpyIdList |
dpyIdListA.opaqueDpyIdList;
return tmpDpyIdList;
}
/* Returns: dpyIdList - dpyId */
static inline __attribute__ ((warn_unused_result))
NVDpyIdList nvDpyIdListMinusDpyId(NVDpyIdList dpyIdList, NVDpyId dpyId)
{
NVDpyIdList tmpDpyIdList;
tmpDpyIdList.opaqueDpyIdList = dpyIdList.opaqueDpyIdList &
(~dpyId.opaqueDpyId);
return tmpDpyIdList;
}
/* Returns: dpyIdListA - dpyIdListB */
static inline __attribute__ ((warn_unused_result))
NVDpyIdList nvDpyIdListMinusDpyIdList(NVDpyIdList dpyIdListA,
NVDpyIdList dpyIdListB)
{
NVDpyIdList tmpDpyIdList;
tmpDpyIdList.opaqueDpyIdList = dpyIdListA.opaqueDpyIdList &
(~dpyIdListB.opaqueDpyIdList);
return tmpDpyIdList;
}
static inline __attribute__ ((warn_unused_result))
NVDpyIdList nvIntersectDpyIdAndDpyIdList(NVDpyId dpyId, NVDpyIdList dpyIdList)
{
NVDpyIdList tmpDpyIdList;
tmpDpyIdList.opaqueDpyIdList = dpyIdList.opaqueDpyIdList &
dpyId.opaqueDpyId;
return tmpDpyIdList;
}
static inline __attribute__ ((warn_unused_result))
NVDpyIdList nvIntersectDpyIdListAndDpyIdList(NVDpyIdList dpyIdListA,
NVDpyIdList dpyIdListB)
{
NVDpyIdList tmpDpyIdList;
tmpDpyIdList.opaqueDpyIdList = dpyIdListA.opaqueDpyIdList &
dpyIdListB.opaqueDpyIdList;
return tmpDpyIdList;
}
static inline __attribute__ ((warn_unused_result))
NVDpyIdList nvXorDpyIdAndDpyIdList(NVDpyId dpyId, NVDpyIdList dpyIdList)
{
NVDpyIdList tmpDpyIdList;
tmpDpyIdList.opaqueDpyIdList = dpyIdList.opaqueDpyIdList ^
dpyId.opaqueDpyId;
return tmpDpyIdList;
}
static inline __attribute__ ((warn_unused_result))
NVDpyIdList nvXorDpyIdListAndDpyIdList(NVDpyIdList dpyIdListA,
NVDpyIdList dpyIdListB)
{
NVDpyIdList tmpDpyIdList;
tmpDpyIdList.opaqueDpyIdList = dpyIdListA.opaqueDpyIdList ^
dpyIdListB.opaqueDpyIdList;
return tmpDpyIdList;
}
/* boolean checks */
static inline NvBool nvDpyIdIsInDpyIdList(NVDpyId dpyId,
NVDpyIdList dpyIdList)
{
return !!(dpyIdList.opaqueDpyIdList & dpyId.opaqueDpyId);
}
static inline NvBool nvDpyIdIsInvalid(NVDpyId dpyId)
{
return (dpyId.opaqueDpyId == 0);
}
static inline NvBool nvDpyIdListIsEmpty(NVDpyIdList dpyIdList)
{
return (dpyIdList.opaqueDpyIdList == 0);
}
static inline NvBool
nvDpyIdListSubDeviceArrayIsEmpty(NVDpyIdList
dpyIdList[NV_DPY_ID_MAX_SUBDEVICES])
{
int dispIndex;
for (dispIndex = 0; dispIndex < NV_DPY_ID_MAX_SUBDEVICES; dispIndex++) {
if (!nvDpyIdListIsEmpty(dpyIdList[dispIndex])) {
return NV_FALSE;
}
}
return NV_TRUE;
}
static inline NvBool nvDpyIdsAreEqual(NVDpyId dpyIdA, NVDpyId dpyIdB)
{
return (dpyIdA.opaqueDpyId == dpyIdB.opaqueDpyId);
}
static inline NvBool nvDpyIdListsAreEqual(NVDpyIdList dpyIdListA,
NVDpyIdList dpyIdListB)
{
return (dpyIdListA.opaqueDpyIdList == dpyIdListB.opaqueDpyIdList);
}
static inline NvBool nvDpyIdListIsASubSetofDpyIdList(NVDpyIdList dpyIdListA,
NVDpyIdList dpyIdListB)
{
NVDpyIdList intersectedDpyIdList =
nvIntersectDpyIdListAndDpyIdList(dpyIdListA, dpyIdListB);
return nvDpyIdListsAreEqual(intersectedDpyIdList, dpyIdListA);
}
/*
* retrieve the individual dpyIds from dpyIdList; if dpyId is invalid,
* start at the beginning of the list; otherwise, start at the dpyId
* after the specified dpyId
*/
static inline __attribute__ ((warn_unused_result))
NVDpyId nvNextDpyIdInDpyIdListUnsorted(NVDpyId dpyId, NVDpyIdList dpyIdList)
{
if (nvDpyIdIsInvalid(dpyId)) {
dpyId.opaqueDpyId = 1;
} else {
dpyId.opaqueDpyId <<= 1;
}
while (dpyId.opaqueDpyId) {
if (nvDpyIdIsInDpyIdList(dpyId, dpyIdList)) {
return dpyId;
}
dpyId.opaqueDpyId <<= 1;
}
/* no dpyIds left in dpyIdlist; return the invalid dpyId */
return nvInvalidDpyId();
}
#define FOR_ALL_DPY_IDS(_dpyId, _dpyIdList) \
for ((_dpyId) = nvNextDpyIdInDpyIdListUnsorted(nvInvalidDpyId(), \
(_dpyIdList)); \
!nvDpyIdIsInvalid(_dpyId); \
(_dpyId) = nvNextDpyIdInDpyIdListUnsorted((_dpyId), \
(_dpyIdList)))
/* report how many dpyIds are in the dpyIdList */
static inline int nvCountDpyIdsInDpyIdList(NVDpyIdList dpyIdList)
{
return nvPopCount32(dpyIdList.opaqueDpyIdList);
}
static inline int
nvCountDpyIdsInDpyIdListSubDeviceArray(NVDpyIdList
dpyIdList[NV_DPY_ID_MAX_SUBDEVICES])
{
int dispIndex, n = 0;
for (dispIndex = 0; dispIndex < NV_DPY_ID_MAX_SUBDEVICES; dispIndex++) {
n += nvCountDpyIdsInDpyIdList(dpyIdList[dispIndex]);
}
return n;
}
/* convert between dpyId/dpyIdList and NV-CONTROL values */
static inline int nvDpyIdToNvControlVal(NVDpyId dpyId)
{
return (int) dpyId.opaqueDpyId;
}
static inline int nvDpyIdListToNvControlVal(NVDpyIdList dpyIdList)
{
return (int) dpyIdList.opaqueDpyIdList;
}
static inline NVDpyId nvNvControlValToDpyId(int val)
{
NVDpyId dpyId;
dpyId.opaqueDpyId = (val == 0) ? 0 : 1 << (__builtin_ffs(val)-1);
return dpyId;
}
static inline NVDpyIdList nvNvControlValToDpyIdList(int val)
{
NVDpyIdList dpyIdList;
dpyIdList.opaqueDpyIdList = val;
return dpyIdList;
}
/* convert between dpyId and NvU32 */
static inline NVDpyId nvNvU32ToDpyId(NvU32 val)
{
NVDpyId dpyId;
dpyId.opaqueDpyId = (val == 0) ? 0 : 1 << (__builtin_ffs(val)-1);
return dpyId;
}
static inline NVDpyIdList nvNvU32ToDpyIdList(NvU32 val)
{
NVDpyIdList dpyIdList;
dpyIdList.opaqueDpyIdList = val;
return dpyIdList;
}
static inline NvU32 nvDpyIdToNvU32(NVDpyId dpyId)
{
return dpyId.opaqueDpyId;
}
static inline NvU32 nvDpyIdListToNvU32(NVDpyIdList dpyIdList)
{
return dpyIdList.opaqueDpyIdList;
}
/* Return the bit position of dpyId: a number in the range [0..31]. */
static inline NvU32 nvDpyIdToIndex(NVDpyId dpyId)
{
return __builtin_ffs(dpyId.opaqueDpyId) - 1;
}
/* Return a display ID that is not in the list passed in. */
static inline NVDpyId nvNewDpyId(NVDpyIdList excludeList)
{
NVDpyId dpyId;
if (~excludeList.opaqueDpyIdList == 0) {
return nvInvalidDpyId();
}
dpyId.opaqueDpyId =
1U << (__builtin_ffs(~excludeList.opaqueDpyIdList) - 1);
return dpyId;
}
/* See comment for NV_DPY_ID_PRINT_FORMAT. */
static inline NvU32 nvDpyIdToPrintFormat(NVDpyId dpyId)
{
return nvDpyIdToNvU32(dpyId);
}
/* Prevent usage of opaque values. */
#define opaqueDpyId __ERROR_ACCESS_ME_VIA_NV_DPY_ID_H
#define opaqueDpyIdList __ERROR_ACCESS_ME_VIA_NV_DPY_ID_H
#endif /* __NV_DPY_ID_H__ */

View File

@@ -0,0 +1,163 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NV_MODE_TIMINGS_H__
#define __NV_MODE_TIMINGS_H__
#include "nvtypes.h"
/*
* NvModeTimings: hardware-independent modetiming structure.
*
* For interlaced modes, the vertical values are stored in frame size,
* rather than field size (e.g., for 1080i modes, vVisible is 1080,
* not 540); similarly, for doublescan modes, the vertical values are
* stored in normal framesize (not doubled vertically).
*
* RRx1k should be field rate for interlaced modes, and should be
* frame rate for doubleScan modes; e.g., 1920x1080@60i and
* 640x480@60d, not 1920x1080@30i or 640x480@120d.
*
* RRx1k is also the "real" refresh rate (time spent displaying one eye)
* for HDMI 3D frame packed modes, e.g. 47940 (2x24hz) for 1920x1080@24
* HDMI 3D mode. This needs to be halved again for all user-visible reported
* refresh rates (which needs to report time spent between each vblank, or
* each pair of eyes).
*
* pixelClock is doubled for doubleScan and HDMI 3D frame packed modes.
*
* The intent is that this structure match the X configuration file
* ModeLine.
*
* hdmi3D reflects whether this mode is a HDMI 3D frame packed mode. True only
* if the user selected HDMI 3D stereo mode and the GPU supports it. If true,
* then pixelClock is doubled.
*
* yuv420Mode reflects whether this mode requires YUV 4:2:0 decimation into a
* half-width output through headsurface (SW YUV420) or >=nvdisplay 4.0 HW CSC
* (HW YUV420).
*
* If a mode requires SW YUV 4:2:0 emulation, the pixelClock and width values
* in NvModeTimings will still be the full width values specified by the mode
* parsed from the EDID (e.g. 3840x2160@60), but the pixelClock and width values
* in NVHwModeTimingsEvo will be the "real" half width values programmed in HW
* and rendered to through a headSurface transform (e.g. 1920x2160@60). If a
* mode requires HW YUV 4:2:0 CSC, the pixelClock and width values in both
* NvModeTimings and NVHwModeTimingsEvo will be full width, and the decimation
* to the half width scanout surface is performed in HW. In both cases, only
* the full width values should ever be reported to the client.
*/
enum NvYuv420Mode {
NV_YUV420_MODE_NONE = 0,
NV_YUV420_MODE_SW,
NV_YUV420_MODE_HW,
};
typedef struct _NvModeTimings {
NvU32 RRx1k;
NvU32 pixelClockHz; /* in Hz units */
NvU16 hVisible;
NvU16 hSyncStart;
NvU16 hSyncEnd;
NvU16 hTotal;
NvU16 hSkew; /* Just placeholder for XRRModeInfo.hSkew */
NvU16 vVisible;
NvU16 vSyncStart;
NvU16 vSyncEnd;
NvU16 vTotal;
struct {
NvU16 w;
NvU16 h;
} sizeMM;
NvBool interlaced;
NvBool doubleScan;
/*
* Note: hSyncPos and vSyncPos are ignored, and the polarity is positive if
* [hv]SyncNeg is false. However, X.Org has separate flags for each, and
* treats modes with positive, negative, both, and neither as separate
* modes.
*/
NvBool hSyncPos;
NvBool hSyncNeg;
NvBool vSyncPos;
NvBool vSyncNeg;
NvBool hdmi3D;
enum NvYuv420Mode yuv420Mode;
} NvModeTimings, *NvModeTimingsPtr;
static inline NvBool NvModeTimingsMatch(const NvModeTimings *pA,
const NvModeTimings *pB,
NvBool ignoreSizeMM,
NvBool ignoreRRx1k)
{
/*
* Ignore sizeMM and/or RRx1k, if requested. The sizeMM and RRx1k fields
* don't impact hardware modetiming values, so it is reasonable that some
* callers may choose to ignore them when comparing NvModeTimings.
*/
NvBool sizeMMmatches = ignoreSizeMM || ((pA->sizeMM.w == pB->sizeMM.w) &&
(pA->sizeMM.h == pB->sizeMM.h));
NvBool rrx1kMatches = ignoreRRx1k || (pA->RRx1k == pB->RRx1k);
return (sizeMMmatches && rrx1kMatches &&
(pA->pixelClockHz == pB->pixelClockHz) &&
(pA->hVisible == pB->hVisible) &&
(pA->hSyncStart == pB->hSyncStart) &&
(pA->hSyncEnd == pB->hSyncEnd) &&
(pA->hTotal == pB->hTotal) &&
(pA->hSkew == pB->hSkew) &&
(pA->vVisible == pB->vVisible) &&
(pA->vSyncStart == pB->vSyncStart) &&
(pA->vSyncEnd == pB->vSyncEnd) &&
(pA->vTotal == pB->vTotal) &&
(pA->interlaced == pB->interlaced) &&
(pA->doubleScan == pB->doubleScan) &&
(pA->hSyncPos == pB->hSyncPos) &&
(pA->hSyncNeg == pB->hSyncNeg) &&
(pA->vSyncPos == pB->vSyncPos) &&
(pA->vSyncNeg == pB->vSyncNeg) &&
(pA->hdmi3D == pB->hdmi3D) &&
(pA->yuv420Mode == pB->yuv420Mode));
}
/*
* Convert between Hz and kHz.
*
* Note that Hz ==> kHz ==> Hz is lossy.
*
* We do +500 before /1000 in order to round, rather than truncate.
*/
static inline NvU32 HzToKHz(NvU32 hz)
{
return (hz + 500) / 1000;
}
static inline NvU32 KHzToHz(NvU32 kHz)
{
return kHz * 1000;
}
#endif /* __NV_MODE_TIMINGS_H__ */

View File

@@ -0,0 +1,62 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NV_MEMORY_TRACKER_H__
#define __NV_MEMORY_TRACKER_H__
#include "nv_list.h"
#include <stddef.h> /* size_t */
/*
* The following functions allocate and free memory, and track the
* allocations in a linked list, such that the includer can call
* nvMemoryTrackerPrintUnfreedAllocations() to print any leaked
* allocations.
*/
void *nvMemoryTrackerTrackedAlloc(NVListPtr list, size_t size,
int line, const char *file);
void *nvMemoryTrackerTrackedCalloc(NVListPtr list, size_t nmemb, size_t size,
int line, const char *file);
void *nvMemoryTrackerTrackedRealloc(NVListPtr list, void *ptr, size_t size,
int line, const char *file);
void nvMemoryTrackerTrackedFree(void *ptr);
void nvMemoryTrackerPrintUnfreedAllocations(NVListPtr list);
/*
* Users of nv_memory_tracker must provide implementations of the
* following helper functions.
*/
void *nvMemoryTrackerAlloc(size_t size);
void nvMemoryTrackerFree(void *ptr, size_t size);
void nvMemoryTrackerPrintf(const char *format, ...)
__attribute__((format (printf, 1, 2)));
void nvMemoryTrackerMemset(void *s, int c, size_t n);
void nvMemoryTrackerMemcpy(void *dest, const void *src, size_t n);
#endif /* __NV_MEMORY_TRACKER_H__ */

View File

@@ -0,0 +1,135 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NV_MODE_TIMINGS_UTILS_H__
#define __NV_MODE_TIMINGS_UTILS_H__
/*
* Utility code to operate on NvModeTimings and NVT_TIMINGs.
*/
#include "nvtypes.h"
#include "nv_mode_timings.h"
#include "timing/nvtiming.h"
#include <stddef.h> /* size_t */
/*
* Macros used for printing values divided by 1000 without floating
* point division and printing.
*
* Example:
* printf("pclk is %.2f MHz\n", pclk_khz / 1000.0f);
* becomes:
* printf("pclk is " NV_FMT_DIV_1000_POINT_2 " MHz\n",
* NV_VA_DIV_1000_POINT_2(pclk_khz));
*
* Different precision controls the number of digits printed after the
* decimal point. Bias is added for correct rounding.
*/
#define NV_FMT_DIV_1000_POINT_1 "%d.%d"
#define NV_FMT_DIV_1000_POINT_2 "%d.%02d"
#define NV_VA_DIV_1000_POINT_1(x) \
((x) + 49) / 1000, (((x) + 49) % 1000) / 100
#define NV_VA_DIV_1000_POINT_2(x) \
((x) + 4) / 1000, (((x) + 4) % 1000) / 10
/*
* macro to use integer math to convert an NvU32 kHz value to Hz; we
* add 500 Hz before dividing by 1000 to round rather than truncate.
*/
#define NV_U32_KHZ_TO_HZ(_x) (((_x) + 500) / 1000)
/*
* NVT_TIMING stores HVisible multiplied by the horizontal replication
* factor (e.g., a 720 mode with hrep=2 has HVisible of 1440). For
* reporting purposes, divide HVisible by hrep.
*/
static inline NvU16 NV_NVT_TIMING_HVISIBLE(const NVT_TIMING *pTiming)
{
if (pTiming->etc.rep > 1) {
return pTiming->HVisible / pTiming->etc.rep;
} else {
return pTiming->HVisible;
}
}
/*
* NVT_TIMING stores VVisible as half height when interlaced (e.g.,
* 1920x1080i has VVisible 540).
*/
static inline NvU16 NV_NVT_TIMING_VVISIBLE(const NVT_TIMING *pTiming)
{
return pTiming->VVisible * (pTiming->interlaced ? 2 : 1);
}
/*
* When non-zero, NVT_TIMING::etc::aspect contains bytes 12, 13, and
* 14 from the Detailed Timing Definition of the EDID. This contains
* a packed width and height. The width and height is either an
* aspect ratio (16:9 or 4:3), or a physical image size in
* millimeters. See Table 3.21, and the subsequent notes, in the
* E-EDID 1.4 specification.
*/
static inline NvU16 NV_NVT_TIMING_IMAGE_SIZE_WIDTH(const NVT_TIMING *pTiming)
{
return (pTiming->etc.aspect >> 16) & 0xFFFF;
}
static inline NvU16 NV_NVT_TIMING_IMAGE_SIZE_HEIGHT(const NVT_TIMING *pTiming)
{
return pTiming->etc.aspect & 0xFFFF;
}
static inline NvBool NV_NVT_TIMING_HAS_ASPECT_RATIO(const NVT_TIMING *pTiming)
{
NvU16 w = NV_NVT_TIMING_IMAGE_SIZE_WIDTH(pTiming);
NvU16 h = NV_NVT_TIMING_IMAGE_SIZE_HEIGHT(pTiming);
return (((w == 16) && (h == 9)) ||
((w == 4) && (h == 3)));
}
static inline NvBool NV_NVT_TIMING_HAS_IMAGE_SIZE(const NVT_TIMING *pTiming)
{
return ((pTiming->etc.aspect != 0) &&
!NV_NVT_TIMING_HAS_ASPECT_RATIO(pTiming));
}
NvBool IsEdid640x480_60_NVT_TIMING(const NVT_TIMING *pTiming);
void NVT_TIMINGtoNvModeTimings(const NVT_TIMING *pTiming,
NvModeTimingsPtr pModeTimings);
void nvBuildModeName(NvU16 width, NvU16 height, char *name, size_t nameLen);
/*
* Users of nvBuildModeName() should provide an implementation of
* nvBuildModeNameSnprintf().
*/
int nvBuildModeNameSnprintf(char *str, size_t size, const char *format, ...)
__attribute__((format (printf, 3, 4)));
#endif /* __NV_MODE_TIMINGS_UTILS_H__ */

View File

@@ -0,0 +1,65 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2003-2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NV_VASPRINTF_H__
#define __NV_VASPRINTF_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include <stddef.h>
/*
* nv_vasprintf() depends on nv_vasprintf_{alloc,free,vsnprintf}().
* Those functions should be implemented by the user of
* nv_vasprintf().
*/
void *nv_vasprintf_alloc(size_t size);
void nv_vasprintf_free(void *ptr);
int nv_vasprintf_vsnprintf(char *str, size_t size,
const char *format, va_list ap);
char* nv_vasprintf(const char *f, va_list ap);
/*
* NV_VSNPRINTF(): macro that assigns b using nv_vasprintf(); intended to
* be used by vararg printing functions.
*
* This macro allocates memory for b; the caller should free the
* memory when done.
*/
#define NV_VSNPRINTF(b, f) do { \
va_list ap; \
va_start(ap, f); \
(b) = nv_vasprintf(f, ap); \
va_end(ap); \
} while(0)
#ifdef __cplusplus
};
#endif
#endif /* __NV_VASPRINTF_H__ */

View File

@@ -0,0 +1,122 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2014 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __UNIX_RM_HANDLE_H__
#define __UNIX_RM_HANDLE_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "nvtypes.h"
#define NV_UNIX_RM_HANDLE_INITIAL_HANDLES 512
#define NV_UNIX_RM_HANDLE_BITMAP_SIZE(_numHandles) ((_numHandles) >> 5)
#if defined(DEBUG)
typedef struct _nv_unix_rm_handle_allocation *NVUnixRmHandleAllocationPtr;
typedef struct _nv_unix_rm_handle_allocation {
const char *file;
int line;
} NVUnixRmHandleAllocationRec;
#endif
typedef struct _nv_unix_rm_handle_allocator *NVUnixRmHandleAllocatorPtr;
typedef struct _nv_unix_rm_handle_allocator {
NvU32 rmClient;
NvU32 clientData;
NvU32 *bitmap;
NvU32 maxHandles;
#if defined(DEBUG)
NVUnixRmHandleAllocationRec *allocationTable;
#endif
} NVUnixRmHandleAllocatorRec;
NvBool nvInitUnixRmHandleAllocator(NVUnixRmHandleAllocatorPtr pAllocator,
NvU32 rmClient, NvU32 clientData);
NvU32 nvGenerateUnixRmHandleInternal(NVUnixRmHandleAllocatorPtr pAllocator);
void nvFreeUnixRmHandleInternal(NVUnixRmHandleAllocatorPtr pAllocator,
NvU32 UnixRmHandle);
void nvTearDownUnixRmHandleAllocator(NVUnixRmHandleAllocatorPtr pAllocator);
#if defined(DEBUG)
#define NV_UNIX_RM_HANDLE_DEBUG_ERROR 0
#define NV_UNIX_RM_HANDLE_DEBUG_MSG 1
#define NV_UNIX_RM_HANDLE_DEBUG_VERBOSE 2
/*
* Users of the handle generator need to provide implementations
* of nvUnixRmHandleDebugAssert() and nvUnixRmHandleLogMsg()
* in builds where DEBUG is defined.
*/
void nvUnixRmHandleDebugAssert(const char *expString,
const char *filenameString,
const char *funcString,
const unsigned lineNumber);
#define nvUnixRmHandleAssert(_exp) \
do { \
if (_exp) { \
} else { \
nvUnixRmHandleDebugAssert(#_exp, __FILE__, __FUNCTION__, __LINE__); \
} \
} while (0)
void nvUnixRmHandleLogMsg(NvU32 level, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
NvU32 nvDebugGenerateUnixRmHandle(NVUnixRmHandleAllocatorPtr pAllocator,
const char *file, int line);
#define nvGenerateUnixRmHandle(s) \
nvDebugGenerateUnixRmHandle((s), __FILE__, __LINE__)
void nvDebugFreeUnixRmHandle(NVUnixRmHandleAllocatorPtr pAllocator, NvU32 handle);
#define nvFreeUnixRmHandle(n,s) nvDebugFreeUnixRmHandle((n), (s))
#else
#define nvUnixRmHandleAssert(_exp) do {} while(0)
#define nvUnixRmHandleLogMsg(__fmt, ...) do {} while(0)
#define nvGenerateUnixRmHandle(s) nvGenerateUnixRmHandleInternal((s))
#define nvFreeUnixRmHandle(n, s) nvFreeUnixRmHandleInternal((n), (s))
#endif /* DEBUG */
/*
* Users of the handle generator always need to provide implementations
* of nvUnixRmHandleReallocMem(), and nvUnixRmHandleFreeMem().
*/
void *nvUnixRmHandleReallocMem(void *oldPtr, NvLength newSize);
void nvUnixRmHandleFreeMem(void *ptr);
#ifdef __cplusplus
};
#endif
#endif

View File

@@ -0,0 +1,230 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#if defined(DEBUG)
#include "nv_memory_tracker.h"
/*
* Define NV_MEMORY_TRACKER_BACKTRACES in the including makefile to enable
* backtrace capture/reporting for memory leaks. E.g.,
* NV_DEFINES += NV_MEMORY_TRACKER_BACKTRACES
* Note that this probably only works with glibc (backtrace() and friends are
* GNU extensions).
*/
#if defined(NV_MEMORY_TRACKER_BACKTRACES)
#include <execinfo.h> /* backtrace() and backtrace_symbols() */
#include <stdlib.h> /* free(3) */
#define MAX_BACKTRACE_DEPTH 30
#endif
typedef union {
struct {
NVListRec entry;
const char *file;
int line;
size_t size;
#if defined(NV_MEMORY_TRACKER_BACKTRACES)
void *backtrace[MAX_BACKTRACE_DEPTH];
int backtraceSize;
#endif
} header;
/*
* Unused. For alignment purposes only. Guarantee alignment to
* twice pointer size. That is the alignment guaranteed by glibc:
* http://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html
* which seems reasonable to match here.
*/
NvU8 align __attribute__((aligned(sizeof(void*) * 2)));
} NvMemoryAllocation;
static void PrintAllocationBacktrace(const NvMemoryAllocation *alloc)
{
#if defined(NV_MEMORY_TRACKER_BACKTRACES)
char **symbols;
const int numSymbols = alloc->header.backtraceSize;
int j;
symbols = backtrace_symbols(alloc->header.backtrace, numSymbols);
if (symbols == NULL) {
return;
}
nvMemoryTrackerPrintf("Allocation context:");
for (j = 0; j < numSymbols; j++) {
if (symbols[j] == NULL) {
continue;
}
nvMemoryTrackerPrintf("#%-2d %s", j, symbols[j]);
}
free(symbols);
#endif
}
static void RegisterAllocation(NVListPtr list, NvMemoryAllocation *alloc,
const char *file, int line, size_t size)
{
nvListAdd(&alloc->header.entry, list);
alloc->header.file = file;
alloc->header.line = line;
alloc->header.size = size;
#if defined(NV_MEMORY_TRACKER_BACKTRACES)
/* Record the backtrace at this point (only addresses, not symbols) */
alloc->header.backtraceSize =
backtrace(alloc->header.backtrace, MAX_BACKTRACE_DEPTH);
#endif
}
static NvBool IsAllocationSane(NvMemoryAllocation *alloc)
{
NVListPtr entry = &alloc->header.entry;
if (entry->prev->next != entry || entry->next->prev != entry) {
/*
* This will likely have already crashed, but we might as well
* report it if we can.
*/
nvMemoryTrackerPrintf("Attempted to free untracked memory %p!",
alloc + 1);
return NV_FALSE;
}
return NV_TRUE;
}
static void UnregisterAllocation(NvMemoryAllocation *alloc)
{
if (!IsAllocationSane(alloc)) {
return;
}
nvListDel(&alloc->header.entry);
}
void *nvMemoryTrackerTrackedAlloc(NVListPtr list, size_t size,
int line, const char *file)
{
NvMemoryAllocation *alloc = nvMemoryTrackerAlloc(sizeof(*alloc) + size);
if (alloc == NULL) {
return NULL;
}
RegisterAllocation(list, alloc, file, line, size);
return alloc + 1;
}
void *nvMemoryTrackerTrackedCalloc(NVListPtr list, size_t nmemb, size_t size,
int line, const char *file)
{
size_t totalSize = size * nmemb;
void *ptr = nvMemoryTrackerTrackedAlloc(list, totalSize, line, file);
if (ptr == NULL) {
return NULL;
}
nvMemoryTrackerMemset(ptr, 0, totalSize);
return ptr;
}
void *nvMemoryTrackerTrackedRealloc(NVListPtr list, void *ptr, size_t size,
int line, const char *file)
{
NvMemoryAllocation *oldAlloc = NULL;
void *newptr;
if (ptr == NULL) {
/* realloc with a ptr of NULL is equivalent to malloc. */
return nvMemoryTrackerTrackedAlloc(list, size, line, file);
}
if (size == 0) {
/* realloc with a size of 0 is equivalent to free. */
nvMemoryTrackerTrackedFree(ptr);
return NULL;
}
oldAlloc = ((NvMemoryAllocation *) ptr) - 1;
newptr = nvMemoryTrackerTrackedAlloc(list, size, line, file);
if (newptr != NULL) {
nvMemoryTrackerMemcpy(newptr, ptr, NV_MIN(size, oldAlloc->header.size));
nvMemoryTrackerTrackedFree(ptr);
}
return newptr;
}
void nvMemoryTrackerTrackedFree(void *ptr)
{
NvMemoryAllocation *alloc;
size_t size;
if (ptr == NULL) {
return;
}
alloc = ((NvMemoryAllocation *) ptr) - 1;
UnregisterAllocation(alloc);
size = alloc->header.size + sizeof(NvMemoryAllocation);
/* Poison the memory. */
nvMemoryTrackerMemset(alloc, 0x55, size);
nvMemoryTrackerFree(alloc, size);
}
void nvMemoryTrackerPrintUnfreedAllocations(NVListPtr list)
{
NvMemoryAllocation *iter;
nvListForEachEntry(iter, list, header.entry) {
nvMemoryTrackerPrintf("Unfreed allocation: %18p (size: %5u) (%s:%d)",
iter + 1,
(unsigned int) iter->header.size,
iter->header.file,
iter->header.line);
PrintAllocationBacktrace(iter);
}
}
#endif /* defined(DEBUG) */

View File

@@ -0,0 +1,159 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "nv_mode_timings_utils.h"
/*
* Check if this NVT_TIMING is the 640x480@60Hz Industry standard
* mode; but due to the lack of precision of the pclk field in the
* NVT_TIMING data structure, is not quite correct: pclk should be
* 2517.5, and rrx1k should be 59940. See bug 263631.
*
* Note that we check if rrx1k is either 60000 or 59940 because we may
* use this function immediately after receiving the NVT_TIMINGs from
* the EDID and patch rrx1k, or we may use this function later from
* NVT_TIMINGtoNvModeTimings(), at which point we'll have already
* patched rrx1k.
*/
NvBool IsEdid640x480_60_NVT_TIMING(const NVT_TIMING *pTiming)
{
return ((pTiming->pclk == 2518) &&
(pTiming->HVisible == 640) &&
(pTiming->VVisible == 480) &&
(pTiming->HTotal == 800) &&
(pTiming->HFrontPorch == 16) &&
(pTiming->HSyncWidth == 96) &&
(pTiming->VTotal == 525) &&
(pTiming->VFrontPorch == 10) &&
(pTiming->VSyncWidth == 2) &&
(pTiming->HBorder == 0) &&
(pTiming->VBorder == 0) &&
(pTiming->HSyncPol == NVT_H_SYNC_NEGATIVE) &&
(pTiming->VSyncPol == NVT_V_SYNC_NEGATIVE) &&
(pTiming->interlaced == 0) &&
((pTiming->etc.flag &
NVT_FLAG_NV_DOUBLE_SCAN_TIMING) == 0) &&
((pTiming->etc.rrx1k == 60000) ||
(pTiming->etc.rrx1k == 59940)));
}
/*
* Convert from NVT_TIMING to NvModeTimings; this is a safe operation
* to perform because NvModeTimings has higher precision (pixelclockHz
* in Hz, and vertical values doubled for interlaced) than NVT_TIMING
*/
void NVT_TIMINGtoNvModeTimings(const NVT_TIMING *pTiming,
NvModeTimingsPtr pModeTimings)
{
char *bytePtr = (char *)pModeTimings;
size_t i;
for (i = 0; i < sizeof(*pModeTimings); i++) {
bytePtr[i] = 0;
}
pModeTimings->RRx1k = pTiming->etc.rrx1k;
/* pTiming->pclk is in 10*kHz; pModeTimings->pixelClockHz is in Hz */
pModeTimings->pixelClockHz = KHzToHz(pTiming->pclk) * 10;
pModeTimings->hVisible = pTiming->HVisible;
pModeTimings->hSyncStart = pTiming->HFrontPorch + pTiming->HVisible;
pModeTimings->hSyncEnd =
pTiming->HFrontPorch + pTiming->HVisible + pTiming->HSyncWidth;
pModeTimings->hTotal = pTiming->HTotal;
pModeTimings->vVisible = pTiming->VVisible;
pModeTimings->vSyncStart = pTiming->VFrontPorch + pTiming->VVisible;
pModeTimings->vSyncEnd =
pTiming->VFrontPorch + pTiming->VVisible + pTiming->VSyncWidth;
pModeTimings->vTotal = pTiming->VTotal;
pModeTimings->interlaced = pTiming->interlaced;
pModeTimings->doubleScan =
!!(pTiming->etc.flag & NVT_FLAG_NV_DOUBLE_SCAN_TIMING);
/*
* pTiming stores vertical values divided by two when interlaced; so
* double the vertical values in pModeTimings
*/
if (pModeTimings->interlaced) {
pModeTimings->vVisible *= 2;
pModeTimings->vSyncStart *= 2;
pModeTimings->vSyncEnd *= 2;
pModeTimings->vTotal *= 2;
}
/*
* pTiming: 0 is positive, 1 is negative
* pModeTimings: FALSE is positive, TRUE is negative
*/
if (pTiming->HSyncPol == NVT_H_SYNC_POSITIVE) {
pModeTimings->hSyncNeg = NV_FALSE;
} else {
pModeTimings->hSyncNeg = NV_TRUE;
}
if (pTiming->VSyncPol == NVT_V_SYNC_POSITIVE) {
pModeTimings->vSyncNeg = NV_FALSE;
} else {
pModeTimings->vSyncNeg = NV_TRUE;
}
pModeTimings->hSyncPos = !pModeTimings->hSyncNeg;
pModeTimings->vSyncPos = !pModeTimings->vSyncNeg;
/*
* Save any physical size information for this mode from the
* Detailed Timing Definition of the EDID.
*/
if (NV_NVT_TIMING_HAS_IMAGE_SIZE(pTiming)) {
pModeTimings->sizeMM.w = NV_NVT_TIMING_IMAGE_SIZE_WIDTH(pTiming);
pModeTimings->sizeMM.h = NV_NVT_TIMING_IMAGE_SIZE_HEIGHT(pTiming);
}
/*
* XXX work around lack of precision in NVT_TIMING: catch the
* 640x480@60Hz EDID mode and patch pixelClockHz and RRx1k.
*/
if (IsEdid640x480_60_NVT_TIMING(pTiming)) {
pModeTimings->RRx1k = 59940;
pModeTimings->pixelClockHz = 25175000;
}
}
/*!
* Build a mode name, of the format 'WIDTHxHEIGHT'.
*/
void nvBuildModeName(NvU16 width, NvU16 height, char *name, size_t nameLen)
{
nvBuildModeNameSnprintf(name, nameLen, "%dx%d", width, height);
name[nameLen - 1] = '\0';
}

View File

@@ -0,0 +1,74 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2003-2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "nv_vasprintf.h"
/*
* nv_vasprintf(): function that returns a string using vsnprintf(); intended to
* be used by vararg printing functions. This is supposedly correct
* for differing semantics of vsnprintf() in different versions of
* glibc:
*
* different semantics of the return value from (v)snprintf:
*
* -1 when the buffer is not long enough (glibc < 2.1)
*
* or
*
* the length the string would have been if the buffer had been large
* enough (glibc >= 2.1)
*
* This function allocates memory for the returned string; the caller should use
* free() the memory when done.
*
* The includer should implement nv_vasprintf_{alloc,free,vsnprintf}.
*/
#define __NV_VASPRINTF_LEN 64
char* nv_vasprintf(const char *f, va_list ap)
{
int len, current_len = __NV_VASPRINTF_LEN;
char *b = (char *)nv_vasprintf_alloc(current_len);
while (b) {
va_list tmp_ap;
va_copy(tmp_ap, ap);
len = nv_vasprintf_vsnprintf(b, current_len, f, tmp_ap);
va_end(tmp_ap);
if ((len > -1) && (len < current_len)) {
break;
} else if (len > -1) {
current_len = len + 1;
} else {
current_len += __NV_VASPRINTF_LEN;
}
nv_vasprintf_free(b);
b = (char *)nv_vasprintf_alloc(current_len);
}
return b;
}

View File

@@ -0,0 +1,385 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 1993-2014 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/*
* This file contains functions for dealing with dynamic allocation and
* management of resource handles.
*
* Note that dynamic handles are not suitable for all use cases. If a
* handle is placed in the pushbuffer, and the pushbuffer will be
* replayed during channel recovery, the handle value must be kept
* constant. For such handles, use an invariant handle value.
*
* We keep a bitmap of which handles we've used.
*
* Composition of an object handle:
* [31:16] Client data
* [15:00] Handle constant
*/
#include <stddef.h>
#include "unix_rm_handle.h"
#define INVALID_HANDLE 0
#define UNIX_RM_HANDLE_CLIENT_DATA_SHIFT 16
/* Mask to AND only client data */
#define CLIENT_DATA_MASK ((~(NvU32)0) << UNIX_RM_HANDLE_CLIENT_DATA_SHIFT)
/* Mask to AND off client data */
#define HANDLE_MASK (~(CLIENT_DATA_MASK))
/* Handle 0 is reserved, so subtract one from a handle to get its index */
#define HANDLE_INDEX(_handle) (((_handle) - 1) & HANDLE_MASK)
/* Bits to OR in for client data */
#define GET_CLIENT_DATA_BITS(_data) \
(((_data) << UNIX_RM_HANDLE_CLIENT_DATA_SHIFT))
#define DWORD_FROM_HANDLE(_handle) (HANDLE_INDEX(_handle) >> 5)
#define BIT_FROM_HANDLE(_handle) (HANDLE_INDEX(_handle) & 0x1f)
/* Check if a handle is used */
#define USED(_bitmap, _handle) \
((_bitmap)[DWORD_FROM_HANDLE(_handle)] & (1U << BIT_FROM_HANDLE(_handle)))
/* Reserve a handle in the bitmap */
#define RESERVE(_bitmap, _handle) \
((_bitmap)[DWORD_FROM_HANDLE(_handle)] |= (1U << BIT_FROM_HANDLE(_handle)))
/* Unreserve a handle in the bitmap */
#define UNRESERVE(_bitmap, _handle) \
((_bitmap)[DWORD_FROM_HANDLE(_handle)] &= (~(1U << BIT_FROM_HANDLE(_handle))))
#if defined(DEBUG)
static void
nvReportUnfreedUnixRmHandleAllocations(NVUnixRmHandleAllocatorPtr pAllocator);
#endif
static void UnixRmHandleMemset(void *ptr, char data, NvLength size)
{
char *byte = (char *)ptr;
NvLength i;
for (i = 0; i < size; i++) {
byte[i] = data;
}
}
static NvBool UnixRmHandleReallocBitmap(NVUnixRmHandleAllocatorPtr pAllocator,
NvU32 newMaxHandles)
{
NvU32 *newBitmap;
#if defined(DEBUG)
NVUnixRmHandleAllocationPtr newAllocationTable;
#endif /* defined(DEBUG) */
const NvLength newMemSize = NV_UNIX_RM_HANDLE_BITMAP_SIZE(newMaxHandles) *
sizeof(*newBitmap);
const NvU32 oldBitmapSize =
NV_UNIX_RM_HANDLE_BITMAP_SIZE(pAllocator->maxHandles);
/* New handle limit must fit in the bitmask */
if (newMaxHandles > GET_CLIENT_DATA_BITS(1)) {
return NV_FALSE;
}
/* New handle limit must be a power of 2 */
nvUnixRmHandleAssert(!(newMaxHandles & (newMaxHandles - 1)));
newBitmap = (NvU32 *)nvUnixRmHandleReallocMem(pAllocator->bitmap, newMemSize);
if (!newBitmap) {
return NV_FALSE;
}
UnixRmHandleMemset(&newBitmap[oldBitmapSize], 0,
newMemSize - (oldBitmapSize * sizeof(*newBitmap)));
pAllocator->bitmap = newBitmap;
#if defined(DEBUG)
newAllocationTable =
(NVUnixRmHandleAllocationPtr)
nvUnixRmHandleReallocMem(pAllocator->allocationTable,
newMaxHandles *
sizeof(*pAllocator->allocationTable));
if (!newAllocationTable) {
/*
* Leave the new bitmap allocation in place. If that realloc
* succeeded, the old bitmap allocation is gone, and it is at
* least big enough to hold the old pAllocator->maxHandles,
* since a shrinking of the allocation table shouldn't have
* failed, and maxHandles currently never decreases anyway.
*/
nvUnixRmHandleAssert(newMaxHandles >= pAllocator->maxHandles);
return NV_FALSE;
}
pAllocator->allocationTable = newAllocationTable;
#endif /* defined(DEBUG) */
pAllocator->maxHandles = newMaxHandles;
return NV_TRUE;
}
NvBool nvInitUnixRmHandleAllocator(NVUnixRmHandleAllocatorPtr pAllocator,
NvU32 rmClient, NvU32 clientData)
{
nvUnixRmHandleAssert(pAllocator != NULL &&
rmClient != 0 && clientData != 0);
nvUnixRmHandleAssert((clientData & 0x0000FFFF) == clientData);
UnixRmHandleMemset(pAllocator, 0, sizeof(*pAllocator));
pAllocator->rmClient = rmClient;
pAllocator->clientData = clientData;
if (!UnixRmHandleReallocBitmap(pAllocator,
NV_UNIX_RM_HANDLE_INITIAL_HANDLES)) {
nvUnixRmHandleAssert(!"Failed to init RM handle allocator bitmap");
nvTearDownUnixRmHandleAllocator(pAllocator);
return NV_FALSE;
}
/*
* If the RM-provided client handle falls within the allocator range
* then reserve it up-front.
*/
if ((pAllocator->rmClient & CLIENT_DATA_MASK) ==
GET_CLIENT_DATA_BITS(pAllocator->clientData)) {
NvU32 handleId = pAllocator->rmClient & HANDLE_MASK;
if ((handleId <= pAllocator->maxHandles) &&
(handleId != INVALID_HANDLE)) {
RESERVE(pAllocator->bitmap, handleId);
}
}
return NV_TRUE;
}
/*
* nvGenerateUnixRmHandleInternal()
* Return a unique, random handle. Be sure to free the handle
* when you're done with it! Returns 0 if we run out of handles.
*/
NvU32 nvGenerateUnixRmHandleInternal(NVUnixRmHandleAllocatorPtr pAllocator)
{
NvU32 handleId;
NvU32 handle;
nvUnixRmHandleAssert(pAllocator != NULL &&
pAllocator->rmClient != 0 &&
pAllocator->clientData != 0);
/* Find free handle */
handleId = 1;
while (USED(pAllocator->bitmap, handleId) &&
(handleId <= pAllocator->maxHandles)) {
handleId++;
}
if (handleId > pAllocator->maxHandles) {
if (!UnixRmHandleReallocBitmap(pAllocator, pAllocator->maxHandles * 2)) {
nvUnixRmHandleAssert(!"Failed to grow RM handle allocator bitmap");
return INVALID_HANDLE;
}
}
nvUnixRmHandleAssert(!USED(pAllocator->bitmap, handleId));
RESERVE(pAllocator->bitmap, handleId);
handle = GET_CLIENT_DATA_BITS(pAllocator->clientData) | handleId;
nvUnixRmHandleAssert(handle != pAllocator->rmClient);
return handle;
}
/*
* nvFreeUnixRmHandleInternal()
* Mark the handle passed in as free in the bitmap.
*/
void nvFreeUnixRmHandleInternal(NVUnixRmHandleAllocatorPtr pAllocator,
NvU32 unixHandle)
{
NvU32 handle = unixHandle & HANDLE_MASK;
if (!unixHandle) {
return;
}
nvUnixRmHandleAssert(pAllocator != NULL &&
pAllocator->rmClient != 0 && pAllocator->clientData != 0);
nvUnixRmHandleAssert(USED(pAllocator->bitmap, handle));
UNRESERVE(pAllocator->bitmap, handle);
}
/*
* This function just makes sure we freed all of the handles we allocated, for
* debugging purposes.
*/
void nvTearDownUnixRmHandleAllocator(NVUnixRmHandleAllocatorPtr pAllocator)
{
if (pAllocator == NULL) {
return;
}
/*
* If the RM-provided client handle falls within the allocator range,
* then it is reserved up-front. so make sure that it is get unreserved
* before teardown.
*/
if ((pAllocator->rmClient & CLIENT_DATA_MASK) ==
GET_CLIENT_DATA_BITS(pAllocator->clientData)) {
NvU32 handleId = pAllocator->rmClient & HANDLE_MASK;
if ((handleId <= pAllocator->maxHandles) &&
(handleId != INVALID_HANDLE)) {
UNRESERVE(pAllocator->bitmap, handleId);
}
}
#if defined(DEBUG)
nvReportUnfreedUnixRmHandleAllocations(pAllocator);
nvUnixRmHandleFreeMem(pAllocator->allocationTable);
#endif
nvUnixRmHandleFreeMem(pAllocator->bitmap);
UnixRmHandleMemset(pAllocator, 0, sizeof(*pAllocator));
}
/*
* Handle allocation tracking code; in a debug build, the below
* functions wrap the actual allocation functions above.
*/
#if defined(DEBUG)
#define UNIX_RM_HANDLE_ALLOC_LABEL "NVIDIA UNIX RM HANDLE TRACKER: "
static NVUnixRmHandleAllocationPtr
FindUnixRmHandleAllocation(NVUnixRmHandleAllocatorPtr pAllocator, NvU32 handle)
{
if (((handle & HANDLE_MASK) == INVALID_HANDLE) ||
((handle & HANDLE_MASK) > pAllocator->maxHandles)) {
return NULL;
}
return &pAllocator->allocationTable[HANDLE_INDEX(handle)];
}
static void RecordUnixRmHandleAllocation(NVUnixRmHandleAllocatorPtr pAllocator,
NvU32 handle, const char *file, int line)
{
/* Find a free allocation table slot. */
NVUnixRmHandleAllocationPtr alloc = FindUnixRmHandleAllocation(pAllocator, handle);
if (!alloc) {
nvUnixRmHandleLogMsg(NV_UNIX_RM_HANDLE_DEBUG_ERROR,
UNIX_RM_HANDLE_ALLOC_LABEL
"NVUnixRmHandleAllocator is corrupted."
"(table entry not found for handle)");
return;
}
nvUnixRmHandleLogMsg(NV_UNIX_RM_HANDLE_DEBUG_VERBOSE,
UNIX_RM_HANDLE_ALLOC_LABEL
"Recording handle allocation: 0x%08x (%s:%d)",
handle, file, line);
alloc->file = file;
alloc->line = line;
}
static void FreeUnixRmHandleAllocation(NVUnixRmHandleAllocatorPtr pAllocator,
NvU32 handle)
{
NVUnixRmHandleAllocationPtr alloc =
FindUnixRmHandleAllocation(pAllocator, handle);
if (!alloc) {
return;
}
nvUnixRmHandleLogMsg(NV_UNIX_RM_HANDLE_DEBUG_VERBOSE,
UNIX_RM_HANDLE_ALLOC_LABEL
"Freeing handle allocation: 0x%08x (%s:%d)",
handle, alloc->file, alloc->line);
UnixRmHandleMemset(alloc, 0, sizeof(*alloc));
}
NvU32
nvDebugGenerateUnixRmHandle(NVUnixRmHandleAllocatorPtr pAllocator,
const char *file, int line)
{
NvU32 handle = nvGenerateUnixRmHandleInternal(pAllocator);
RecordUnixRmHandleAllocation(pAllocator, handle, file, line);
return handle;
}
void nvDebugFreeUnixRmHandle(NVUnixRmHandleAllocatorPtr pAllocator, NvU32 handle)
{
if (!handle) {
return;
}
FreeUnixRmHandleAllocation(pAllocator, handle);
nvFreeUnixRmHandleInternal(pAllocator, handle);
}
void nvReportUnfreedUnixRmHandleAllocations(NVUnixRmHandleAllocatorPtr pAllocator)
{
NvU32 handleId;
for (handleId = 1; handleId <= pAllocator->maxHandles; handleId++) {
if (USED(pAllocator->bitmap, handleId)) {
NVUnixRmHandleAllocationPtr alloc =
FindUnixRmHandleAllocation(pAllocator, handleId);
if (alloc == NULL) {
continue;
}
nvUnixRmHandleLogMsg(NV_UNIX_RM_HANDLE_DEBUG_MSG,
UNIX_RM_HANDLE_ALLOC_LABEL
"Unfreed handle ID allocation: 0x%08x (%s:%d)",
handleId,
alloc->file,
alloc->line);
}
}
}
#endif /* DEBUG */