RK3368 GPU version: Rogue L 0.17

1. Support gpu disable dvfs case.
2. Add rk_tf_check_version to compatible for rk3328.
3. merge 1.4_ED3573678 DDK code.
   Tip: Need update RK3368 GPU so version to L0.17(@vendor/rockchip/common).
This commit is contained in:
zxl 2015-06-02 16:07:27 +08:00
parent 46f1476d2d
commit 5d82dfee2f
32 changed files with 1607 additions and 428 deletions

View File

@ -695,8 +695,15 @@ Enable automatic decoding of Firmware Trace via DebugFS._\
))
$(eval $(call TunableKernelConfigC,PVR_LINUX_PYSMEM_MAX_POOL_PAGES,"$(MAX_POOL_PAGES)"))
$(eval $(call TunableKernelConfigC,PVR_LINUX_VMALLOC_ALLOCATION_THRESHOLD, 16384 ))
# ARM-Linux specific:
# When allocating uncached or write-combine memory we need to invalidate the
# CPU cache before we can use the acquired pages.
# The threshhold defines at which number of pages we want to do a full
# cache flush instead of invalidating pages one by one.
$(eval $(call TunableKernelConfigC,PVR_LINUX_ARM_PAGEALLOC_FLUSH_THRESHOLD, 256))
$(eval $(call TunableKernelConfigC,PVR_LINUX_VMALLOC_ALLOCATION_THRESHOLD, 16384 ))
# Tunable RGX_MAX_TA_SYNCS / RGX_MAX_3D_SYNCS to increase the size of sync array in the DDK
# If defined, these macros take up the values as defined in the environment,

View File

@ -28,6 +28,7 @@
#define LDM_PLATFORM
#define PVRSRV_ENABLE_PROCESS_STATS
#define PVR_LINUX_PYSMEM_MAX_POOL_PAGES 10240
#define PVR_LINUX_ARM_PAGEALLOC_FLUSH_THRESHOLD 256
#define PVR_LINUX_VMALLOC_ALLOCATION_THRESHOLD 16384
#define ANDROID
#define PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC

View File

@ -42,8 +42,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef _RGXCONFIG_KM_4_V_2_51_H_
#define _RGXCONFIG_KM_4_V_2_51_H_
/***** Automatically generated file (11/24/2014 2:08:59 PM): Do not edit manually ********************/
/***** Timestamp: (11/24/2014 2:08:59 PM)************************************************************/
/***** Automatically generated file (3/5/2015 11:29:38 AM): Do not edit manually ********************/
/***** Timestamp: (3/5/2015 11:29:38 AM)************************************************************/
#define RGX_BNC_KM_B 4
#define RGX_BNC_KM_N 2
@ -59,11 +59,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define RGX_FEATURE_CLUSTER_GROUPING
#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
#define RGX_FEATURE_TLA
#define RGX_FEATURE_GS_RTA_SUPPORT
#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
#define RGX_FEATURE_META (LTP218)
#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE
#define RGX_FEATURE_FBCDC_ARCHITECTURE (2)
#define RGX_FEATURE_META_COREMEM_SIZE (32)
#define RGX_FEATURE_COMPUTE
#endif /* _RGXCONFIG_4_V_2_51_H_ */

View File

@ -2255,6 +2255,34 @@ Data master value to be used for fence requests
#define RGX_CR_GARTEN_SLC_FORCE_COHERENCY_CLRMSK (0XFFFFFFFEU)
#define RGX_CR_GARTEN_SLC_FORCE_COHERENCY_EN (0X00000001U)
/*
Register RGX_CR_BIF_MMU_ENTRY_STATUS
*/
#define RGX_CR_BIF_MMU_ENTRY_STATUS (0x1288U)
#define RGX_CR_BIF_MMU_ENTRY_STATUS_MASKFULL (IMG_UINT64_C(0x000000FFFFFFF0F3))
#define RGX_CR_BIF_MMU_ENTRY_STATUS_ADDRESS_SHIFT (12U)
#define RGX_CR_BIF_MMU_ENTRY_STATUS_ADDRESS_CLRMSK (IMG_UINT64_C(0XFFFFFF0000000FFF))
#define RGX_CR_BIF_MMU_ENTRY_STATUS_CAT_BASE_SHIFT (4U)
#define RGX_CR_BIF_MMU_ENTRY_STATUS_CAT_BASE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFF0F))
#define RGX_CR_BIF_MMU_ENTRY_STATUS_DATA_TYPE_SHIFT (0U)
#define RGX_CR_BIF_MMU_ENTRY_STATUS_DATA_TYPE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFC))
/*
Register RGX_CR_BIF_MMU_ENTRY
*/
#define RGX_CR_BIF_MMU_ENTRY (0x1290U)
#define RGX_CR_BIF_MMU_ENTRY_MASKFULL (IMG_UINT64_C(0x0000000000000003))
#define RGX_CR_BIF_MMU_ENTRY_ENABLE_SHIFT (1U)
#define RGX_CR_BIF_MMU_ENTRY_ENABLE_CLRMSK (0XFFFFFFFDU)
#define RGX_CR_BIF_MMU_ENTRY_ENABLE_EN (0X00000002U)
#define RGX_CR_BIF_MMU_ENTRY_PENDING_SHIFT (0U)
#define RGX_CR_BIF_MMU_ENTRY_PENDING_CLRMSK (0XFFFFFFFEU)
#define RGX_CR_BIF_MMU_ENTRY_PENDING_EN (0X00000001U)
/*
Index registers per data master. Byte aligned fields to allow byte-masked access

View File

@ -45,6 +45,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef _PVRVERSION_H_
#define _PVRVERSION_H_
/*
* Rogue KM Version Note
*
* L 0.16:
* Support gpu disable dvfs case.
* Add rk_tf_check_version to compatible for rk3328.
* L 0.17:
* merge 1.4_ED3573678 DDK code
*/
#define PVR_STR(X) #X
#define PVR_STR2(X) PVR_STR(X)
@ -53,7 +63,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define PVRVERSION_FAMILY "rogueddk"
#define PVRVERSION_BRANCHNAME "1.4"
#define PVRVERSION_BUILD 3443629
#define PVRVERSION_BUILD 3573678
#define PVRVERSION_BSCONTROL "Rogue_DDK_Android_RSCompute"
#define PVRVERSION_STRING "Rogue_DDK_Android_RSCompute rogueddk 1.4@" PVR_STR2(PVRVERSION_BUILD)
@ -61,8 +71,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define COPYRIGHT_TXT "Copyright (c) Imagination Technologies Ltd. All Rights Reserved."
#define PVRVERSION_BUILD_HI 344
#define PVRVERSION_BUILD_LO 3629
#define PVRVERSION_BUILD_HI 357
#define PVRVERSION_BUILD_LO 3678
#define PVRVERSION_STRING_NUMERIC PVR_STR2(PVRVERSION_MAJ) "." PVR_STR2(PVRVERSION_MIN) "." PVR_STR2(PVRVERSION_BUILD_HI) "." PVR_STR2(PVRVERSION_BUILD_LO)
#define PVRVERSION_PACK(MAJ,MIN) ((((MAJ)&0xFFFF) << 16) | (((MIN)&0xFFFF) << 0))
@ -70,5 +80,5 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define PVRVERSION_UNPACK_MIN(VERSION) (((VERSION) >> 0) & 0xFFFF)
//chenli:define rockchip version
#define RKVERSION "Rogue L 0.15"
#define RKVERSION "Rogue L 0.17"
#endif /* _PVRVERSION_H_ */

View File

