mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 14:04:54 +02:00
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:
parent
46f1476d2d
commit
5d82dfee2f
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
49
drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.h
vendored
Normal file
49
drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.h
vendored
Normal 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__ */
|
||||
|
|
@ -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 = ¶ms;
|
||||
#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)))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__) */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user