@ -462,6 +462,36 @@ static bool pdp_vsync_triggered(struct adf_pdp_device *pdp)
return atomic_read(&pdp->vsync_triggered) == 1;
}
static void pdp_enable_vsync(struct adf_pdp_device *pdp)
{
int err = 0;
u32 reg_value = pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB);
reg_value |= (0x1 << INTEN_VBLNK1_SHIFT);
pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB, reg_value);
err = apollo_enable_interrupt(&pdp->pdata->pdev->dev,
APOLLO_INTERRUPT_PDP);
if (err) {
dev_err(&pdp->pdev->dev,
"apollo_enable_interrupt failed (%d)\n", err);
}
}
static void pdp_disable_vsync(struct adf_pdp_device *pdp)
{
int err = 0;
u32 reg_value = pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB);
reg_value &= ~(0x1 << INTEN_VBLNK1_SHIFT);
pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB, reg_value);
err = apollo_disable_interrupt(&pdp->pdata->pdev->dev,
APOLLO_INTERRUPT_PDP);
if (err) {
dev_err(&pdp->pdev->dev,
"apollo_disable_interrupt failed (%d)\n", err);
}
}
static void pdp_post(struct adf_device *adf_dev, struct adf_post *cfg,
void *driver_state)
{
@ -515,17 +545,17 @@ static void pdp_post(struct adf_device *adf_dev, struct adf_post *cfg,
/* Wait until the buffer is on-screen, so we know the previous buffer
* has been retired and off-screen.
*
* If vsync was already off when this post was serviced, we don't need
* to wait for it (note: this will cause tearing if done when the
* display is not blanked).
* If vsync was already off when this post was serviced, we need to
* enable the vsync again briefly so the register updates we shadowed
* above get applied and we don't signal the fence prematurely. One
* vsync afterwards, we'll disable the vsync again.
*/
if (atomic_read(&pdp->vsync_state)) {
if (wait_event_timeout(pdp->vsync_wait_queue,
pdp_vsync_triggered(pdp), timeout) == 0) {
/* Timeout - continue as if vsync was triggered, as
* possible tearing is better than wedging */
dev_err(&pdp->pdev->dev, "Post VSync wait timeout");
}
if (!atomic_xchg(&pdp->vsync_state, 1))
pdp_enable_vsync(pdp);
if (wait_event_timeout(pdp->vsync_wait_queue,
pdp_vsync_triggered(pdp), timeout) == 0) {
dev_err(&pdp->pdev->dev, "Post VSync wait timeout");
}
}
@ -546,21 +576,6 @@ static bool pdp_supports_event(struct adf_obj *obj, enum adf_event_type type)
}
}
static void pdp_disable_vsync(struct adf_pdp_device *pdp)
{
int err = 0;
u32 reg_value = pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB);
reg_value &= ~(0x1 << INTEN_VBLNK1_SHIFT);
pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB, reg_value);
err = apollo_disable_interrupt(&pdp->pdata->pdev->dev,
APOLLO_INTERRUPT_PDP);
if (err) {
dev_err(&pdp->pdev->dev,
"apollo_disable_interrupt failed (%d)\n", err);
}
}
static void pdp_irq_handler(void *data)
{
struct adf_pdp_device *pdp = data;
@ -588,21 +603,6 @@ static void pdp_irq_handler(void *data)
}
}
static void pdp_enable_vsync(struct adf_pdp_device *pdp)
{
int err = 0;
u32 reg_value = pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB);
reg_value |= (0x1 << INTEN_VBLNK1_SHIFT);
pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB, reg_value);
err = apollo_enable_interrupt(&pdp->pdata->pdev->dev,
APOLLO_INTERRUPT_PDP);
if (err) {
dev_err(&pdp->pdev->dev,
"apollo_enable_interrupt failed (%d)\n", err);
}
}
static void pdp_set_event(struct adf_obj *obj, enum adf_event_type type,
bool enabled)
{

View File

@ -1038,6 +1038,10 @@ enum PVRSRV_ERROR pvr_sync_append_fences(
struct pvr_sync_alloc_data *alloc_sync_data = NULL;
unsigned i;
if ((nr_updates && (!update_ufo_addresses || !update_values)) ||
(nr_checks && (!check_ufo_addresses || !check_values)))
return PVRSRV_ERROR_INVALID_PARAMS;
sync_data =
kzalloc(sizeof(struct pvr_sync_append_data)
+ nr_check_fences * sizeof(struct sync_fence*),
@ -1303,15 +1307,19 @@ enum PVRSRV_ERROR pvr_sync_append_fences(
sync_data->nr_checks = nr_checks + num_used_sync_checks;
sync_data->nr_updates = nr_updates + num_used_sync_updates;
/* Append original check and update sync values/addresses */
memcpy(update_address_pos, update_ufo_addresses,
sizeof(PRGXFWIF_UFO_ADDR) * nr_updates);
memcpy(update_value_pos, update_values,
sizeof(u32) * nr_updates);
if (update_ufo_addresses)
memcpy(update_address_pos, update_ufo_addresses,
sizeof(PRGXFWIF_UFO_ADDR) * nr_updates);
if (update_values)
memcpy(update_value_pos, update_values,
sizeof(u32) * nr_updates);
memcpy(check_address_pos, check_ufo_addresses,
sizeof(PRGXFWIF_UFO_ADDR) * nr_checks);
memcpy(check_value_pos, check_values,
sizeof(u32) * nr_checks);
if (check_ufo_addresses)
memcpy(check_address_pos, check_ufo_addresses,
sizeof(PRGXFWIF_UFO_ADDR) * nr_checks);
if (check_values)
memcpy(check_value_pos, check_values,
sizeof(u32) * nr_checks);
*append_sync_data = sync_data;

View File

@ -215,6 +215,7 @@ typedef struct _PVRSRV_PROCESS_STATS_ {
/* OS level process ID */
IMG_PID pid;
IMG_UINT32 ui32RefCount;
IMG_UINT32 ui32MemRefCount;
/* Folder name used to store the statistic */
IMG_CHAR szFolderName[MAX_PROC_NAME_LENGTH];
@ -232,6 +233,7 @@ typedef struct _PVRSRV_PROCESS_STATS_ {
struct _PVRSRV_MEMORY_STATS_* psMemoryStats;
struct _PVRSRV_RI_MEMORY_STATS_* psRIMemoryStats;
} PVRSRV_PROCESS_STATS;
typedef struct _PVRSRV_RENDER_STATS_ {
@ -364,13 +366,15 @@ static PVRSRV_GLOBAL_MEMORY_STATS gsGlobalStats;
#define HASH_INITIAL_SIZE 5
static HASH_TABLE* gpsTrackingTable;
static IMG_UINT32 _PVRSRVIncrMemStatRefCount(IMG_PVOID pvStatPtr);
static IMG_UINT32 _PVRSRVDecrMemStatRefCount(IMG_PVOID pvStatPtr);
static IMG_BOOL
_PVRSRVGetGlobalMemStat(IMG_PVOID pvStatPtr,
IMG_UINT32 ui32StatNumber,
IMG_INT32* pi32StatData,
IMG_CHAR** ppszStatFmtText);
IMG_VOID InsertPowerTimeStatistic(PVRSRV_POWER_ENTRY_TYPE bType,
IMG_INT32 i32CurrentState, IMG_INT32 i32NextState,
IMG_UINT64 ui64SysStartTime, IMG_UINT64 ui64SysEndTime,
@ -480,9 +484,6 @@ _DestoryRenderStat(PVRSRV_RENDER_STATS* psRenderStats)
{
PVR_ASSERT(psRenderStats != IMG_NULL);
/* Remove the statistic from the OS... */
OSRemoveStatisticEntry(psRenderStats->pvOSData);
/* Free the memory... */
OSFreeMem(psRenderStats);
} /* _DestoryRenderStat */
@ -667,28 +668,35 @@ _CreateOSStatisticEntries(PVRSRV_PROCESS_STATS* psProcessStats,
psProcessStats->pvOSPidEntryData = OSCreateStatisticEntry("process_stats",
psProcessStats->pvOSPidFolderData,
PVRSRVStatsObtainElement,
_PVRSRVIncrMemStatRefCount,
_PVRSRVDecrMemStatRefCount,
(IMG_PVOID) psProcessStats);
if (pvOSPowerStatsEntryData==NULL)
{
pvOSPowerStatsEntryData = OSCreateStatisticEntry("power_timings_stats",
pvOSPowerStatsEntryData = OSCreateStatisticEntry("power_timings_stats",
NULL,
PVRSRVPowerStatsObtainElement,
(IMG_PVOID) psProcessStats);
IMG_NULL,
IMG_NULL,
(IMG_PVOID) psProcessStats);
}
#if defined(PVRSRV_ENABLE_MEMORY_STATS)
psProcessStats->psMemoryStats->pvOSMemEntryData = OSCreateStatisticEntry("mem_area",
psProcessStats->pvOSPidFolderData,
PVRSRVStatsObtainElement,
(IMG_PVOID) psProcessStats->psMemoryStats);
IMG_NULL,
IMG_NULL,
(IMG_PVOID) psProcessStats->psMemoryStats);
#endif
#if defined(PVR_RI_DEBUG)
psProcessStats->psRIMemoryStats->pvOSRIMemEntryData = OSCreateStatisticEntry("ri_mem_area",
psProcessStats->pvOSPidFolderData,
PVRSRVStatsObtainElement,
(IMG_PVOID) psProcessStats->psRIMemoryStats);
IMG_NULL,
IMG_NULL,
(IMG_PVOID) psProcessStats->psRIMemoryStats);
#endif
} /* _CreateOSStatisticEntries */
@ -704,14 +712,18 @@ _RemoveOSStatisticEntries(PVRSRV_PROCESS_STATS* psProcessStats)
PVR_ASSERT(psProcessStats != IMG_NULL);
#if defined(PVR_RI_DEBUG)
PVR_ASSERT(psProcessStats->psRIMemoryStats->pvOSRIMemEntryData != IMG_NULL);
OSRemoveStatisticEntry(psProcessStats->psRIMemoryStats->pvOSRIMemEntryData);
#endif
#if defined(PVRSRV_ENABLE_MEMORY_STATS)
PVR_ASSERT(psProcessStats->psMemoryStats->pvOSMemEntryData != IMG_NULL);
OSRemoveStatisticEntry(psProcessStats->psMemoryStats->pvOSMemEntryData);
#endif
PVR_ASSERT(psProcessStats->pvOSPidEntryData != IMG_NULL);
OSRemoveStatisticEntry(psProcessStats->pvOSPidEntryData);
PVR_ASSERT(psProcessStats->pvOSPidFolderData != IMG_NULL);
OSRemoveStatisticFolder(psProcessStats->pvOSPidFolderData);
} /* _RemoveOSStatisticEntries */
@ -726,9 +738,6 @@ _DestoryProcessStat(PVRSRV_PROCESS_STATS* psProcessStats)
{
PVR_ASSERT(psProcessStats != IMG_NULL);
/* Remove this statistic from the OS... */
_RemoveOSStatisticEntries(psProcessStats);
/* Free the live and dead render statistic lists... */
while (psProcessStats->psRenderLiveList != IMG_NULL)
{
@ -748,17 +757,77 @@ _DestoryProcessStat(PVRSRV_PROCESS_STATS* psProcessStats)
/* Free the memory statistics... */
#if defined(PVRSRV_ENABLE_MEMORY_STATS)
while (psProcessStats->psMemoryStats->psMemoryRecords)
if (psProcessStats->psMemoryStats != IMG_NULL)
{
List_PVRSRV_MEM_ALLOC_REC_Remove(psProcessStats->psMemoryStats->psMemoryRecords);
while (psProcessStats->psMemoryStats->psMemoryRecords)
{
List_PVRSRV_MEM_ALLOC_REC_Remove(psProcessStats->psMemoryStats->psMemoryRecords);
}
OSMemSet(psProcessStats->psMemoryStats, 0x6b, sizeof(PVRSRV_MEMORY_STATS));
OSFreeMem(psProcessStats->psMemoryStats);
psProcessStats->psMemoryStats = IMG_NULL;
}
#endif
#if defined(PVR_RI_DEBUG)
if (psProcessStats->psRIMemoryStats != IMG_NULL)
{
OSFreeMem(psProcessStats->psRIMemoryStats);
psProcessStats->psRIMemoryStats = IMG_NULL;
}
OSFreeMem(psProcessStats->psMemoryStats);
#endif
/* Free the memory... */
OSFreeMem(psProcessStats);
} /* _DestoryProcessStat */
static IMG_UINT32 _PVRSRVIncrMemStatRefCount(IMG_PVOID pvStatPtr)
{
PVRSRV_STAT_STRUCTURE_TYPE* peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
PVRSRV_PROCESS_STATS* psProcessStats = (PVRSRV_PROCESS_STATS*) pvStatPtr;
IMG_UINT32 ui32Res = 7777;
switch (*peStructureType)
{
case PVRSRV_STAT_STRUCTURE_PROCESS:
{
/* Increment stat memory refCount */
ui32Res = ++psProcessStats->ui32MemRefCount;
break;
}
default:
{
break;
}
}
return ui32Res;
}
static IMG_UINT32 _PVRSRVDecrMemStatRefCount(IMG_PVOID pvStatPtr)
{
PVRSRV_STAT_STRUCTURE_TYPE* peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
PVRSRV_PROCESS_STATS* psProcessStats = (PVRSRV_PROCESS_STATS*) pvStatPtr;
IMG_UINT32 ui32Res = 7777;
switch (*peStructureType)
{
case PVRSRV_STAT_STRUCTURE_PROCESS:
{
/* Decrement stat memory refCount and free if now zero */
ui32Res = --psProcessStats->ui32MemRefCount;
if (ui32Res == 0)
{
_DestoryProcessStat(psProcessStats);
}
break;
}
default:
{
break;
}
}
return ui32Res;
}
/*************************************************************************/ /*!
@Function _CompressMemoryUsage
@ -806,7 +875,8 @@ _CompressMemoryUsage(IMG_VOID)
PVRSRV_PROCESS_STATS* psNextProcessStats = psProcessStatsToBeFreed->psNext;
psProcessStatsToBeFreed->psNext = IMG_NULL;
_DestoryProcessStat(psProcessStatsToBeFreed);
_RemoveOSStatisticEntries(psProcessStatsToBeFreed);
_PVRSRVDecrMemStatRefCount((void*)psProcessStatsToBeFreed);
psProcessStatsToBeFreed = psNextProcessStats;
}
@ -863,6 +933,8 @@ PVRSRVStatsInitialise(IMG_VOID)
pvOSGlobalMemEntryRef = OSCreateStatisticEntry(pszDriverStatFilename,
IMG_NULL,
_PVRSRVGetGlobalMemStat,
IMG_NULL,
IMG_NULL,
IMG_NULL);
OSMemSet(&gsGlobalStats, 0, sizeof(gsGlobalStats));
@ -908,20 +980,20 @@ PVRSRVStatsDestroy(IMG_VOID)
}
/* Free the live and dead lists... */
while (psLiveList != IMG_NULL)
while (psLiveList != IMG_NULL)
{
PVRSRV_PROCESS_STATS* psProcessStats = psLiveList;
_RemoveProcessStatsFromList(psProcessStats);
_DestoryProcessStat(psProcessStats);
_RemoveOSStatisticEntries(psProcessStats);
}
while (psDeadList != IMG_NULL)
while (psDeadList != IMG_NULL)
{
PVRSRV_PROCESS_STATS* psProcessStats = psDeadList;
_RemoveProcessStatsFromList(psProcessStats);
_DestoryProcessStat(psProcessStats);
_RemoveOSStatisticEntries(psProcessStats);
}
/* Remove the OS folders used by the PID folders... */
@ -938,7 +1010,6 @@ PVRSRVStatsDestroy(IMG_VOID)
} /* PVRSRVStatsDestroy */
static void _decrease_global_stat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
IMG_SIZE_T uiBytes)
{
@ -1219,6 +1290,7 @@ PVRSRVStatsRegisterProcess(IMG_HANDLE* phProcessStats)
psProcessStats->eStructureType = PVRSRV_STAT_STRUCTURE_PROCESS;
psProcessStats->pid = currentPid;
psProcessStats->ui32RefCount = 1;
psProcessStats->ui32MemRefCount = 1;
psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS] = 1;
psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_CONNECTIONS] = 1;
@ -2458,10 +2530,12 @@ IMG_BOOL
PVRSRVStatsObtainElement(IMG_PVOID pvStatPtr, IMG_UINT32 ui32StatNumber,
IMG_INT32* pi32StatData, IMG_CHAR** ppszStatFmtText)
{
IMG_BOOL bRes = IMG_FALSE;
PVRSRV_STAT_STRUCTURE_TYPE* peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
if (peStructureType == IMG_NULL || pi32StatData == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "%s: Invalid param, peStructureType=<%p>, pvStatPtr=<%p>", __FUNCTION__, (void*)peStructureType, (void*)pvStatPtr));
return IMG_FALSE;
}
@ -2469,16 +2543,18 @@ PVRSRVStatsObtainElement(IMG_PVOID pvStatPtr, IMG_UINT32 ui32StatNumber,
{
PVRSRV_PROCESS_STATS* psProcessStats = (PVRSRV_PROCESS_STATS*) pvStatPtr;
return _ObtainProcessStatistic(psProcessStats, ui32StatNumber,
bRes = _ObtainProcessStatistic(psProcessStats, ui32StatNumber,
pi32StatData, ppszStatFmtText);
return bRes;
}
#if defined(PVRSRV_ENABLE_MEMORY_STATS)
else if (*peStructureType == PVRSRV_STAT_STRUCTURE_MEMORY)
{
PVRSRV_MEMORY_STATS* psMemoryStats = (PVRSRV_MEMORY_STATS*) pvStatPtr;
return _ObtainMemoryStatistic(psMemoryStats, ui32StatNumber,
bRes = _ObtainMemoryStatistic(psMemoryStats, ui32StatNumber,
pi32StatData, ppszStatFmtText);
return bRes;
}
#endif
#if defined(PVR_RI_DEBUG)
@ -2486,13 +2562,15 @@ PVRSRVStatsObtainElement(IMG_PVOID pvStatPtr, IMG_UINT32 ui32StatNumber,
{
PVRSRV_RI_MEMORY_STATS* psRIMemoryStats = (PVRSRV_RI_MEMORY_STATS*) pvStatPtr;
return _ObtainRIMemoryStatistic(psRIMemoryStats, ui32StatNumber,
bRes = _ObtainRIMemoryStatistic(psRIMemoryStats, ui32StatNumber,
pi32StatData, ppszStatFmtText);
return bRes;
}
#endif
/* Stat type not handled probably indicates bad pointers... */
PVR_ASSERT(IMG_FALSE);
else
{
PVR_DPF((PVR_DBG_ERROR, "%s: Unrecognised peStructureType<%p>=%d", __FUNCTION__, (void*)peStructureType, *peStructureType));
}
return IMG_FALSE;
} /* PVRSRVStatsObtainElement */
@ -2538,6 +2616,7 @@ IMG_BOOL PVRSRVPowerStatsObtainElement(IMG_PVOID pvStatPtr, IMG_UINT32 ui32StatN
if (peStructureType == IMG_NULL || pi32StatData == IMG_NULL)
{
/* Stat type not handled probably indicates bad pointers... */
PVR_DPF((PVR_DBG_ERROR, "%s: Invalid param, peStructureType=<%p>, pvStatPtr=<%p>, ppszStatFmtText=<%p>, *ppszStatFmtText=<%p>", __FUNCTION__, (void*)peStructureType, (void*)pvStatPtr, (void*)ppszStatFmtText, (void*)*ppszStatFmtText));
PVR_ASSERT(IMG_FALSE);
return IMG_FALSE;
}
@ -2552,25 +2631,53 @@ IMG_BOOL PVRSRVPowerStatsObtainElement(IMG_PVOID pvStatPtr, IMG_UINT32 ui32StatN
case PVRSRV_POWER_TIMING_STAT_PRE_DEVICE:
{
(*ppszStatFmtText)="Pre-Device: %u\n";
(*pi32StatData)= ((IMG_UINT32)(ui64ForcedPreDevice)/(IMG_UINT32) ui64TotalForcedEntries);
if (ui64TotalForcedEntries > 0)
{
(*pi32StatData)= ((IMG_UINT32)(ui64ForcedPreDevice)/(IMG_UINT32) ui64TotalForcedEntries);
}
else
{
(*pi32StatData)= 0;
}
break;
}
case PVRSRV_POWER_TIMING_STAT_PRE_SYSTEM:
{
(*ppszStatFmtText)="Pre-System: %u\n";
(*pi32StatData)=((IMG_UINT32)(ui64ForcedPreSystem)/(IMG_UINT32) ui64TotalForcedEntries);
if (ui64TotalForcedEntries > 0)
{
(*pi32StatData)=((IMG_UINT32)(ui64ForcedPreSystem)/(IMG_UINT32) ui64TotalForcedEntries);
}
else
{
(*pi32StatData)= 0;
}
break;
}
case PVRSRV_POWER_TIMING_STAT_POST_DEVICE:
{
(*ppszStatFmtText)="Post-Device: %u\n";
(*pi32StatData)=((IMG_UINT32)(ui64ForcedPostDevice)/(IMG_UINT32) ui64TotalForcedEntries);
if (ui64TotalForcedEntries > 0)
{
(*pi32StatData)=((IMG_UINT32)(ui64ForcedPostDevice)/(IMG_UINT32) ui64TotalForcedEntries);
}
else
{
(*pi32StatData)= 0;
}
break;
}
case PVRSRV_POWER_TIMING_STAT_POST_SYSTEM:
{
(*ppszStatFmtText)="Post-System: %u\n";
(*pi32StatData)=((IMG_UINT32)(ui64ForcedPostSystem)/(IMG_UINT32) ui64TotalForcedEntries);
if (ui64TotalForcedEntries > 0)
{
(*pi32StatData)=((IMG_UINT32)(ui64ForcedPostSystem)/(IMG_UINT32) ui64TotalForcedEntries);
}
else
{
(*pi32StatData)= 0;
}
break;
}
case PVRSRV_POWER_TIMING_STAT_NEWLINE1:
@ -2587,25 +2694,53 @@ IMG_BOOL PVRSRVPowerStatsObtainElement(IMG_PVOID pvStatPtr, IMG_UINT32 ui32StatN
case PVRSRV_POWER_TIMING_STAT_NON_PRE_DEVICE:
{
(*ppszStatFmtText)="Pre-Device: %u\n";
(*pi32StatData)=((IMG_UINT32)(ui64NotForcedPreDevice)/(IMG_UINT32) ui64TotalNotForcedEntries);
if (ui64TotalNotForcedEntries > 0)
{
(*pi32StatData)=((IMG_UINT32)(ui64NotForcedPreDevice)/(IMG_UINT32) ui64TotalNotForcedEntries);
}
else
{
(*pi32StatData)= 0;
}
break;
}
case PVRSRV_POWER_TIMING_STAT_NON_PRE_SYSTEM:
{
(*ppszStatFmtText)="Pre-System: %u\n";
(*pi32StatData)=((IMG_UINT32)(ui64NotForcedPreSystem)/(IMG_UINT32) ui64TotalNotForcedEntries);
if (ui64TotalNotForcedEntries > 0)
{
(*pi32StatData)=((IMG_UINT32)(ui64NotForcedPreSystem)/(IMG_UINT32) ui64TotalNotForcedEntries);
}
else
{
(*pi32StatData)= 0;
}
break;
}
case PVRSRV_POWER_TIMING_STAT_NON_POST_DEVICE:
{
(*ppszStatFmtText)="Post-Device: %u\n";
(*pi32StatData)= ((IMG_UINT32)(ui64NotForcedPostDevice)/(IMG_UINT32) ui64TotalNotForcedEntries);
if (ui64TotalNotForcedEntries > 0)
{
(*pi32StatData)= ((IMG_UINT32)(ui64NotForcedPostDevice)/(IMG_UINT32) ui64TotalNotForcedEntries);
}
else
{
(*pi32StatData)= 0;
}
break;
}
case PVRSRV_POWER_TIMING_STAT_NON_POST_SYSTEM:
{
(*ppszStatFmtText)="Post-System: %u\n";
(*pi32StatData)=((IMG_UINT32)(ui64NotForcedPostSystem)/(IMG_UINT32) ui64TotalNotForcedEntries);
if (ui64TotalNotForcedEntries > 0)
{
(*pi32StatData)=((IMG_UINT32)(ui64NotForcedPostSystem)/(IMG_UINT32) ui64TotalNotForcedEntries);
}
else
{
(*pi32StatData)= 0;
}
break;
}
case PVRSRV_POWER_TIMING_STAT_FW_BOOTUP_TIME:

View File

@ -371,6 +371,9 @@ static IMG_VOID CleanupThread(IMG_PVOID pvData)
PVRSRV_ERROR eRc;
IMG_UINT64 ui64TimesliceLimit;
/* Store the process id (pid) of the clean-up thread */
psPVRSRVData->cleanupThreadPid = OSGetCurrentProcessIDKM();
PVR_DPF((CLEANUP_DPFL, "CleanupThread: thread starting... "));
/* Open an event on the clean up event object so we can listen on it,

View File

@ -126,6 +126,14 @@ static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psContext,
static IMG_VOID ResManFreeResources(PRESMAN_CONTEXT psResManContext);
static IMG_VOID ResManDeferResources(PRESMAN_CONTEXT psResManContext);
/* list of deferred work passed back from cleanup callbacks, to be called
* with the bridge lock released.
* This is a list because a single cleanup callback may
* generate multiple additional callbacks to be run without
* the bridge lock held.
*/
static DECLARE_DLLIST(gsFreeOSPagesWorkList);
/*!
******************************************************************************
@ -818,6 +826,58 @@ static IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list
}
}
/*!
******************************************************************************
@Function PVRSRVResManAddNoBridgeLockCallback
@Description
Called from resman callback cleanup functions. Adds a function
callback to be called without the bridge lock held.
@inputs psCallbackInfo - the callback function and callback data parameter
@Return None
**************************************************************************/
IMG_VOID PVRSRVResManAddNoBridgeLockCallback(RESMAN_FREE_FN_AND_DATA *psCallbackInfo)
{
dllist_add_to_tail(&gsFreeOSPagesWorkList, &psCallbackInfo->sNode);
}
/*!
******************************************************************************
@Function PVRSRVResManInDeferredCleanup
@Description
Indicates whether resman is currently in a deferred cleanup call.
@Return IMG_BOOL - IMG_TRUE if resman is currently in a deferred cleanup call.
**************************************************************************/
IMG_BOOL PVRSRVResManInDeferredCleanup(IMG_VOID)
{
PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
return OSGetCurrentProcessIDKM() == psPVRSRVData->cleanupThreadPid;
}
static IMG_BOOL _ResManDeferredCallbackCB(DLLIST_NODE *psNode, IMG_VOID *pvData)
{
RESMAN_FREE_FN_AND_DATA *psCallbackInfo;
PVRSRV_ERROR eError;
PVR_UNREFERENCED_PARAMETER(pvData);
psCallbackInfo = IMG_CONTAINER_OF(psNode, RESMAN_FREE_FN_AND_DATA, sNode);
eError = psCallbackInfo->pfnFree(psCallbackInfo->pvParam);
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "_ResManDeferredCallbackCB: pfnFree returned error: %u (%s)",
eError,
PVRSRVGETERRORSTRING(eError)));
}
return IMG_TRUE;
}
/*!
******************************************************************************
@Function FreeResourceByCriteria
@ -867,6 +927,24 @@ static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
if (eError == PVRSRV_OK)
{
iu32ItemsCounter++;
/* process any cleanup work which needed to be deferred until
* the bridge lock is released
*/
if(!dllist_is_empty(&gsFreeOSPagesWorkList))
{
OSReleaseBridgeLock();
dllist_foreach_node(&gsFreeOSPagesWorkList,
_ResManDeferredCallbackCB,
IMG_NULL);
/* work done. empty the list */
dllist_init(&gsFreeOSPagesWorkList);
OSAcquireBridgeLock();
}
}
else
{

View File

@ -492,25 +492,57 @@ static IMG_VOID _RGXDecodeBIFReqTags(RGXDBG_BIF_ID eBankID,
case 0xF:
{
pszTagID = "FB_CDC";
#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
{
IMG_UINT32 ui32Req = (ui32TagSB >> 2) & 0x3;
IMG_UINT32 ui32MCUSB = ui32TagSB & 0x3;
IMG_CHAR* pszReqId = (ui32TagSB & 0x10)?"FBDC":"FBC";
IMG_CHAR* pszOrig = "";
IMG_UINT32 ui32Req = (ui32TagSB >> 0) & 0xf;
IMG_UINT32 ui32MCUSB = (ui32TagSB >> 4) & 0x3;
IMG_CHAR* pszReqOrig = "";
switch (ui32Req)
{
case 0x0: pszOrig = "ZLS"; break;
case 0x1: pszOrig = (ui32TagSB & 0x10)?"MCU":"PBE"; break;
case 0x2: pszOrig = "Host"; break;
case 0x3: pszOrig = "TLA"; break;
case 0x0: pszReqOrig = "FBC Request, originator ZLS"; break;
case 0x1: pszReqOrig = "FBC Request, originator PBE"; break;
case 0x2: pszReqOrig = "FBC Request, originator Host"; break;
case 0x3: pszReqOrig = "FBC Request, originator TLA"; break;
case 0x4: pszReqOrig = "FBDC Request, originator ZLS"; break;
case 0x5: pszReqOrig = "FBDC Request, originator MCU"; break;
case 0x6: pszReqOrig = "FBDC Request, originator Host"; break;
case 0x7: pszReqOrig = "FBDC Request, originator TLA"; break;
case 0x8: pszReqOrig = "FBC Request, originator ZLS Requester Fence"; break;
case 0x9: pszReqOrig = "FBC Request, originator PBE Requester Fence"; break;
case 0xa: pszReqOrig = "FBC Request, originator Host Requester Fence"; break;
case 0xb: pszReqOrig = "FBC Request, originator TLA Requester Fence"; break;
case 0xc: pszReqOrig = "Reserved"; break;
case 0xd: pszReqOrig = "Reserved"; break;
case 0xe: pszReqOrig = "FBDC Request, originator FBCDC(Host) Memory Fence"; break;
case 0xf: pszReqOrig = "FBDC Request, originator FBCDC(TLA) Memory Fence"; break;
}
OSSNPrintf(pszScratchBuf, ui32ScratchBufSize,
"%s Request, originator %s, MCU sideband 0x%X",
pszReqId, pszOrig, ui32MCUSB);
"%s, MCU sideband 0x%X", pszReqOrig, ui32MCUSB);
pszTagSB = pszScratchBuf;
}
#else
{
IMG_UINT32 ui32Req = (ui32TagSB >> 2) & 0x7;
IMG_UINT32 ui32MCUSB = (ui32TagSB >> 0) & 0x3;
IMG_CHAR* pszReqOrig = "";
switch (ui32Req)
{
case 0x0: pszReqOrig = "FBC Request, originator ZLS"; break;
case 0x1: pszReqOrig = "FBC Request, originator PBE"; break;
case 0x2: pszReqOrig = "FBC Request, originator Host"; break;
case 0x3: pszReqOrig = "FBC Request, originator TLA"; break;
case 0x4: pszReqOrig = "FBDC Request, originator ZLS"; break;
case 0x5: pszReqOrig = "FBDC Request, originator MCU"; break;
case 0x6: pszReqOrig = "FBDC Request, originator Host"; break;
case 0x7: pszReqOrig = "FBDC Request, originator TLA"; break;
}
OSSNPrintf(pszScratchBuf, ui32ScratchBufSize,
"%s, MCU sideband 0x%X", pszReqOrig, ui32MCUSB);
pszTagSB = pszScratchBuf;
}
#endif
break;
}
} /* switch(TagID) */
@ -816,22 +848,31 @@ static IMG_VOID _RGXDecodeMMUReqTags(IMG_UINT32 ui32TagID,
case RGXDBG_FBCDC:
{
IMG_UINT32 ui32Req = (ui32TagSB >> 2) & 0x3;
IMG_UINT32 ui32MCUSB = ui32TagSB & 0x3;
IMG_CHAR* pszReqId = (ui32TagSB & 0x10)?"FBDC":"FBC";
IMG_CHAR* pszOrig = "";
IMG_UINT32 ui32Req = (ui32TagSB >> 0) & 0xf;
IMG_UINT32 ui32MCUSB = (ui32TagSB >> 4) & 0x3;
IMG_CHAR* pszReqOrig = "";
switch (ui32Req)
{
case 0x0: pszOrig = "ZLS"; break;
case 0x1: pszOrig = (ui32TagSB & 0x10)?"MCU":"PBE"; break;
case 0x2: pszOrig = "Host"; break;
case 0x3: pszOrig = "TLA"; break;
case 0x0: pszReqOrig = "FBC Request, originator ZLS"; break;
case 0x1: pszReqOrig = "FBC Request, originator PBE"; break;
case 0x2: pszReqOrig = "FBC Request, originator Host"; break;
case 0x3: pszReqOrig = "FBC Request, originator TLA"; break;
case 0x4: pszReqOrig = "FBDC Request, originator ZLS"; break;
case 0x5: pszReqOrig = "FBDC Request, originator MCU"; break;
case 0x6: pszReqOrig = "FBDC Request, originator Host"; break;
case 0x7: pszReqOrig = "FBDC Request, originator TLA"; break;
case 0x8: pszReqOrig = "FBC Request, originator ZLS Requester Fence"; break;
case 0x9: pszReqOrig = "FBC Request, originator PBE Requester Fence"; break;
case 0xa: pszReqOrig = "FBC Request, originator Host Requester Fence"; break;
case 0xb: pszReqOrig = "FBC Request, originator TLA Requester Fence"; break;
case 0xc: pszReqOrig = "Reserved"; break;
case 0xd: pszReqOrig = "Reserved"; break;
case 0xe: pszReqOrig = "FBDC Request, originator FBCDC(Host) Memory Fence"; break;
case 0xf: pszReqOrig = "FBDC Request, originator FBCDC(TLA) Memory Fence"; break;
}
OSSNPrintf(pszScratchBuf, ui32ScratchBufSize,
"%s Request, originator %s, MCU sideband 0x%X",
pszReqId, pszOrig, ui32MCUSB);
"%s, MCU sideband 0x%X", pszReqOrig, ui32MCUSB);
pszTagSB = pszScratchBuf;
break;
}
@ -1366,6 +1407,74 @@ static IMG_VOID _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
}
}
#if !defined(NO_HARDWARE)
/*!
*******************************************************************************
@Function _CheckForPendingPage
@Description
Check if the MMU indicates it is blocked on a pending page
@Input psDevInfo - RGX device info
@Return IMG_BOOL - IMG_TRUE if there is a pending page
******************************************************************************/
static INLINE IMG_BOOL _CheckForPendingPage(PVRSRV_RGXDEV_INFO *psDevInfo)
{
IMG_UINT32 ui32BIFMMUEntry;
ui32BIFMMUEntry = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_MMU_ENTRY);
if(ui32BIFMMUEntry & RGX_CR_BIF_MMU_ENTRY_PENDING_EN)
{
return IMG_TRUE;
}
else
{
return IMG_FALSE;
}
}
/*!
*******************************************************************************
@Function _GetPendingPageInfo
@Description
Get information about the pending page from the MMU status registers
@Input psDevInfo - RGX device info
@Output psDevVAddr - The device virtual address of the pending MMU address translation
@Output pui32CatBase - The page catalog base
@Output pui32DataType - The MMU entry data type
@Return void
******************************************************************************/
static void _GetPendingPageInfo(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_DEV_VIRTADDR *psDevVAddr,
IMG_UINT32 *pui32CatBase,
IMG_UINT32 *pui32DataType)
{
IMG_UINT64 ui64BIFMMUEntryStatus;
ui64BIFMMUEntryStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_MMU_ENTRY_STATUS);
psDevVAddr->uiAddr = (ui64BIFMMUEntryStatus & ~RGX_CR_BIF_MMU_ENTRY_STATUS_ADDRESS_CLRMSK);
*pui32CatBase = (ui64BIFMMUEntryStatus & ~RGX_CR_BIF_MMU_ENTRY_STATUS_CAT_BASE_CLRMSK) >>
RGX_CR_BIF_MMU_ENTRY_STATUS_CAT_BASE_SHIFT;
*pui32DataType = (ui64BIFMMUEntryStatus & ~RGX_CR_BIF_MMU_ENTRY_STATUS_DATA_TYPE_CLRMSK) >>
RGX_CR_BIF_MMU_ENTRY_STATUS_DATA_TYPE_SHIFT;
}
#endif
/*!
*******************************************************************************
@ -1433,6 +1542,37 @@ static IMG_VOID _RGXDumpRGXDebugSummary(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrint
#endif
#endif
#endif
#if !defined(NO_HARDWARE)
if(_CheckForPendingPage(psDevInfo))
{
IMG_UINT32 ui32CatBase;
IMG_UINT32 ui32DataType;
IMG_DEV_VIRTADDR sDevVAddr;
PVR_DUMPDEBUG_LOG(("MMU Pending page: Yes"));
_GetPendingPageInfo(psDevInfo, &sDevVAddr, &ui32CatBase, &ui32DataType);
if(ui32CatBase >= 8)
{
PVR_DUMPDEBUG_LOG(("Cannot check address on PM cat base %u", ui32CatBase));
}
else
{
IMG_DEV_PHYADDR sPCDevPAddr;
sPCDevPAddr.uiAddr = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_CAT_BASEN(ui32CatBase));
PVR_DUMPDEBUG_LOG(("Checking device virtual address " IMG_DEV_VIRTADDR_FMTSPEC
" on cat base %u. PC Addr = 0x%llX",
(unsigned long long) sDevVAddr.uiAddr,
ui32CatBase,
(unsigned long long) sPCDevPAddr.uiAddr));
RGXCheckFaultAddress(psDevInfo, &sDevVAddr, &sPCDevPAddr);
}
}
#endif /* NO_HARDWARE */
}
/* Firmware state */

View File

@ -877,7 +877,7 @@ PVRSRV_ERROR PVRSRVRGXCtrlHWPerfCountersKM(
static POS_LOCK hFTraceLock;
static IMG_VOID RGXHWPerfFTraceCmdCompleteNotify(PVRSRV_CMDCOMP_HANDLE);
static IMG_VOID RGXHWPerfFTraceGPUEnable(void)
static PVRSRV_ERROR RGXHWPerfFTraceGPUEnable(void)
{
PVRSRV_ERROR eError = PVRSRV_OK;
@ -923,7 +923,7 @@ static IMG_VOID RGXHWPerfFTraceGPUEnable(void)
gpsRgxDevInfo->bFTraceGPUEventsEnabled = IMG_TRUE;
err_out:
PVR_DPF_RETURN;
PVR_DPF_RETURN_RC(eError);
err_close_stream:
TLClientCloseStream(gpsRgxDevInfo->hGPUTraceTLConnection,
@ -933,9 +933,9 @@ static IMG_VOID RGXHWPerfFTraceGPUEnable(void)
goto err_out;
}
static IMG_VOID RGXHWPerfFTraceGPUDisable(IMG_BOOL bDeInit)
static PVRSRV_ERROR RGXHWPerfFTraceGPUDisable(IMG_BOOL bDeInit)
{
PVRSRV_ERROR eError;
PVRSRV_ERROR eError = PVRSRV_OK;
PVR_DPF_ENTERED;
@ -978,12 +978,13 @@ static IMG_VOID RGXHWPerfFTraceGPUDisable(IMG_BOOL bDeInit)
OSLockRelease(hFTraceLock);
PVR_DPF_RETURN;
PVR_DPF_RETURN_RC(eError);
}
IMG_VOID RGXHWPerfFTraceGPUEventsEnabledSet(IMG_BOOL bNewValue)
PVRSRV_ERROR RGXHWPerfFTraceGPUEventsEnabledSet(IMG_BOOL bNewValue)
{
IMG_BOOL bOldValue;
PVRSRV_ERROR eError = PVRSRV_OK;
PVR_DPF_ENTERED;
@ -992,7 +993,8 @@ IMG_VOID RGXHWPerfFTraceGPUEventsEnabledSet(IMG_BOOL bNewValue)
/* RGXHWPerfFTraceGPUInit hasn't been called yet -- it's too early
* to enable tracing.
*/
PVR_DPF_RETURN;
eError = PVRSRV_ERROR_NO_DEVICEDATA_FOUND;
PVR_DPF_RETURN_RC(eError);
}
bOldValue = gpsRgxDevInfo->bFTraceGPUEventsEnabled;
@ -1001,25 +1003,29 @@ IMG_VOID RGXHWPerfFTraceGPUEventsEnabledSet(IMG_BOOL bNewValue)
{
if (bNewValue)
{
RGXHWPerfFTraceGPUEnable();
eError = RGXHWPerfFTraceGPUEnable();
}
else
{
RGXHWPerfFTraceGPUDisable(IMG_FALSE);
eError = RGXHWPerfFTraceGPUDisable(IMG_FALSE);
}
}
PVR_DPF_RETURN;
PVR_DPF_RETURN_RC(eError);
}
IMG_VOID PVRGpuTraceEnabledSet(IMG_BOOL bNewValue)
PVRSRV_ERROR PVRGpuTraceEnabledSet(IMG_BOOL bNewValue)
{
PVRSRV_ERROR eError = PVRSRV_OK;
/* Lock down because we need to protect
* RGXHWPerfFTraceGPUDisable()/RGXHWPerfFTraceGPUEnable()
*/
OSAcquireBridgeLock();
RGXHWPerfFTraceGPUEventsEnabledSet(bNewValue);
eError = RGXHWPerfFTraceGPUEventsEnabledSet(bNewValue);
OSReleaseBridgeLock();
return eError;
}
IMG_BOOL RGXHWPerfFTraceGPUEventsEnabled(IMG_VOID)

View File

@ -103,7 +103,7 @@ IMG_VOID RGXHWPerfFTraceGPUEnqueueEvent(PVRSRV_RGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32ExternalJobRef, IMG_UINT32 ui32InternalJobRef,
const IMG_CHAR* pszJobType);
IMG_VOID RGXHWPerfFTraceGPUEventsEnabledSet(IMG_BOOL bNewValue);
PVRSRV_ERROR RGXHWPerfFTraceGPUEventsEnabledSet(IMG_BOOL bNewValue);
IMG_BOOL RGXHWPerfFTraceGPUEventsEnabled(IMG_VOID);
IMG_VOID RGXHWPerfFTraceGPUThread(IMG_PVOID pvData);

View File

@ -191,6 +191,13 @@ int MMapPMR(struct file *pFile, struct vm_area_struct *ps_vma)
#if defined(PVR_MMAP_USE_VM_INSERT)
IMG_BOOL bMixedMap = IMG_FALSE;
#endif
if(psConnection == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "Invalid connection data"));
goto em0;
}
/*
* The pmr lock used here to protect both handle related operations and PMR
* operations.
@ -461,7 +468,7 @@ int MMapPMR(struct file *pFile, struct vm_area_struct *ps_vma)
PVR_ASSERT(eError != PVRSRV_OK);
PVR_DPF((PVR_DBG_ERROR, "unable to translate error %d", eError));
mutex_unlock(&g_sMMapMutex);
em0:
return -ENOENT; // -EAGAIN // or what?
}

View File

@ -810,7 +810,7 @@ CONNECTION_DATA *LinuxConnectionFromFile(struct file *pFile)
{
PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
return psPrivateData->pvConnectionData;
return (psPrivateData == IMG_NULL) ? IMG_NULL : psPrivateData->pvConnectionData;
}
struct file *LinuxFileFromEnvConnection(ENV_CONNECTION_DATA *psEnvConnection)

View File

@ -90,6 +90,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
#include "syscommon.h"
#endif
#include "physmem_osmem_linux.h"
#if defined(EMULATOR) || defined(VIRTUAL_PLATFORM)
#define EVENT_OBJECT_TIMEOUT_MS (2000)
@ -290,7 +291,11 @@ PVRSRV_ERROR OSMMUPxMap(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle,
/* vmalloc and friends expect a guard page so we need to take that into account */
tmp_area.addr = (void *)uiCPUVAddr;
tmp_area.size = 2 * PAGE_SIZE;
ret = map_vm_area(&tmp_area, prot, &ppsPage);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,17,0))
ret = map_vm_area(&tmp_area, prot, ppsPage);
#else
ret = map_vm_area(&tmp_area, prot, & ppsPage);
#endif
if (ret) {
gen_pool_free(pvrsrv_pool_writecombine, uiCPUVAddr, PAGE_SIZE);
PVR_DPF((PVR_DBG_ERROR,
@ -486,6 +491,8 @@ PVRSRV_ERROR OSInitEnvData(void)
}
#endif /* defined(CONFIG_GENERIC_ALLOCATOR) && defined(CONFIG_X86) && (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0)) */
LinuxInitPagePool();
return PVRSRV_OK;
}
@ -511,6 +518,8 @@ void OSDeInitEnvData(void)
psEnvData->pvBridgeData = IMG_NULL;
OSFreeMem(psEnvData);
LinuxDeinitPagePool();
}
ENV_DATA *OSGetEnvData(void)
@ -1991,6 +2000,12 @@ struct task_struct *OSGetBridgeLockOwner(void)
root.
@Input pfnGetElement Pointer to function that can be used to obtain the
value of the statistic.
@Input pfnIncMemRefCt Pointer to function that can be used to take a
reference on the memory backing the statistic
entry.
@Input pfnDecMemRefCt Pointer to function that can be used to drop a
reference on the memory backing the statistic
entry.
@Input pvData OS specific reference that can be used by
pfnGetElement.
@Return Pointer void reference to the entry created, which can be
@ -1998,9 +2013,11 @@ struct task_struct *OSGetBridgeLockOwner(void)
*/ /**************************************************************************/
IMG_PVOID OSCreateStatisticEntry(IMG_CHAR* pszName, IMG_PVOID pvFolder,
OS_GET_STATS_ELEMENT_FUNC* pfnGetElement,
OS_INC_STATS_MEM_REFCOUNT_FUNC* pfnIncMemRefCt,
OS_DEC_STATS_MEM_REFCOUNT_FUNC* pfnDecMemRefCt,
IMG_PVOID pvData)
{
return PVRDebugFSCreateStatisticEntry(pszName, pvFolder, pfnGetElement, pvData);
return PVRDebugFSCreateStatisticEntry(pszName, (PVR_DEBUGFS_DIR_DATA *)pvFolder, pfnGetElement, pfnIncMemRefCt, pfnDecMemRefCt, pvData);
} /* OSCreateStatisticEntry */
@ -2012,7 +2029,7 @@ IMG_PVOID OSCreateStatisticEntry(IMG_CHAR* pszName, IMG_PVOID pvFolder,
*/ /**************************************************************************/
void OSRemoveStatisticEntry(IMG_PVOID pvEntry)
{
PVRDebugFSRemoveStatisticEntry(pvEntry);
PVRDebugFSRemoveStatisticEntry((PVR_DEBUGFS_DRIVER_STAT *)pvEntry);
} /* OSRemoveStatisticEntry */
@ -2027,12 +2044,11 @@ void OSRemoveStatisticEntry(IMG_PVOID pvEntry)
*/ /**************************************************************************/
IMG_PVOID OSCreateStatisticFolder(IMG_CHAR *pszName, IMG_PVOID pvFolder)
{
struct dentry *psDir;
PVR_DEBUGFS_DIR_DATA *psNewStatFolder = IMG_NULL;
int iResult;
iResult = PVRDebugFSCreateEntryDir(pszName, pvFolder, &psDir);
return (iResult == 0) ? psDir : IMG_NULL;
iResult = PVRDebugFSCreateEntryDir(pszName, (PVR_DEBUGFS_DIR_DATA *)pvFolder, &psNewStatFolder);
return (iResult == 0) ? (void *)psNewStatFolder : IMG_NULL;
} /* OSCreateStatisticFolder */
@ -2044,5 +2060,5 @@ IMG_PVOID OSCreateStatisticFolder(IMG_CHAR *pszName, IMG_PVOID pvFolder)
*/ /**************************************************************************/
void OSRemoveStatisticFolder(IMG_PVOID pvFolder)
{
PVRDebugFSRemoveEntryDir((struct dentry *)pvFolder);
PVRDebugFSRemoveEntryDir((PVR_DEBUGFS_DIR_DATA *)pvFolder);
} /* OSRemoveStatisticFolder */

View File

@ -132,9 +132,6 @@ PVRSRV_ERROR OSSecureExport(CONNECTION_DATA *psConnection,
goto e0;
}
/* Bind our struct file with it's fd number */
fd_install(secure_fd, secure_file);
/* Return the new services connection our secure data created */
#if defined(SUPPORT_DRM)
psSecureConnection = LinuxConnectionFromFile(PVR_DRM_FILE_FROM_FILE(secure_file));
@ -142,6 +139,16 @@ PVRSRV_ERROR OSSecureExport(CONNECTION_DATA *psConnection,
psSecureConnection = LinuxConnectionFromFile(secure_file);
#endif
if(psSecureConnection == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "Invalid connection data"));
eError = PVRSRV_ERROR_INVALID_PARAMS;
goto e0;
}
/* Bind our struct file with it's fd number */
fd_install(secure_fd, secure_file);
/* Save the private data */
PVR_ASSERT(psSecureConnection->hSecureData == IMG_NULL);
psSecureConnection->hSecureData = pvData;

View File

@ -60,6 +60,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* ourselves */
#include "physmem_osmem.h"
#include "physmem_osmem_linux.h"
#if defined(PVRSRV_ENABLE_PROCESS_STATS)
#include "process_stats.h"
@ -137,8 +138,42 @@ struct _PMR_OSPAGEARRAY_DATA_ {
*/
IMG_UINT32 ui32CPUCacheFlags;
IMG_BOOL bUnsetMemoryType;
/*
structure used to hook in to the resman queue of additionally
deferred work, to be done without the bridge lock held
*/
RESMAN_FREE_FN_AND_DATA sResManData;
};
/* clone a PMR_OSPAGEARRAY_DATA structure, including making a copy of
* the the list of physical pages it owns.
* returns a pointer to the newly allocated PMR_OSPAGEARRAY_DATA structure.
*/
static struct _PMR_OSPAGEARRAY_DATA_ *_CloneOSPageArrayData(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayDataIn)
{
struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayDataOut;
size_t uiStructureSize;
uiStructureSize = sizeof(struct _PMR_OSPAGEARRAY_DATA_) +
sizeof(struct page *) * psPageArrayDataIn->uiNumPages;
psPageArrayDataOut = OSAllocMemstatMem(uiStructureSize);
if(psPageArrayDataOut == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "_CloneOSPageArrayData: Failed to clone PMR_OSPAGEARRAY_DATA"));
return IMG_NULL;
}
memcpy(psPageArrayDataOut, psPageArrayDataIn, uiStructureSize);
psPageArrayDataOut->pagearray = (void *) ((char *) psPageArrayDataOut) +
sizeof(struct _PMR_OSPAGEARRAY_DATA_);
return psPageArrayDataOut;
}
/***********************************
* Page pooling for uncached pages *
***********************************/
@ -161,7 +196,6 @@ typedef struct
/* Track what is live */
static IMG_UINT32 g_ui32PagePoolEntryCount = 0;
static IMG_UINT32 g_ui32PagePoolMaxEntries = PVR_LINUX_PYSMEM_MAX_POOL_PAGES;
static IMG_UINT32 g_ui32LiveAllocs = 0;
/* Global structures we use to manage the page pool */
static struct kmem_cache *g_psLinuxPagePoolCache = IMG_NULL;
@ -432,11 +466,10 @@ static void DisableOOMKiller(void)
current->flags |= PF_DUMPCORE;
}
static void _InitPagePool(void)
void LinuxInitPagePool(void)
{
IMG_UINT32 ui32Flags = 0;
_PagePoolLock();
#if defined(DEBUG_LINUX_SLAB_ALLOCATIONS)
ui32Flags |= SLAB_POISON|SLAB_RED_ZONE;
#endif
@ -449,14 +482,12 @@ static void _InitPagePool(void)
register_shrinker(&g_sShrinker);
}
#endif
_PagePoolUnlock();
}
static void _DeinitPagePool(void)
void LinuxDeinitPagePool(void)
{
LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
_PagePoolLock();
/* Evict all the pages from the pool */
list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem)
{
@ -512,7 +543,6 @@ static void _DeinitPagePool(void)
#if defined(PHYSMEM_SUPPORTS_SHRINKER)
unregister_shrinker(&g_sShrinker);
#endif
_PagePoolUnlock();
}
static void EnableOOMKiller(void)
@ -669,49 +699,6 @@ _AllocOSPage(IMG_UINT32 ui32CPUCacheFlags,
DisableOOMKiller();
psPage = alloc_pages(gfp_flags, uiOrder);
EnableOOMKiller();
#if defined (CONFIG_ARM) || defined(CONFIG_ARM64) || defined (CONFIG_METAG)
/*
On ARM kernels we can be given pages which still remain in the cache.
In order to make sure that the data we write through our mappings
doesn't get over written by later cache evictions we invalidate the
pages that get given to us.
Note:
This still seems to be true if we request cold pages, it's just less
likely to be in the cache.
*/
if (psPage != IMG_NULL)
{
pvPageVAddr = kmap(psPage);
if (ui32CPUCacheFlags != PVRSRV_MEMALLOCFLAG_CPU_CACHED)
{
IMG_CPU_PHYADDR sCPUPhysAddrStart, sCPUPhysAddrEnd;
sCPUPhysAddrStart.uiAddr = page_to_phys(psPage);
sCPUPhysAddrEnd.uiAddr = sCPUPhysAddrStart.uiAddr + PAGE_SIZE;
/* If we're zeroing, we need to make sure the cleared memory is pushed out
of the cache before the cache lines are invalidated */
if (bFlush)
{
OSFlushCPUCacheRangeKM(pvPageVAddr,
pvPageVAddr + PAGE_SIZE,
sCPUPhysAddrStart,
sCPUPhysAddrEnd);
}
else
{
OSInvalidateCPUCacheRangeKM(pvPageVAddr,
pvPageVAddr + PAGE_SIZE,
sCPUPhysAddrStart,
sCPUPhysAddrEnd);
}
}
kunmap(psPage);
}
#endif
}
else
{
@ -831,11 +818,11 @@ _AllocOSPages(struct _PMR_OSPAGEARRAY_DATA_ **ppsPageArrayDataPtr)
unsigned int gfp_flags;
#if defined (CONFIG_X86)
/* On x86 we might have to change the page cache attributes.
* We do this by storing references to all the changed pages that are not
* from the page pool and then set the attribute of all the pages at once.
* This saves us calling set_memory_XX() and therefore a cache flush every time
* On ARM we have to just invalidate pages that have different cache attributes..
*/
struct page **apsUnsetPages = OSAllocMem(sizeof(struct page*) * psPageArrayData->uiNumPages);
IMG_UINT32 uiUnsetPagesIndex = 0;
@ -847,26 +834,14 @@ _AllocOSPages(struct _PMR_OSPAGEARRAY_DATA_ **ppsPageArrayDataPtr)
goto e_exit;
}
#endif
PVR_ASSERT(!psPageArrayData->bHasOSPages);
/* Try and create the page pool if required */
if ((g_ui32PagePoolMaxEntries > 0) && (g_psLinuxPagePoolCache == NULL))
{
_InitPagePool();
}
uiOrder = psPageArrayData->uiLog2PageSize - PAGE_SHIFT;
ui32CPUCacheFlags = psPageArrayData->ui32CPUCacheFlags;
gfp_flags = GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC;
#if defined(CONFIG_X86)
gfp_flags |= __GFP_DMA32;
#else
#if !defined(CONFIG_X86)
gfp_flags |= __GFP_HIGHMEM;
#endif
@ -914,13 +889,11 @@ _AllocOSPages(struct _PMR_OSPAGEARRAY_DATA_ **ppsPageArrayDataPtr)
&ppsPageArray[uiPageIndex],
&bPageFromPool);
#if defined(CONFIG_X86)
if (!bPageFromPool)
{
apsUnsetPages[uiUnsetPagesIndex] = ppsPageArray[uiPageIndex];
uiUnsetPagesIndex++;
}
#endif
if (eError != PVRSRV_OK)
{
@ -969,6 +942,58 @@ _AllocOSPages(struct _PMR_OSPAGEARRAY_DATA_ **ppsPageArrayDataPtr)
#endif
#endif
}
#if defined (CONFIG_ARM) || defined(CONFIG_ARM64) || defined (CONFIG_METAG)
/*
On ARM kernels we can be given pages which still remain in the cache.
In order to make sure that the data we write through our mappings
doesn't get over written by later cache evictions we invalidate the
pages that get given to us.
Note:
This still seems to be true if we request cold pages, it's just less
likely to be in the cache.
*/
if (ui32CPUCacheFlags != PVRSRV_MEMALLOCFLAG_CPU_CACHED)
{
if (uiUnsetPagesIndex < PVR_LINUX_ARM_PAGEALLOC_FLUSH_THRESHOLD)
{
int i;
void* pvPageVAddr;
for (i = 0; i < uiUnsetPagesIndex; i++)
{
IMG_CPU_PHYADDR sCPUPhysAddrStart, sCPUPhysAddrEnd;
pvPageVAddr = kmap(apsUnsetPages[i]);
sCPUPhysAddrStart.uiAddr = page_to_phys(apsUnsetPages[i]);
sCPUPhysAddrEnd.uiAddr = sCPUPhysAddrStart.uiAddr + PAGE_SIZE;
/* If we're zeroing, we need to make sure the cleared memory is pushed out
of the cache before the cache lines are invalidated */
if (psPageArrayData->bZero)
{
OSFlushCPUCacheRangeKM(pvPageVAddr,
pvPageVAddr + PAGE_SIZE,
sCPUPhysAddrStart,
sCPUPhysAddrEnd);
}
else
{
OSInvalidateCPUCacheRangeKM(pvPageVAddr,
pvPageVAddr + PAGE_SIZE,
sCPUPhysAddrStart,
sCPUPhysAddrEnd);
}
kunmap(apsUnsetPages[i]);
}
}
else
{
OSCPUOperation(PVRSRV_CACHE_OP_FLUSH);
}
}
#endif
#if defined (CONFIG_X86)
/*
@ -1020,16 +1045,14 @@ _AllocOSPages(struct _PMR_OSPAGEARRAY_DATA_ **ppsPageArrayDataPtr)
}
}
OSFreeMem(apsUnsetPages);
#endif
OSFreeMem(apsUnsetPages);
/* OS Pages have been allocated */
psPageArrayData->bHasOSPages = IMG_TRUE;
PVR_DPF((PVR_DBG_MESSAGE, "physmem_osmem_linux.c: allocated OS memory for PMR @0x%p", psPageArrayData));
g_ui32LiveAllocs++;
return PVRSRV_OK;
@ -1038,10 +1061,8 @@ _AllocOSPages(struct _PMR_OSPAGEARRAY_DATA_ **ppsPageArrayDataPtr)
*/
e_freed_pages:
#if defined (CONFIG_X86)
OSFreeMem(apsUnsetPages);
e_exit:
#endif
PVR_ASSERT(eError != PVRSRV_OK);
return eError;
}
@ -1056,8 +1077,44 @@ _FreeOSPagesArray(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
return PVRSRV_OK;
}
#if defined(PVRSRV_ENABLE_PROCESS_STATS)
/* _FreeOSPages_MemStats: Depends on the bridge lock already being held */
static PVRSRV_ERROR
_FreeOSPages(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
_FreeOSPages_MemStats(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
{
IMG_UINT32 uiNumPages;
struct page **ppsPageArray;
#if defined(PVRSRV_ENABLE_MEMORY_STATS)
IMG_UINT32 uiPageIndex;
#endif
PVR_ASSERT(psPageArrayData->bHasOSPages);
ppsPageArray = psPageArrayData->pagearray;
uiNumPages = psPageArrayData->uiNumPages;
#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES, uiNumPages * PAGE_SIZE);
#else
for (uiPageIndex = 0;
uiPageIndex < uiNumPages;
uiPageIndex++)
{
IMG_CPU_PHYADDR sCPUPhysAddr;
sCPUPhysAddr.uiAddr = page_to_phys(ppsPageArray[uiPageIndex]);
PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES, sCPUPhysAddr.uiAddr);
}
#endif /* !defined(PVRSRV_ENABLE_MEMORY_STATS) */
return PVRSRV_OK;
}
#endif /* PVRSRV_ENABLE_PROCESS_STATS */
/* _FreeOSPages_FreePages: Does not require the bridge lock */
static PVRSRV_ERROR
_FreeOSPages_FreePages(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
{
PVRSRV_ERROR eError;
IMG_UINT32 uiNumPages;
@ -1068,7 +1125,7 @@ _FreeOSPages(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
#if defined (CONFIG_X86)
IMG_UINT32 uiUnsetPagesIndex = 0;
struct page **apsUnsetPages = OSAllocMem(sizeof(struct page *) * psPageArrayData->uiNumPages);
struct page **apsUnsetPages = OSAllocMemstatMem(sizeof(struct page *) * psPageArrayData->uiNumPages);
if (apsUnsetPages == NULL)
{
@ -1079,9 +1136,6 @@ _FreeOSPages(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
}
#endif
PVR_ASSERT(psPageArrayData->bHasOSPages);
g_ui32LiveAllocs--;
ppsPageArray = psPageArrayData->pagearray;
uiNumPages = psPageArrayData->uiNumPages;
@ -1100,20 +1154,6 @@ _FreeOSPages(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
_FreePoisonSize);
}
#if defined(PVRSRV_ENABLE_PROCESS_STATS)
#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
/* Allocation is done a page at a time */
PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES, PAGE_SIZE);
#else
{
IMG_CPU_PHYADDR sCPUPhysAddr;
sCPUPhysAddr.uiAddr = page_to_phys(ppsPageArray[uiPageIndex]);
PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES, sCPUPhysAddr.uiAddr);
}
#endif
#endif
/* Only zero order pages can be managed in the pool */
if (uiOrder == 0)
{
@ -1166,24 +1206,150 @@ _FreeOSPages(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
}
}
OSFreeMem(apsUnsetPages);
OSFreeMemstatMem(apsUnsetPages);
#endif
eError = PVRSRV_OK;
psPageArrayData->bHasOSPages = IMG_FALSE;
/* Destroy the page pool if required */
if ((g_ui32PagePoolMaxEntries > 0) && (g_psLinuxPagePoolCache != NULL) && (g_ui32LiveAllocs == 0))
{
_DeinitPagePool();
}
eError = PVRSRV_OK;
#if defined(CONFIG_X86)
e_exit:
#endif
return eError;
}
static PVRSRV_ERROR
_FreeOSPages_FreePagesAndFreeStructure(void *pvData)
{
struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData = pvData;
PVRSRV_ERROR eError;
eError = _FreeOSPages_FreePages(psPageArrayData);
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "_FreeOSPages_FreePagesAndFreeStructure: _FreeOSPages_FreePages failed"));
}
else
{
eError = _FreeOSPagesArray(psPageArrayData);
}
return eError;
}
static PVRSRV_ERROR
_FreeOSPages(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData, IMG_BOOL bFreePageArray)
{
PVRSRV_ERROR eError = PVRSRV_OK;
/* if this is a deferred callback then have resman do the work in two parts,
* with the second part without the bridge lock held
*/
if(PVRSRVResManInDeferredCleanup())
{
/* if the page array data structure (struct _PMR_OSPAGEARRAY_DATA_) is
* being freed then we can go ahead and put the structure on the
* deferred free list.
* otherwise, the _PMR_OSPAGEARRAY_DATA_ structure may be re-used so its
* contents cannot be relied upon to be stable when the bridge lock is not held.
* for this reason we fork/clone the _PMR_OSPAGEARRAY_DATA_ structure and move
* ownership of the pages onto the new structure. the existing _PMR_OSPAGEARRAY_DATA_
* structure immediately has no pages belonging to it.
*/
if(bFreePageArray)
{
#if defined(PVRSRV_ENABLE_PROCESS_STATS)
eError = _FreeOSPages_MemStats(psPageArrayData);
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "_FreeOSPages_MemStats failed"));
}
#endif
/* set up the deferred work */
psPageArrayData->sResManData.pfnFree = _FreeOSPages_FreePagesAndFreeStructure;
psPageArrayData->sResManData.pvParam = psPageArrayData;
PVRSRVResManAddNoBridgeLockCallback(&psPageArrayData->sResManData);
}
else
{
struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayDataClone;
/* we are only expected to free the physical backing, not the PMR OS page array data structure.
* because the PMR OS page array may be re-mapped, the existing struct _PMR_OSPAGEARRAY_DATA_
* cannot be passed to the async/deferred free function (the re-mapping may occur before
* the free). So at this point we detach the physical page list from the
* struct _PMR_OSPAGEARRAY_DATA_ and leave the struct _PMR_OSPAGEARRAY_DATA_ intact,
* only modifying its 'bHasOSPages' boolean to reflect it no longer owns
* any OS allocated pages
*/
psPageArrayDataClone = _CloneOSPageArrayData(psPageArrayData);
if(psPageArrayDataClone == NULL)
{
/* failed to clone the structure so we cannot defer this work. do it immediately */
goto free_immediately;
}
/* psPageArrayDataClone takes ownership of the pages, so mark
* psPageArrayData as not having any pages
*/
psPageArrayData->bHasOSPages = IMG_FALSE;
#if defined(PVRSRV_ENABLE_PROCESS_STATS)
eError = _FreeOSPages_MemStats(psPageArrayDataClone);
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "_FreeOSPages_MemStats failed"));
}
#endif
/* set up the deferred work */
psPageArrayDataClone->sResManData.pfnFree = _FreeOSPages_FreePagesAndFreeStructure;
psPageArrayDataClone->sResManData.pvParam = psPageArrayDataClone;
PVRSRVResManAddNoBridgeLockCallback(&psPageArrayDataClone->sResManData);
}
return PVRSRV_OK;
}
free_immediately:
/* immediately free the pages and, if specified, the _PMR_OSPAGEARRAY_DATA_ structure */
#if defined(PVRSRV_ENABLE_PROCESS_STATS)
eError = _FreeOSPages_MemStats(psPageArrayData);
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "_FreeOSPages_MemStats failed"));
}
#endif
eError = _FreeOSPages_FreePages(psPageArrayData);
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "_FreeOSPages_FreePages failed"));
goto err_out;
}
if(bFreePageArray)
{
eError = _FreeOSPagesArray(psPageArrayData);
}
err_out:
return eError;
}
/*
*
* Implementation of callback functions
@ -1212,12 +1378,13 @@ PMRFinalizeOSMem(PMR_IMPL_PRIVDATA pvPriv
/* We can't free pages until now. */
if (psOSPageArrayData->bHasOSPages)
{
eError = _FreeOSPages(psOSPageArrayData);
eError = _FreeOSPages(psOSPageArrayData, IMG_TRUE);
PVR_ASSERT (eError == PVRSRV_OK); /* can we do better? */
}
eError = _FreeOSPagesArray(psOSPageArrayData);
PVR_ASSERT (eError == PVRSRV_OK); /* can we do better? */
else
{
_FreeOSPagesArray(psOSPageArrayData);
}
return PVRSRV_OK;
}
@ -1277,7 +1444,7 @@ PMRUnlockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv
if (psOSPageArrayData->bOnDemand)
{
/* Free Memory for deferred allocation */
eError = _FreeOSPages(psOSPageArrayData);
eError = _FreeOSPages(psOSPageArrayData, IMG_FALSE);
if (eError != PVRSRV_OK)
{
return eError;
@ -1603,7 +1770,7 @@ _NewOSAllocPagesPMR(PVRSRV_DEVICE_NODE *psDevNode,
errorOnCreate:
if (!bOnDemand)
{
eError2 = _FreeOSPages(psPrivData);
eError2 = _FreeOSPages(psPrivData, IMG_FALSE);
PVR_ASSERT(eError2 == PVRSRV_OK);
}

View File

@ -0,0 +1,49 @@
/*************************************************************************/ /*!
@File
@Title Linux OS physmem implementation
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
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.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) 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; AND (B) 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(__PHYSMEM_OSMEM_LINUX_H__)
#define __PHYSMEM_OSMEM_LINUX_H__
void LinuxInitPagePool(void);
void LinuxDeinitPagePool(void);
#endif /* __PHYSMEM_OSMEM_LINUX_H__ */

View File

@ -87,7 +87,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#if defined(DEBUG_BRIDGE_KM)
static struct dentry *gpsPVRDebugFSBridgeStatsEntry = NULL;
static PVR_DEBUGFS_ENTRY_DATA *gpsPVRDebugFSBridgeStatsEntry = NULL;
static struct seq_operations gsBridgeStatsReadOps;
#endif
@ -157,7 +157,7 @@ LinuxBridgeInit(void)
&gsBridgeStatsReadOps,
NULL,
&g_BridgeDispatchTable[0],
&gpsPVRDebugFSBridgeStatsEntry);
&gpsPVRDebugFSBridgeStatsEntry);
if (iResult != 0)
{
return PVRSRV_ERROR_OUT_OF_MEMORY;
@ -349,8 +349,8 @@ void
LinuxBridgeDeInit(void)
{
#if defined(DEBUG_BRIDGE_KM)
PVRDebugFSRemoveEntry(gpsPVRDebugFSBridgeStatsEntry);
gpsPVRDebugFSBridgeStatsEntry = NULL;
PVRDebugFSRemoveEntry(gpsPVRDebugFSBridgeStatsEntry);
gpsPVRDebugFSBridgeStatsEntry = NULL;
#endif
}
@ -459,11 +459,19 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig
PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
#endif
PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pFile);
CONNECTION_DATA *psConnection;
IMG_INT err = -EFAULT;
OSAcquireBridgeLock();
psConnection = LinuxConnectionFromFile(pFile);
if(psConnection == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "%s: Connection is closed", __FUNCTION__));
OSReleaseBridgeLock();
return err;
}
#if defined(SUPPORT_DRM)
PVR_UNREFERENCED_PARAMETER(dev);
@ -542,17 +550,28 @@ PVRSRV_BridgeCompatDispatchKM(struct file *pFile,
PVRSRV_BRIDGE_PACKAGE params_for_64;
struct bridge_package_from_32 params;
struct bridge_package_from_32 * const params_addr = &params;
#if !defined(SUPPORT_DRM)
CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pFile);
#else
struct drm_file *file_priv = pFile->private_data;
CONNECTION_DATA *psConnection = LinuxConnectionFromFile(file_priv);
#if defined(SUPPORT_DRM)
struct drm_file *file_priv;
#endif
CONNECTION_DATA *psConnection;
// make sure there is no padding inserted by compiler
PVR_ASSERT(sizeof(struct bridge_package_from_32) == 6 * sizeof(IMG_UINT32));
OSAcquireBridgeLock();
#if !defined(SUPPORT_DRM)
psConnection = LinuxConnectionFromFile(pFile);
#else
file_priv = pFile->private_data;
psConnection = LinuxConnectionFromFile(file_priv);
#endif
if(psConnection == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "%s: Connection is closed", __FUNCTION__));
goto unlock_and_return;
}
if(!OSAccessOK(PVR_VERIFY_READ, (void *) arg,
sizeof(struct bridge_package_from_32)))
{

View File

@ -1310,17 +1310,18 @@ static IMG_INT DebugLevelSet(const char __user *pcBuffer,
}
#endif /* defined(DEBUG) */
static struct dentry *gpsVersionDebugFSEntry;
static struct dentry *gpsNodesDebugFSEntry;
static struct dentry *gpsStatusDebugFSEntry;
static struct dentry *gpsDumpDebugDebugFSEntry;
static PVR_DEBUGFS_ENTRY_DATA *gpsVersionDebugFSEntry;
static PVR_DEBUGFS_ENTRY_DATA *gpsNodesDebugFSEntry;
static PVR_DEBUGFS_ENTRY_DATA *gpsStatusDebugFSEntry;
static PVR_DEBUGFS_ENTRY_DATA *gpsDumpDebugDebugFSEntry;
#if defined(PVRSRV_ENABLE_FW_TRACE_DEBUGFS)
static struct dentry *gpsFWTraceDebugFSEntry;
static PVR_DEBUGFS_ENTRY_DATA *gpsFWTraceDebugFSEntry;
#endif
#if defined(DEBUG)
static struct dentry *gpsDebugLevelDebugFSEntry;
static PVR_DEBUGFS_ENTRY_DATA *gpsDebugLevelDebugFSEntry;
#endif
int PVRDebugCreateDebugFSEntries(void)
@ -1337,6 +1338,7 @@ int PVRDebugCreateDebugFSEntries(void)
NULL,
psPVRSRVData,
&gpsVersionDebugFSEntry);
if (iResult != 0)
{
return iResult;
@ -1475,5 +1477,6 @@ void PVRDebugRemoveDebugFSEntries(void)
PVRDebugFSRemoveEntry(gpsVersionDebugFSEntry);
gpsVersionDebugFSEntry = NULL;
}
}

View File

@ -50,6 +50,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
static struct dentry *gpsPVRDebugFSEntryDir = NULL;
/* Lock used when adjusting refCounts and deleting entries */
static struct mutex gDebugFSLock;
/*************************************************************************/ /*!
Statistic entry read functions
@ -57,47 +59,107 @@ static struct dentry *gpsPVRDebugFSEntryDir = NULL;
typedef struct _PVR_DEBUGFS_DRIVER_STAT_
{
struct dentry *psEntry;
void *pvData;
PVRSRV_GET_NEXT_STAT_FUNC *pfnGetNextStat;
PVRSRV_INC_STAT_MEM_REFCOUNT_FUNC *pfnIncStatMemRefCount;
PVRSRV_DEC_STAT_MEM_REFCOUNT_FUNC *pfnDecStatMemRefCount;
IMG_UINT32 ui32RefCount;
IMG_INT32 i32StatValue;
IMG_CHAR *pszStatFormat;
PVR_DEBUGFS_ENTRY_DATA *pvDebugFSEntry;
} PVR_DEBUGFS_DRIVER_STAT;
typedef struct _PVR_DEBUGFS_DIR_DATA_
{
struct dentry *psDir;
PVR_DEBUGFS_DIR_DATA *psParentDir;
IMG_UINT32 ui32RefCount;
} PVR_DEBUGFS_DIR_DATA;
typedef struct _PVR_DEBUGFS_ENTRY_DATA_
{
struct dentry *psEntry;
PVR_DEBUGFS_DIR_DATA *psParentDir;
IMG_UINT32 ui32RefCount;
PVR_DEBUGFS_DRIVER_STAT *psStatData;
} PVR_DEBUGFS_ENTRY_DATA;
typedef struct _PVR_DEBUGFS_PRIV_DATA_
{
struct seq_operations *psReadOps;
PVRSRV_ENTRY_WRITE_FUNC *pfnWrite;
void *pvData;
IMG_BOOL bValid;
PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry;
} PVR_DEBUGFS_PRIV_DATA;
static void _RefDirEntry(PVR_DEBUGFS_DIR_DATA *psDirEntry);
static void _UnrefAndMaybeDestroyDirEntry(PVR_DEBUGFS_DIR_DATA *psDirEntry);
static void _UnrefAndMaybeDestroyDirEntryWhileLocked(PVR_DEBUGFS_DIR_DATA *psDirEntry);
static IMG_BOOL _RefDebugFSEntryNoLock(PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry);
static void _UnrefAndMaybeDestroyDebugFSEntry(PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry);
static IMG_BOOL _RefStatEntry(PVR_DEBUGFS_DRIVER_STAT *psStatEntry);
static IMG_BOOL _UnrefAndMaybeDestroyStatEntry(PVR_DEBUGFS_DRIVER_STAT *psStatEntry);
static void *_DebugFSStatisticSeqStart(struct seq_file *psSeqFile, loff_t *puiPosition)
{
PVR_DEBUGFS_DRIVER_STAT *psStatData = (PVR_DEBUGFS_DRIVER_STAT *)psSeqFile->private;
IMG_BOOL bResult;
IMG_BOOL bResult = IMG_FALSE;
bResult = psStatData->pfnGetNextStat(psStatData->pvData,
(IMG_UINT32)(*puiPosition),
&psStatData->i32StatValue,
&psStatData->pszStatFormat);
if (psStatData)
{
if (psStatData->pvData)
{
/* take reference on psStatData (for duration of stat iteration) */
if (!_RefStatEntry((void*)psStatData))
{
return NULL;
}
}
bResult = psStatData->pfnGetNextStat(psStatData->pvData,
(IMG_UINT32)(*puiPosition),
&psStatData->i32StatValue,
&psStatData->pszStatFormat);
}
return bResult ? psStatData : NULL;
}
static void _DebugFSStatisticSeqStop(struct seq_file *psSeqFile, void *pvData)
{
PVR_UNREFERENCED_PARAMETER(psSeqFile);
PVR_UNREFERENCED_PARAMETER(pvData);
PVR_DEBUGFS_DRIVER_STAT *psStatData = (PVR_DEBUGFS_DRIVER_STAT *)psSeqFile->private;
if (psStatData)
{
/* drop ref taken on stat memory, and if it is now zero, be sure we don't try to read it again */
if ((psStatData->ui32RefCount > 0) && (psStatData->pvData))
{
/* drop reference on psStatData (held for duration of stat iteration) */
_UnrefAndMaybeDestroyStatEntry((void*)psStatData);
}
}
}
static void *_DebugFSStatisticSeqNext(struct seq_file *psSeqFile,
void *pvData,
loff_t *puiPosition)
void *pvData,
loff_t *puiPosition)
{
PVR_DEBUGFS_DRIVER_STAT *psStatData = (PVR_DEBUGFS_DRIVER_STAT *)psSeqFile->private;
IMG_BOOL bResult;
IMG_BOOL bResult = IMG_FALSE;
(*puiPosition)++;
bResult = psStatData->pfnGetNextStat(psStatData->pvData,
(IMG_UINT32)(*puiPosition),
&psStatData->i32StatValue,
&psStatData->pszStatFormat);
if (puiPosition)
{
(*puiPosition)++;
if (psStatData)
{
if (psStatData->pvData)
{
bResult = psStatData->pfnGetNextStat(psStatData->pvData,
(IMG_UINT32)(*puiPosition),
&psStatData->i32StatValue,
&psStatData->pszStatFormat);
}
}
}
return bResult ? psStatData : NULL;
}
@ -131,29 +193,84 @@ static struct seq_operations gsDebugFSStatisticReadOps =
Common internal API
*/ /**************************************************************************/
typedef struct _PVR_DEBUGFS_PRIV_DATA_
{
struct seq_operations *psReadOps;
PVRSRV_ENTRY_WRITE_FUNC *pfnWrite;
void *pvData;
} PVR_DEBUGFS_PRIV_DATA;
static int _DebugFSFileOpen(struct inode *psINode, struct file *psFile)
{
PVR_DEBUGFS_PRIV_DATA *psPrivData = (PVR_DEBUGFS_PRIV_DATA *)psINode->i_private;
int iResult;
PVR_DEBUGFS_PRIV_DATA *psPrivData;
int iResult = -EIO;
IMG_BOOL bRefRet = IMG_FALSE;
PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry = NULL;
iResult = seq_open(psFile, psPrivData->psReadOps);
if (iResult == 0)
mutex_lock(&gDebugFSLock);
PVR_ASSERT(psINode);
psPrivData = (PVR_DEBUGFS_PRIV_DATA *)psINode->i_private;
if (psPrivData)
{
struct seq_file *psSeqFile = psFile->private_data;
/* Check that psPrivData is still valid to use */
if (psPrivData->bValid)
{
psDebugFSEntry = psPrivData->psDebugFSEntry;
psSeqFile->private = psPrivData->pvData;
/* Take ref on stat entry before opening seq file - this ref will be dropped if we
* fail to open the seq file or when we close it
*/
if (psDebugFSEntry)
{
bRefRet = _RefDebugFSEntryNoLock(psDebugFSEntry);
mutex_unlock(&gDebugFSLock);
if (bRefRet)
{
iResult = seq_open(psFile, psPrivData->psReadOps);
if (iResult == 0)
{
struct seq_file *psSeqFile = psFile->private_data;
psSeqFile->private = psPrivData->pvData;
}
else
{
/* Drop ref if we failed to open seq file */
_UnrefAndMaybeDestroyDebugFSEntry(psDebugFSEntry);
PVR_DPF((PVR_DBG_ERROR, "%s: Failed to seq_open psFile, returning %d", __FUNCTION__, iResult));
}
}
}
else
{
mutex_unlock(&gDebugFSLock);
}
}
else
{
mutex_unlock(&gDebugFSLock);
}
}
else
{
mutex_unlock(&gDebugFSLock);
}
return iResult;
}
static int _DebugFSFileClose(struct inode *psINode, struct file *psFile)
{
int iResult;
PVR_DEBUGFS_PRIV_DATA *psPrivData = (PVR_DEBUGFS_PRIV_DATA *)psINode->i_private;
PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry = NULL;
if (psPrivData)
{
psDebugFSEntry = psPrivData->psDebugFSEntry;
}
iResult = seq_release(psINode, psFile);
if (psDebugFSEntry)
{
_UnrefAndMaybeDestroyDebugFSEntry(psDebugFSEntry);
}
return iResult;
}
static ssize_t _DebugFSFileWrite(struct file *psFile,
const char __user *pszBuffer,
size_t uiCount,
@ -164,6 +281,7 @@ static ssize_t _DebugFSFileWrite(struct file *psFile,
if (psPrivData->pfnWrite == NULL)
{
PVR_DPF((PVR_DBG_ERROR, "%s: Called for file '%s', which does not have pfnWrite defined, returning -EIO(%d)", __FUNCTION__, psFile->f_path.dentry->d_iname, -EIO));
return -EIO;
}
@ -177,7 +295,7 @@ static const struct file_operations gsPVRDebugFSFileOps =
.read = seq_read,
.write = _DebugFSFileWrite,
.llseek = seq_lseek,
.release = seq_release,
.release = _DebugFSFileClose,
};
@ -196,6 +314,8 @@ int PVRDebugFSInit(void)
{
PVR_ASSERT(gpsPVRDebugFSEntryDir == NULL);
mutex_init(&gDebugFSLock);
gpsPVRDebugFSEntryDir = debugfs_create_dir(PVR_DEBUGFS_DIR_NAME, NULL);
if (gpsPVRDebugFSEntryDir == NULL)
{
@ -223,6 +343,7 @@ void PVRDebugFSDeInit(void)
debugfs_remove(gpsPVRDebugFSEntryDir);
gpsPVRDebugFSEntryDir = NULL;
mutex_destroy(&gDebugFSLock);
}
/*************************************************************************/ /*!
@ -242,31 +363,50 @@ void PVRDebugFSDeInit(void)
error code.
*/ /**************************************************************************/
int PVRDebugFSCreateEntryDir(IMG_CHAR *pszName,
struct dentry *psParentDir,
struct dentry **ppsDir)
PVR_DEBUGFS_DIR_DATA *psParentDir,
PVR_DEBUGFS_DIR_DATA **ppsNewDir)
{
struct dentry *psDir;
PVR_DEBUGFS_DIR_DATA *psNewDir;
PVR_ASSERT(gpsPVRDebugFSEntryDir != NULL);
if (pszName == NULL || ppsDir == NULL)
if (pszName == NULL || ppsNewDir == NULL)
{
PVR_DPF((PVR_DBG_ERROR, "%s: Invalid param", __FUNCTION__));
return -EINVAL;
}
psDir = debugfs_create_dir(pszName,
(psParentDir) ? psParentDir : gpsPVRDebugFSEntryDir);
if (psDir == NULL)
psNewDir = kmalloc(sizeof(*psNewDir), GFP_KERNEL);
if (psNewDir == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR,
"%s: Cannot allocate memory for '%s' pvr_debugfs structure",
__FUNCTION__, pszName));
return -ENOMEM;
}
psNewDir->psParentDir = psParentDir;
psNewDir->psDir = debugfs_create_dir(pszName, (psNewDir->psParentDir) ? psNewDir->psParentDir->psDir : gpsPVRDebugFSEntryDir);
if (psNewDir->psDir == NULL)
{
PVR_DPF((PVR_DBG_ERROR,
"%s: Cannot create '%s' debugfs directory",
__FUNCTION__, pszName));
kfree(psNewDir);
return -ENOMEM;
}
*ppsDir = psDir;
*ppsNewDir = psNewDir;
psNewDir->ui32RefCount = 1;
/* if parent directory is not gpsPVRDebugFSEntryDir, increment its refCount */
if (psNewDir->psParentDir)
{
_RefDirEntry(psNewDir->psParentDir);
}
return 0;
}
@ -278,16 +418,16 @@ int PVRDebugFSCreateEntryDir(IMG_CHAR *pszName,
@Input psDir Pointer representing the directory to be removed.
@Return void
*/ /**************************************************************************/
void PVRDebugFSRemoveEntryDir(struct dentry *psDir)
void PVRDebugFSRemoveEntryDir(PVR_DEBUGFS_DIR_DATA *psDir)
{
debugfs_remove(psDir);
_UnrefAndMaybeDestroyDirEntry(psDir);
}
/*************************************************************************/ /*!
@Function PVRDebugFSCreateEntry
@Description Create an entry in the specified directory.
@Input pszName String containing the name for the entry.
@Input pvDir Pointer from PVRDebugFSCreateEntryDir()
@Input psParentDir Pointer from PVRDebugFSCreateEntryDir()
representing the directory in which to create
the entry or NULL for the root directory.
@Input psReadOps Pointer to structure containing the necessary
@ -296,18 +436,19 @@ void PVRDebugFSRemoveEntryDir(struct dentry *psDir)
@Input pvData Private data to be passed to the read
functions, in the seq_file private member, and
the write function callback.
@Output ppsEntry On success, points to the newly created entry.
@Output ppsNewEntry On success, points to the newly created entry.
@Return int On success, returns 0. Otherwise, returns an
error code.
*/ /**************************************************************************/
int PVRDebugFSCreateEntry(const char *pszName,
void *pvDir,
PVR_DEBUGFS_DIR_DATA *psParentDir,
struct seq_operations *psReadOps,
PVRSRV_ENTRY_WRITE_FUNC *pfnWrite,
void *pvData,
struct dentry **ppsEntry)
PVR_DEBUGFS_ENTRY_DATA **ppsNewEntry)
{
PVR_DEBUGFS_PRIV_DATA *psPrivData;
PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry;
struct dentry *psEntry;
umode_t uiMode;
@ -318,10 +459,20 @@ int PVRDebugFSCreateEntry(const char *pszName,
{
return -ENOMEM;
}
psDebugFSEntry = kmalloc(sizeof(*psDebugFSEntry), GFP_KERNEL);
if (psDebugFSEntry == NULL)
{
kfree(psPrivData);
return -ENOMEM;
}
psPrivData->psReadOps = psReadOps;
psPrivData->pfnWrite = pfnWrite;
psPrivData->pvData = pvData;
psPrivData->pvData = (void*)pvData;
psPrivData->bValid = IMG_TRUE;
/* Store ptr to debugFSEntry in psPrivData, so a ref can be taken on it
* when the client opens a file */
psPrivData->psDebugFSEntry = psDebugFSEntry;
uiMode = S_IFREG;
@ -335,9 +486,19 @@ int PVRDebugFSCreateEntry(const char *pszName,
uiMode |= S_IWUSR;
}
psDebugFSEntry->psParentDir = psParentDir;
psDebugFSEntry->ui32RefCount = 1;
psDebugFSEntry->psStatData = (PVR_DEBUGFS_DRIVER_STAT*)pvData;
if (psDebugFSEntry->psParentDir)
{
/* increment refCount of parent directory */
_RefDirEntry(psDebugFSEntry->psParentDir);
}
psEntry = debugfs_create_file(pszName,
uiMode,
(pvDir != NULL) ? (struct dentry *)pvDir : gpsPVRDebugFSEntryDir,
(psParentDir != NULL) ? psParentDir->psDir : gpsPVRDebugFSEntryDir,
psPrivData,
&gsPVRDebugFSFileOps);
if (IS_ERR(psEntry))
@ -349,11 +510,8 @@ int PVRDebugFSCreateEntry(const char *pszName,
return PTR_ERR(psEntry);
}
/* take reference on inode (for allocation held in d_inode->i_private) - stops
* inode being removed until we have freed the memory allocated in i_private */
igrab(psEntry->d_inode);
*ppsEntry = psEntry;
psDebugFSEntry->psEntry = psEntry;
*ppsNewEntry = (void*)psDebugFSEntry;
return 0;
}
@ -361,94 +519,273 @@ int PVRDebugFSCreateEntry(const char *pszName,
/*************************************************************************/ /*!
@Function PVRDebugFSRemoveEntry
@Description Removes an entry that was created by PVRDebugFSCreateEntry().
@Input psEntry Pointer representing the entry to be removed.
@Input psDebugFSEntry Pointer representing the entry to be removed.
@Return void
*/ /**************************************************************************/
void PVRDebugFSRemoveEntry(struct dentry *psEntry)
void PVRDebugFSRemoveEntry(PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry)
{
if(psEntry != IMG_NULL)
{
/* Free any private data that was provided to debugfs_create_file() */
if (psEntry->d_inode->i_private != NULL)
{
kfree(psEntry->d_inode->i_private);
/* drop reference on inode now that we have freed the allocated memory*/
iput(psEntry->d_inode);
}
debugfs_remove(psEntry);
}
_UnrefAndMaybeDestroyDebugFSEntry(psDebugFSEntry);
}
/*************************************************************************/ /*!
@Function PVRDebugFSCreateStatisticEntry
@Description Create a statistic entry in the specified directory.
@Input pszName String containing the name for the entry.
@Input pvDir Pointer from PVRDebugFSCreateEntryDir()
@Input psDir Pointer from PVRDebugFSCreateEntryDir()
representing the directory in which to create
the entry or NULL for the root directory.
@Input pfnGetNextStat A callback function used to get the next
statistic when reading from the statistic
@Input pfnStatsPrint A callback function used to print all the
statistics when reading from the statistic
entry.
@Input pfnIncStatMemRefCount A callback function used take a
reference on the memory backing the
statistic.
@Input pfnDecStatMemRefCount A callback function used drop a
reference on the memory backing the
statistic.
@Input pvData Private data to be passed to the provided
callback function.
@Return void * On success, a pointer representing the newly
created statistic entry. Otherwise, NULL.
@Return PVR_DEBUGFS_DRIVER_STAT* On success, a pointer representing
the newly created statistic entry.
Otherwise, NULL.
*/ /**************************************************************************/
void *PVRDebugFSCreateStatisticEntry(const char *pszName,
void *pvDir,
PVR_DEBUGFS_DRIVER_STAT *PVRDebugFSCreateStatisticEntry(const char *pszName,
PVR_DEBUGFS_DIR_DATA *psDir,
PVRSRV_GET_NEXT_STAT_FUNC *pfnGetNextStat,
void *pvData)
PVRSRV_INC_STAT_MEM_REFCOUNT_FUNC *pfnIncStatMemRefCount,
PVRSRV_INC_STAT_MEM_REFCOUNT_FUNC *pfnDecStatMemRefCount,
void *pvData)
{
PVR_DEBUGFS_DRIVER_STAT *psStatData;
PVR_DEBUGFS_ENTRY_DATA * psDebugFSEntry;
int iResult;
if (pszName == NULL || pfnGetNextStat == NULL)
{
return NULL;
}
if ((pfnIncStatMemRefCount != NULL || pfnDecStatMemRefCount != NULL) && pvData == NULL)
{
return NULL;
}
psStatData = kzalloc(sizeof(*psStatData), GFP_KERNEL);
if (psStatData == NULL)
{
return NULL;
}
psStatData->pvData = pvData;
psStatData->pfnGetNextStat = pfnGetNextStat;
psStatData->pfnIncStatMemRefCount = pfnIncStatMemRefCount;
psStatData->pfnDecStatMemRefCount = pfnDecStatMemRefCount;
psStatData->ui32RefCount = 1;
iResult = PVRDebugFSCreateEntry(pszName,
pvDir,
psDir,
&gsDebugFSStatisticReadOps,
NULL,
psStatData,
&psStatData->psEntry);
&psDebugFSEntry);
if (iResult != 0)
{
kfree(psStatData);
return NULL;
}
psStatData->pvDebugFSEntry = (void*)psDebugFSEntry;
return psStatData;
if (pfnIncStatMemRefCount)
{
/* call function to take reference on the memory holding the stat */
psStatData->pfnIncStatMemRefCount((void*)psStatData->pvData);
}
psDebugFSEntry->ui32RefCount = 1;
return psStatData;
}
/*************************************************************************/ /*!
@Function PVRDebugFSRemoveStatisticEntry
@Description Removes a statistic entry that was created by
PVRDebugFSCreateStatisticEntry().
@Input pvEntry Pointer representing the statistic entry to be
removed.
@Input psStatEntry Pointer representing the statistic entry to be
removed.
@Return void
*/ /**************************************************************************/
void PVRDebugFSRemoveStatisticEntry(void *pvStatEntry)
void PVRDebugFSRemoveStatisticEntry(PVR_DEBUGFS_DRIVER_STAT *psStatEntry)
{
PVR_DEBUGFS_DRIVER_STAT *psStatData = (PVR_DEBUGFS_DRIVER_STAT *)pvStatEntry;
/* drop reference on pvStatEntry*/
_UnrefAndMaybeDestroyStatEntry(psStatEntry);
}
if (psStatData != NULL)
static void _RefDirEntry(PVR_DEBUGFS_DIR_DATA *psDirEntry)
{
mutex_lock(&gDebugFSLock);
if (psDirEntry->ui32RefCount > 0)
{
PVRDebugFSRemoveEntry(psStatData->psEntry);
/* Increment refCount */
psDirEntry->ui32RefCount++;
}
kfree(psStatData);
mutex_unlock(&gDebugFSLock);
}
static void _UnrefAndMaybeDestroyDirEntryWhileLocked(PVR_DEBUGFS_DIR_DATA *psDirEntry)
{
if (psDirEntry->ui32RefCount > 0)
{
/* Decrement refCount and free if now zero */
if (--psDirEntry->ui32RefCount == 0)
{
/* if parent directory is not gpsPVRDebugFSEntryDir, decrement its refCount */
debugfs_remove(psDirEntry->psDir);
if (psDirEntry->psParentDir)
{
_UnrefAndMaybeDestroyDirEntryWhileLocked(psDirEntry->psParentDir);
}
kfree(psDirEntry);
}
}
}
static void _UnrefAndMaybeDestroyDirEntry(PVR_DEBUGFS_DIR_DATA *psDirEntry)
{
mutex_lock(&gDebugFSLock);
if (psDirEntry->ui32RefCount > 0)
{
/* Decrement refCount and free if now zero */
if (--psDirEntry->ui32RefCount == 0)
{
/* if parent directory is not gpsPVRDebugFSEntryDir, decrement its refCount */
debugfs_remove(psDirEntry->psDir);
if (psDirEntry->psParentDir)
{
_UnrefAndMaybeDestroyDirEntryWhileLocked(psDirEntry->psParentDir);
}
kfree(psDirEntry);
}
}
mutex_unlock(&gDebugFSLock);
}
static IMG_BOOL _RefDebugFSEntryNoLock(PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry)
{
IMG_BOOL bResult = IMG_FALSE;
PVR_ASSERT(psDebugFSEntry != NULL);
bResult = (psDebugFSEntry->ui32RefCount > 0);
if (bResult)
{
/* Increment refCount of psDebugFSEntry */
psDebugFSEntry->ui32RefCount++;
}
return bResult;
}
static void _UnrefAndMaybeDestroyDebugFSEntry(PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry)
{
mutex_lock(&gDebugFSLock);
/* Decrement refCount of psDebugFSEntry, and free if now zero */
PVR_ASSERT(psDebugFSEntry != IMG_NULL);
if (psDebugFSEntry->ui32RefCount > 0)
{
if (--psDebugFSEntry->ui32RefCount == 0)
{
struct dentry *psEntry = psDebugFSEntry->psEntry;
if (psEntry)
{
/* Free any private data that was provided to debugfs_create_file() */
if (psEntry->d_inode->i_private != NULL)
{
PVR_DEBUGFS_PRIV_DATA *psPrivData = (PVR_DEBUGFS_PRIV_DATA*)psDebugFSEntry->psEntry->d_inode->i_private;
psPrivData->bValid = IMG_FALSE;
psPrivData->psDebugFSEntry = NULL;
kfree(psEntry->d_inode->i_private);
psEntry->d_inode->i_private = IMG_NULL;
}
debugfs_remove(psEntry);
}
/* decrement refcount of parent directory */
if (psDebugFSEntry->psParentDir)
{
_UnrefAndMaybeDestroyDirEntryWhileLocked(psDebugFSEntry->psParentDir);
}
/* now free the memory allocated for psDebugFSEntry */
kfree(psDebugFSEntry);
}
}
mutex_unlock(&gDebugFSLock);
}
static IMG_BOOL _RefStatEntry(PVR_DEBUGFS_DRIVER_STAT *psStatEntry)
{
IMG_BOOL bResult = IMG_FALSE;
PVR_ASSERT(psStatEntry != NULL);
mutex_lock(&gDebugFSLock);
bResult = (psStatEntry->ui32RefCount > 0);
if (bResult)
{
/* Increment refCount of psStatEntry */
psStatEntry->ui32RefCount++;
}
mutex_unlock(&gDebugFSLock);
return bResult;
}
static IMG_BOOL _UnrefAndMaybeDestroyStatEntry(PVR_DEBUGFS_DRIVER_STAT *psStatEntry)
{
IMG_BOOL bResult;
PVR_ASSERT(psStatEntry != IMG_NULL);
mutex_lock(&gDebugFSLock);
bResult = (psStatEntry->ui32RefCount > 0);
if (bResult)
{
/* Decrement refCount of psStatData, and free if now zero */
if (--psStatEntry->ui32RefCount == 0)
{
mutex_unlock(&gDebugFSLock);
if (psStatEntry->pvDebugFSEntry)
{
_UnrefAndMaybeDestroyDebugFSEntry((PVR_DEBUGFS_ENTRY_DATA*)psStatEntry->pvDebugFSEntry);
}
if (psStatEntry->pfnDecStatMemRefCount)
{
/* call function to drop reference on the memory holding the stat */
psStatEntry->pfnDecStatMemRefCount((void*)psStatEntry->pvData);
}
}
else
{
mutex_unlock(&gDebugFSLock);
}
}
else
{
mutex_unlock(&gDebugFSLock);
}
return bResult;
}

View File

@ -58,26 +58,37 @@ typedef IMG_BOOL (PVRSRV_GET_NEXT_STAT_FUNC)(void *pvStatPtr,
IMG_INT32 *piStatData,
IMG_CHAR **ppszStatFmtText);
typedef IMG_UINT32 (PVRSRV_INC_STAT_MEM_REFCOUNT_FUNC)(void *pvStatPtr);
typedef IMG_UINT32 (PVRSRV_DEC_STAT_MEM_REFCOUNT_FUNC)(void *pvStatPtr);
typedef struct _PVR_DEBUGFS_DIR_DATA_ PVR_DEBUGFS_DIR_DATA;
typedef struct _PVR_DEBUGFS_ENTRY_DATA_ PVR_DEBUGFS_ENTRY_DATA;
typedef struct _PVR_DEBUGFS_DRIVER_STAT_ PVR_DEBUGFS_DRIVER_STAT;
int PVRDebugFSInit(void);
void PVRDebugFSDeInit(void);
int PVRDebugFSCreateEntryDir(IMG_CHAR *pszName,
struct dentry *psParentDir,
struct dentry **ppsDir);
void PVRDebugFSRemoveEntryDir(struct dentry *psDir);
PVR_DEBUGFS_DIR_DATA *psParentDir,
PVR_DEBUGFS_DIR_DATA **ppsNewDir);
void PVRDebugFSRemoveEntryDir(PVR_DEBUGFS_DIR_DATA *psDir);
int PVRDebugFSCreateEntry(const char *pszName,
void *pvDir,
struct seq_operations *psReadOps,
PVRSRV_ENTRY_WRITE_FUNC *pfnWrite,
void *pvData,
struct dentry **ppsEntry);
void PVRDebugFSRemoveEntry(struct dentry *psEntry);
PVR_DEBUGFS_DIR_DATA *psParentDir,
struct seq_operations *psReadOps,
PVRSRV_ENTRY_WRITE_FUNC *pfnWrite,
void *pvData,
PVR_DEBUGFS_ENTRY_DATA **ppsNewEntry);
void *PVRDebugFSCreateStatisticEntry(const char *pszName,
void *pvDir,
PVRSRV_GET_NEXT_STAT_FUNC *pfnGetNextStat,
void *pvData);
void PVRDebugFSRemoveStatisticEntry(void *pvStatEntry);
void PVRDebugFSRemoveEntry(PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry);
PVR_DEBUGFS_DRIVER_STAT *PVRDebugFSCreateStatisticEntry(const char *pszName,
PVR_DEBUGFS_DIR_DATA *psDir,
PVRSRV_GET_NEXT_STAT_FUNC *pfnGetNextStat,
PVRSRV_INC_STAT_MEM_REFCOUNT_FUNC *pfnIncStatMemRefCount,
PVRSRV_INC_STAT_MEM_REFCOUNT_FUNC *pfnDecStatMemRefCount,
void *pvData);
void PVRDebugFSRemoveStatisticEntry(PVR_DEBUGFS_DRIVER_STAT *psStatEntry);
#endif /* !defined(__PVR_DEBUGFS_H__) */

View File

@ -197,7 +197,7 @@ static PVRSRV_ERROR GetCtxAndJobID(IMG_UINT32 ui32PID,
/* DebugFS entry for the feature's on/off file */
static struct dentry* gpsPVRDebugFSGpuTracingOnEntry = NULL;
static PVR_DEBUGFS_ENTRY_DATA *gpsPVRDebugFSGpuTracingOnEntry = NULL;
/*
@ -291,8 +291,14 @@ static IMG_INT GpuTracingSet(const IMG_CHAR *buffer, size_t count, loff_t uiPosi
case 'y':
case 'Y':
{
PVRGpuTraceEnabledSet(IMG_TRUE);
PVR_TRACE(("ENABLED GPU FTrace"));
if (PVRGpuTraceEnabledSet(IMG_TRUE) == PVRSRV_OK)
{
PVR_TRACE(("ENABLED GPU FTrace"));
}
else
{
PVR_TRACE(("FAILED to enable GPU FTrace"));
}
break;
}
}
@ -388,17 +394,17 @@ PVRSRV_ERROR PVRGpuTraceInit(void)
&gsGpuTracingReadOps,
(PVRSRV_ENTRY_WRITE_FUNC *)GpuTracingSet,
NULL,
&gpsPVRDebugFSGpuTracingOnEntry);
&gpsPVRDebugFSGpuTracingOnEntry);
}
void PVRGpuTraceDeInit(void)
{
/* Can be NULL if driver startup failed */
if (gpsPVRDebugFSGpuTracingOnEntry)
if (gpsPVRDebugFSGpuTracingOnEntry)
{
PVRDebugFSRemoveEntry(gpsPVRDebugFSGpuTracingOnEntry);
gpsPVRDebugFSGpuTracingOnEntry = NULL;
PVRDebugFSRemoveEntry(gpsPVRDebugFSGpuTracingOnEntry);
gpsPVRDebugFSGpuTracingOnEntry = NULL;
}
}

View File

@ -54,7 +54,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The device layer of the KM driver defines these two APIs to allow a
platform module to set and retrieve the feature's on/off state.
*/
extern void PVRGpuTraceEnabledSet(IMG_BOOL bNewValue);
extern PVRSRV_ERROR PVRGpuTraceEnabledSet(IMG_BOOL bNewValue);
extern IMG_BOOL PVRGpuTraceEnabled(void);

View File

@ -414,8 +414,13 @@ typedef IMG_BOOL (OS_GET_STATS_ELEMENT_FUNC)(IMG_PVOID pvStatPtr,
IMG_INT32* pi32StatData,
IMG_CHAR** ppszStatFmtText);
typedef IMG_UINT32 (OS_INC_STATS_MEM_REFCOUNT_FUNC)(IMG_PVOID pvStatPtr);
typedef IMG_UINT32 (OS_DEC_STATS_MEM_REFCOUNT_FUNC)(IMG_PVOID pvStatPtr);
IMG_PVOID OSCreateStatisticEntry(IMG_CHAR* pszName, IMG_PVOID pvFolder,
OS_GET_STATS_ELEMENT_FUNC* pfnGetElement,
OS_INC_STATS_MEM_REFCOUNT_FUNC* pfnIncMemRefCt,
OS_DEC_STATS_MEM_REFCOUNT_FUNC* pfnDecMemRefCt,
IMG_PVOID pvData);
IMG_VOID OSRemoveStatisticEntry(IMG_PVOID pvEntry);
IMG_PVOID OSCreateStatisticFolder(IMG_CHAR *pszName, IMG_PVOID pvFolder);

View File

@ -94,6 +94,7 @@ typedef struct PVRSRV_DATA_TAG
IMG_HANDLE hCleanupThread; /*!< Cleanup thread */
IMG_HANDLE hCleanupEventObject; /*!< Event object to drive cleanup thread */
IMG_PID cleanupThreadPid; /*!< Cleanup thread process id */
IMG_HANDLE hDevicesWatchdogThread; /*!< Devices Watchdog thread */
IMG_HANDLE hDevicesWatchdogEvObj; /*! Event object to drive devices watchdog thread */

View File

@ -49,6 +49,7 @@ extern "C" {
#endif
#include "servicesext.h"
#include "dllist.h"
/******************************************************************************
* resman definitions
@ -138,6 +139,13 @@ typedef struct _RESMAN_ITEM_ *PRESMAN_ITEM;
typedef struct _RESMAN_CONTEXT_ *PRESMAN_CONTEXT;
typedef struct _RESMAN_DEFER_CONTEXTS_LIST_ *PRESMAN_DEFER_CONTEXTS_LIST;
typedef struct _RESMAN_FREE_FN_AND_DATA_
{
DLLIST_NODE sNode;
RESMAN_FREE_FN pfnFree;
IMG_VOID *pvParam;
} RESMAN_FREE_FN_AND_DATA;
/******************************************************************************
* resman functions
*****************************************************************************/
@ -187,6 +195,10 @@ IMG_BOOL PVRSRVResManFlushDeferContext(PRESMAN_DEFER_CONTEXTS_LIST hDeferContext
IMG_VOID PVRSRVResManDestroyDeferContext(PRESMAN_DEFER_CONTEXTS_LIST hDeferContext);
IMG_VOID PVRSRVResManAddNoBridgeLockCallback(RESMAN_FREE_FN_AND_DATA *psCallbackInfo);
IMG_BOOL PVRSRVResManInDeferredCleanup(IMG_VOID);
#if defined (__cplusplus)
}
#endif

View File

@ -1081,19 +1081,7 @@ DevmemAllocate(DEVMEM_HEAP *psHeap,
PVR_ASSERT(uiSize<IMG_UINT32_MAX);
#endif
#if defined(CONFIG_ARM64) || defined(__arm64__) || defined(__aarch64__)
{
IMG_UINT32 i;
IMG_BYTE * pbyPtr;
pbyPtr = (IMG_BYTE*) pvAddr;
for (i = 0; i < uiSize; i++)
*pbyPtr++ = 0;
}
#else
OSMemSet(pvAddr, 0x0, (IMG_SIZE_T) uiSize);
#endif
DevmemReleaseCpuVirtAddr(psMemDesc);

View File

@ -50,7 +50,7 @@ typedef struct _FLASH_DATA_
IMG_UINT32 ui32ReadEntry;
IMG_BOOL bEnteredResetMode;
struct dentry *debugFSEntry;
PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry;
PFN_APOLLO_FLASH_INIT pfnFlashInit;
PFN_APOLLO_FLASH_WRITE pfnFlashWrite;
PFN_APOLLO_FLASH_GET_STATUS pfnFlashGetStatus;
@ -221,7 +221,7 @@ PVRSRV_ERROR ApolloFlasherSetup(IMG_HANDLE *phFlasher,
&gsFlasherReadOps,
(PVRSRV_ENTRY_WRITE_FUNC *)ApolloFlashWrite,
(IMG_VOID *)psApolloFlashData,
&psApolloFlashData->debugFSEntry) < 0)
&psApolloFlashData->psDebugFSEntry) < 0)
{
OSFreeMem(psApolloFlashData);
@ -239,9 +239,9 @@ PVRSRV_ERROR ApolloFlasherCleanup(IMG_HANDLE hFlasher)
if (psFlashData != IMG_NULL)
{
if (psFlashData->debugFSEntry != NULL)
if (psFlashData->psDebugFSEntry != NULL)
{
PVRDebugFSRemoveEntry(psFlashData->debugFSEntry);
PVRDebugFSRemoveEntry(psFlashData->psDebugFSEntry);
}
OSFreeMem(hFlasher);

View File

@ -24,6 +24,66 @@
#include "power.h"
#include "rk_init.h"
#include <asm/compiler.h>
#if RK_TF_VERSION
#define PSCI_RKSIP_TF_VERSION (0x82000001)
static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1,
u64 arg2)
{
asm volatile(
__asmeq("%0", "x0")
__asmeq("%1", "x1")
__asmeq("%2", "x2")
__asmeq("%3", "x3")
"smc #0\n"
: "+r" (function_id)
: "r" (arg0), "r" (arg1), "r" (arg2));
return function_id;
}
static int (*invoke_psci_fn)(u64, u64 , u64, u64) = __invoke_psci_fn_smc;
static int rk_tf_get_version(void)
{
int ver_num;
ver_num = invoke_psci_fn(PSCI_RKSIP_TF_VERSION, 0, 0, 0);
return ver_num;
}
static int rk_tf_check_version(void)
{
int version=0;
int high_16=0;
int low_16=0;
IMG_PINT pNULL=NULL;
version = rk_tf_get_version();
high_16 = (version >> 16) & ~(0xFFFF << 16);
low_16 = (version & ~(0xFFFF << 16));
printk("raw version=0x%x,rk_tf_version=%x.%x\n",version,high_16,low_16);
if((version != 0xFFFFFFFF) && (high_16 >= 1) && (low_16 >= 3))
{
return 0;
}
else
{
printk("Error:%s-line:%d This version cann't support rk3328\n",__func__,__LINE__);
*pNULL=0; //crash system
return -1;
}
}
#endif
extern struct platform_device *gpsPVRLDMDev;
@ -62,6 +122,7 @@ unsigned int RGX_DVFS_STEP = ARRAY_SIZE(rgx_dvfs_infotbl);
static int rk33_clk_set_normal_node(struct clk* node, unsigned long rate)
{
int ret = 0;
if (!node)
{
printk("rk33_clk_set_normal_node error \r\n");
@ -158,15 +219,20 @@ static void rk33_dvfs_set_clock(int freq)
if (NULL == platform)
panic("oops");
if (!platform->gpu_clk_node || !platform->aclk_gpu_mem || !platform->gpu_clk_node)
if ( !platform->aclk_gpu_mem || !platform->aclk_gpu_cfg || !platform->dvfs_enabled)
{
printk("gpu_clk_node not init\n");
printk("aclk_gpu_mem or aclk_gpu_cfg not init\n");
return;
}
//mutex_lock(&rgx_set_clock_lock);
rk33_clk_set_normal_node(platform->aclk_gpu_mem, freq);
rk33_clk_set_normal_node(platform->aclk_gpu_cfg, freq);
rk33_clk_set_dvfs_node(platform->gpu_clk_node, freq);
if(platform->gpu_clk_node)
rk33_clk_set_dvfs_node(platform->gpu_clk_node, freq);
else if(platform->clk_gpu)
rk33_clk_set_normal_node(platform->clk_gpu, freq);
//mutex_unlock(&rgx_set_clock_lock);
return;
}
@ -784,7 +850,6 @@ static IMG_VOID rk33_dvfs_utils_init(struct rk_context *platform)
platform->temperature = 0;
platform->temperature_time = 0;
platform->timer_active = IMG_FALSE;
platform->dvfs_enabled = IMG_TRUE;
#if RK33_USE_CL_COUNT_UTILS
platform->abs_load[0] = platform->abs_load[1] = platform->abs_load[2] = platform->abs_load[3] = 0;
@ -799,8 +864,6 @@ static IMG_VOID rk33_dvfs_utils_init(struct rk_context *platform)
#endif //RK33_DVFS_FREQ_LIMIT
#endif //RK33_SYSFS_FILE_SUPPORT
//dvfs timer
spin_lock_init(&platform->timer_lock);
#if USE_HRTIMER
{
@ -1622,9 +1685,9 @@ IMG_BOOL rk33_set_device_node(IMG_HANDLE hDevCookie)
//start timer
#if USE_HRTIMER
if(platform->psDeviceNode && platform->timer.function && !platform->timer_active)
if(platform->psDeviceNode && platform->dvfs_enabled && platform->timer.function && !platform->timer_active)
#elif USE_KTHREAD
if(platform->psDeviceNode && !platform->timer_active)
if(platform->psDeviceNode && platform->dvfs_enabled && !platform->timer_active)
#endif
{
spin_lock_irqsave(&platform->timer_lock, flags);
@ -1657,7 +1720,7 @@ IMG_BOOL rk33_clear_device_node(IMG_VOID)
if(platform)
{
//cacel timer
if(platform->timer_active)
if(platform->timer_active && platform->dvfs_enabled)
{
spin_lock_irqsave(&platform->timer_lock, flags);
platform->timer_active = IMG_FALSE;
@ -1683,23 +1746,27 @@ IMG_BOOL rk33_clear_device_node(IMG_VOID)
static IMG_VOID RgxEnableClock(IMG_VOID)
{
struct rk_context *platform;
#if RK33_DVFS_SUPPORT
unsigned long flags;
#endif
platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
if (
platform->gpu_clk_node &&
platform->aclk_gpu_mem && platform->aclk_gpu_cfg && !platform->gpu_active)
if (platform->aclk_gpu_mem && platform->aclk_gpu_cfg && !platform->gpu_active)
{
dvfs_clk_prepare_enable(platform->gpu_clk_node);
if(platform->gpu_clk_node)
dvfs_clk_prepare_enable(platform->gpu_clk_node);
else if(platform->clk_gpu)
clk_prepare_enable(platform->clk_gpu);
clk_prepare_enable(platform->aclk_gpu_mem);
clk_prepare_enable(platform->aclk_gpu_cfg);
#if RK33_DVFS_SUPPORT
rk33_dvfs_record_gpu_active(platform);
if(platform->psDeviceNode && !platform->timer_active)
if(platform->psDeviceNode && platform->dvfs_enabled && !platform->timer_active)
{
spin_lock_irqsave(&platform->timer_lock, flags);
platform->timer_active = IMG_TRUE;
spin_unlock_irqrestore(&platform->timer_lock, flags);
@ -1713,24 +1780,25 @@ static IMG_VOID RgxEnableClock(IMG_VOID)
{
PVR_DPF((PVR_DBG_WARNING, "Failed to enable clock!"));
}
}
static IMG_VOID RgxDisableClock(IMG_VOID)
{
struct rk_context *platform;
#if RK33_DVFS_SUPPORT
unsigned long flags;
#endif
platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
if (
platform->gpu_clk_node &&
platform->aclk_gpu_mem && platform->aclk_gpu_cfg && platform->gpu_active)
if (platform->aclk_gpu_mem && platform->aclk_gpu_cfg && platform->gpu_active)
{
#if RK33_DVFS_SUPPORT
//Force to drop freq to the lowest.
rk33_dvfs_set_level(0);
if(platform->timer_active)
if(platform->dvfs_enabled && platform->timer_active)
{
spin_lock_irqsave(&platform->timer_lock, flags);
platform->timer_active = IMG_FALSE;
@ -1739,11 +1807,16 @@ static IMG_VOID RgxDisableClock(IMG_VOID)
hrtimer_cancel(&platform->timer);
#endif
}
rk33_dvfs_record_gpu_idle(platform);
#endif
clk_disable_unprepare(platform->aclk_gpu_cfg);
clk_disable_unprepare(platform->aclk_gpu_mem);
dvfs_clk_disable_unprepare(platform->gpu_clk_node);
if(platform->gpu_clk_node)
dvfs_clk_disable_unprepare(platform->gpu_clk_node);
else if(platform->clk_gpu)
clk_disable_unprepare(platform->clk_gpu);
}
else
{
@ -1816,12 +1889,14 @@ IMG_VOID RgxResume(IMG_VOID)
#if OPEN_GPU_PD
RgxEnablePower();
#endif
//mdelay(2);
/* set external isolation invalid */
//writel(0, SUNXI_R_PRCM_VBASE + GPU_PWROFF_GATING);
//DeAssertGpuResetSignal();
RgxEnableClock();
/* delay for internal power stability */
@ -1873,6 +1948,10 @@ IMG_VOID RgxRkInit(IMG_VOID)
return;
}
#if RK_TF_VERSION
rk_tf_check_version();
#endif
dev_set_drvdata(&gpsPVRLDMDev->dev, platform);
#if OPEN_GPU_PD
@ -1882,17 +1961,18 @@ IMG_VOID RgxRkInit(IMG_VOID)
platform->psDeviceNode = NULL;
spin_lock_init(&platform->cmu_pmu_lock);
spin_lock_init(&platform->timer_lock);
#if OPEN_GPU_PD
platform->pd_gpu_0 = devm_clk_get(&gpsPVRLDMDev->dev, "pd_gpu_0");
if (IS_ERR(platform->pd_gpu_0))
if (IS_ERR_OR_NULL(platform->pd_gpu_0))
{
PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to find pd_gpu_0 clock source"));
goto fail0;
}
platform->pd_gpu_1 = devm_clk_get(&gpsPVRLDMDev->dev, "pd_gpu_1");
if (IS_ERR(platform->pd_gpu_1))
if (IS_ERR_OR_NULL(platform->pd_gpu_1))
{
PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to find pd_gpu_1 clock source"));
goto fail1;
@ -1900,37 +1980,46 @@ IMG_VOID RgxRkInit(IMG_VOID)
#endif
platform->aclk_gpu_mem = devm_clk_get(&gpsPVRLDMDev->dev, "aclk_gpu_mem");
if (IS_ERR(platform->aclk_gpu_mem))
if (IS_ERR_OR_NULL(platform->aclk_gpu_mem))
{
PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to find aclk_gpu_mem clock source"));
goto fail2;
}
platform->aclk_gpu_cfg = devm_clk_get(&gpsPVRLDMDev->dev, "aclk_gpu_cfg");
if (IS_ERR(platform->aclk_gpu_cfg))
if (IS_ERR_OR_NULL(platform->aclk_gpu_cfg))
{
PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to find aclk_gpu_cfg clock source"));
goto fail3;
}
platform->gpu_clk_node = clk_get_dvfs_node("clk_gpu");
if (IS_ERR(platform->gpu_clk_node))
if (IS_ERR_OR_NULL(platform->gpu_clk_node))
{
PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to find gpu_clk_node clock source"));
goto fail4;
platform->dvfs_enabled = IMG_FALSE;
PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: GPU Dvfs is disabled"));
platform->clk_gpu = devm_clk_get(&gpsPVRLDMDev->dev, "clk_gpu");
if (IS_ERR_OR_NULL(platform->clk_gpu))
{
PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to find clk_gpu clock source"));
goto fail4;
}
}
rk33_clk_set_normal_node(platform->aclk_gpu_mem, RK33_DEFAULT_CLOCK);
rk33_clk_set_normal_node(platform->aclk_gpu_cfg, RK33_DEFAULT_CLOCK);
rk33_clk_set_dvfs_node(platform->gpu_clk_node, RK33_DEFAULT_CLOCK);
else
{
platform->dvfs_enabled = IMG_TRUE;
rk33_clk_set_dvfs_node(platform->gpu_clk_node, RK33_DEFAULT_CLOCK);
rk33_clk_set_normal_node(platform->aclk_gpu_mem, RK33_DEFAULT_CLOCK);
rk33_clk_set_normal_node(platform->aclk_gpu_cfg, RK33_DEFAULT_CLOCK);
#if RK33_DVFS_SUPPORT
rk33_dvfs_init();
rk33_dvfs_init();
#if RK33_SYSFS_FILE_SUPPORT
//create sysfs file node
rk_create_sysfs_file(&gpsPVRLDMDev->dev);
//create sysfs file node
rk_create_sysfs_file(&gpsPVRLDMDev->dev);
#endif
#endif //end of RK33_DVFS_SUPPORT
}
RgxResume();
@ -1943,6 +2032,7 @@ IMG_VOID RgxRkInit(IMG_VOID)
devm_clk_put(&gpsPVRLDMDev->dev, platform->aclk_gpu_mem);
platform->aclk_gpu_mem = NULL;
fail2:
#if OPEN_GPU_PD
devm_clk_put(&gpsPVRLDMDev->dev, platform->pd_gpu_1);
platform->pd_gpu_1 = NULL;
@ -1950,7 +2040,8 @@ IMG_VOID RgxRkInit(IMG_VOID)
devm_clk_put(&gpsPVRLDMDev->dev, platform->pd_gpu_0);
platform->pd_gpu_0 = NULL;
fail0:
#endif
#endif //end of OPEN_GPU_PD
kfree(platform);
}
@ -1960,15 +2051,52 @@ IMG_VOID RgxRkUnInit(IMG_VOID)
platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
#if RK33_DVFS_SUPPORT
#if RK33_SYSFS_FILE_SUPPORT
rk_remove_sysfs_file(&gpsPVRLDMDev->dev);
#endif
rk33_dvfs_term();
RgxSuspend();
if(platform->gpu_clk_node)
{
clk_put_dvfs_node(platform->gpu_clk_node);
platform->gpu_clk_node = NULL;
}
else if(platform->clk_gpu)
{
devm_clk_put(&gpsPVRLDMDev->dev, platform->clk_gpu);
platform->clk_gpu = NULL;
}
if(platform->aclk_gpu_cfg)
{
devm_clk_put(&gpsPVRLDMDev->dev, platform->aclk_gpu_cfg);
platform->aclk_gpu_cfg = NULL;
}
if(platform->aclk_gpu_mem)
{
devm_clk_put(&gpsPVRLDMDev->dev, platform->aclk_gpu_mem);
platform->aclk_gpu_mem = NULL;
}
#if OPEN_GPU_PD
if(platform->pd_gpu_1)
{
devm_clk_put(&gpsPVRLDMDev->dev, platform->pd_gpu_1);
platform->pd_gpu_1 = NULL;
}
if(platform->pd_gpu_0)
{
devm_clk_put(&gpsPVRLDMDev->dev, platform->pd_gpu_0);
platform->pd_gpu_0 = NULL;
}
#endif
if(platform->dvfs_enabled)
{
#if RK33_DVFS_SUPPORT
#if RK33_SYSFS_FILE_SUPPORT
rk_remove_sysfs_file(&gpsPVRLDMDev->dev);
#endif
rk33_dvfs_term();
#endif
}
kfree(platform);
RgxSuspend();
}

View File

@ -23,6 +23,8 @@
#define USE_KTHREAD 0
#define USE_HRTIMER 1
#define RK_TF_VERSION 1
#define RK33_MAX_UTILIS 4
#define RK33_DVFS_FREQ 50
#define RK33_DEFAULT_CLOCK 400
@ -92,6 +94,8 @@ struct rk_context
IMG_INT cmu_pmu_status;
/** cmd & pmu lock */
spinlock_t cmu_pmu_lock;
/*Timer*/
spinlock_t timer_lock;
#if OPEN_GPU_PD
IMG_BOOL bEnablePd;
@ -101,13 +105,15 @@ struct rk_context
//struct clk *aclk_gpu;
struct clk *aclk_gpu_mem;
struct clk *aclk_gpu_cfg;
struct clk *clk_gpu;
struct dvfs_node *gpu_clk_node;
PVRSRV_DEVICE_NODE *psDeviceNode;
RGXFWIF_GPU_UTIL_STATS sUtilStats;
RGXFWIF_GPU_UTIL_STATS sUtilStats;
IMG_BOOL gpu_active;
IMG_BOOL dvfs_enabled;
#if RK33_DVFS_SUPPORT
IMG_BOOL gpu_active;
#if RK33_USE_CUSTOMER_GET_GPU_UTIL
ktime_t time_period_start;
#endif
@ -116,8 +122,6 @@ struct rk_context
IMG_UINT32 temperature;
IMG_UINT32 temperature_time;
/*Timer*/
spinlock_t timer_lock;
#if USE_HRTIMER
struct hrtimer timer;
#endif
@ -137,7 +141,7 @@ struct rk_context
IMG_INT utilisation;
IMG_UINT32 time_busy;
IMG_UINT32 time_idle;
IMG_BOOL dvfs_enabled;
#if RK33_USE_CL_COUNT_UTILS
IMG_UINT32 abs_load[4];
#endif