summaryrefslogtreecommitdiff
path: root/drivers/gpu/rogue
diff options
context:
space:
mode:
authorzxl <zhuangxl@rock-chips.com>2015-06-02 16:07:27 +0800
committerzxl <zhuangxl@rock-chips.com>2015-06-02 16:07:27 +0800
commit5d82dfee2f33ad21f622b864f3c8c683dc2fa5d0 (patch)
tree461365b5e873dffce170734a1bd2d669bf209361 /drivers/gpu/rogue
parent46f1476d2d9dcfe4054108a1fae935e3ddadabf8 (diff)
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).
Diffstat (limited to 'drivers/gpu/rogue')
-rw-r--r--drivers/gpu/rogue/build/linux/config/core.mk9
-rw-r--r--drivers/gpu/rogue/config_kernel.h1
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.51.h7
-rw-r--r--drivers/gpu/rogue/hwdefs/km/rgx_cr_defs_km.h28
-rwxr-xr-xdrivers/gpu/rogue/include/pvrversion.h18
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_pdp.c80
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.c26
-rwxr-xr-xdrivers/gpu/rogue/services/server/common/process_stats.c207
-rw-r--r--drivers/gpu/rogue/services/server/common/pvrsrv.c3
-rw-r--r--drivers/gpu/rogue/services/server/common/resman.c78
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.c182
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.c30
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.h2
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/mmap.c9
-rwxr-xr-xdrivers/gpu/rogue/services/server/env/linux/module.c2
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/osfunc.c32
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/ossecure_export.c13
-rwxr-xr-xdrivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.c373
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.h49
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pvr_bridge_k.c39
-rwxr-xr-xdrivers/gpu/rogue/services/server/env/linux/pvr_debug.c15
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.c509
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.h41
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.c20
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.h2
-rw-r--r--drivers/gpu/rogue/services/server/include/osfunc.h5
-rw-r--r--drivers/gpu/rogue/services/server/include/pvrsrv.h1
-rw-r--r--drivers/gpu/rogue/services/server/include/resman.h12
-rwxr-xr-xdrivers/gpu/rogue/services/shared/common/devicemem.c12
-rw-r--r--drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher_linux.c8
-rwxr-xr-xdrivers/gpu/rogue/system/rk3368/rk_init.c204
-rwxr-xr-xdrivers/gpu/rogue/system/rk3368/rk_init.h14
32 files changed, 1605 insertions, 426 deletions
diff --git a/drivers/gpu/rogue/build/linux/config/core.mk b/drivers/gpu/rogue/build/linux/config/core.mk
index ddfef8546156..e2abc54b4a51 100644
--- a/drivers/gpu/rogue/build/linux/config/core.mk
+++ b/drivers/gpu/rogue/build/linux/config/core.mk
@@ -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,
diff --git a/drivers/gpu/rogue/config_kernel.h b/drivers/gpu/rogue/config_kernel.h
index 18168ff53db6..c00d1985435b 100644
--- a/drivers/gpu/rogue/config_kernel.h
+++ b/drivers/gpu/rogue/config_kernel.h
@@ -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
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.51.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.51.h
index 6464e705d7ae..771dd6b418ca 100644
--- a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.51.h
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.51.h
@@ -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_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/rgx_cr_defs_km.h b/drivers/gpu/rogue/hwdefs/km/rgx_cr_defs_km.h
index 463a5ad6b620..7ca15eceb94f 100644
--- a/drivers/gpu/rogue/hwdefs/km/rgx_cr_defs_km.h
+++ b/drivers/gpu/rogue/hwdefs/km/rgx_cr_defs_km.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
diff --git a/drivers/gpu/rogue/include/pvrversion.h b/drivers/gpu/rogue/include/pvrversion.h
index 24c08f8d35f0..f763ca080be4 100755
--- a/drivers/gpu/rogue/include/pvrversion.h
+++ b/drivers/gpu/rogue/include/pvrversion.h
@@ -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_ */
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_pdp.c b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_pdp.c
index 8a325e14557b..1dd4f9e578be 100644
--- a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_pdp.c
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_pdp.c
@@ -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)
{
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.c b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.c
index 31cab2e359b0..e00e76fab86f 100644
--- a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.c
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.c
@@ -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);
-
- memcpy(check_address_pos, check_ufo_addresses,
- sizeof(PRGXFWIF_UFO_ADDR) * nr_checks);
- memcpy(check_value_pos, check_values,
- sizeof(u32) * nr_checks);
+ 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);
+
+ 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;
diff --git a/drivers/gpu/rogue/services/server/common/process_stats.c b/drivers/gpu/rogue/services/server/common/process_stats.c
index d0e4b4d3fab0..79d9f15e7eb6 100755
--- a/drivers/gpu/rogue/services/server/common/process_stats.c
+++ b/drivers/gpu/rogue/services/server/common/process_stats.c
@@ -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)
+ {
+ 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)
{
- List_PVRSRV_MEM_ALLOC_REC_Remove(psProcessStats->psMemoryStats->psMemoryRecords);
+ 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:
diff --git a/drivers/gpu/rogue/services/server/common/pvrsrv.c b/drivers/gpu/rogue/services/server/common/pvrsrv.c
index c642bda8f87b..fdad3ef8d64d 100644
--- a/drivers/gpu/rogue/services/server/common/pvrsrv.c
+++ b/drivers/gpu/rogue/services/server/common/pvrsrv.c
@@ -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,
diff --git a/drivers/gpu/rogue/services/server/common/resman.c b/drivers/gpu/rogue/services/server/common/resman.c
index c23db6135d18..4ef15944ae82 100644
--- a/drivers/gpu/rogue/services/server/common/resman.c
+++ b/drivers/gpu/rogue/services/server/common/resman.c
@@ -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);
+
/*!
******************************************************************************
@@ -820,6 +828,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
@Description
@@ -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
{
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.c
index b7029fd33c74..37486f9915e0 100644
--- a/drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.c
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.c
@@ -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_UINT32 ui32Req = (ui32TagSB >> 0) & 0xf;
+ IMG_UINT32 ui32MCUSB = (ui32TagSB >> 4) & 0x3;
+ IMG_CHAR* pszReqOrig = "";
- IMG_CHAR* pszReqId = (ui32TagSB & 0x10)?"FBDC":"FBC";
- IMG_CHAR* pszOrig = "";
+ 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;
+ 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, 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: 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;
}
OSSNPrintf(pszScratchBuf, ui32ScratchBufSize,
- "%s Request, originator %s, MCU sideband 0x%X",
- pszReqId, pszOrig, ui32MCUSB);
+ "%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 */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.c
index d8a3f2c8c4f7..5a3930c9fad6 100644
--- a/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.c
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.c
@@ -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 @@ err_disconnect:
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)
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.h
index 1e5bd03ab216..9e65d954a04c 100644
--- a/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.h
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.h
@@ -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);
diff --git a/drivers/gpu/rogue/services/server/env/linux/mmap.c b/drivers/gpu/rogue/services/server/env/linux/mmap.c
index ad16d58bd7c6..b9caeb92a285 100644
--- a/drivers/gpu/rogue/services/server/env/linux/mmap.c
+++ b/drivers/gpu/rogue/services/server/env/linux/mmap.c
@@ -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?
}
diff --git a/drivers/gpu/rogue/services/server/env/linux/module.c b/drivers/gpu/rogue/services/server/env/linux/module.c
index 3e1d33e4ed8e..c190ce5c17cb 100755
--- a/drivers/gpu/rogue/services/server/env/linux/module.c
+++ b/drivers/gpu/rogue/services/server/env/linux/module.c
@@ -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)
diff --git a/drivers/gpu/rogue/services/server/env/linux/osfunc.c b/drivers/gpu/rogue/services/server/env/linux/osfunc.c
index 66455008cd9e..05265d4048af 100644
--- a/drivers/gpu/rogue/services/server/env/linux/osfunc.c
+++ b/drivers/gpu/rogue/services/server/env/linux/osfunc.c
@@ -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 */
diff --git a/drivers/gpu/rogue/services/server/env/linux/ossecure_export.c b/drivers/gpu/rogue/services/server/env/linux/ossecure_export.c
index 1488553e6a0d..f21921597d8e 100644
--- a/drivers/gpu/rogue/services/server/env/linux/ossecure_export.c
+++ b/drivers/gpu/rogue/services/server/env/linux/ossecure_export.c
@@ -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;
diff --git a/drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.c b/drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.c
index 4299add0737f..dd8e0a4d1543 100755
--- a/drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.c
+++ b/drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.c
@@ -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,21 +1206,147 @@ _FreeOSPages(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
}
}
- OSFreeMem(apsUnsetPages);
+ OSFreeMemstatMem(apsUnsetPages);
#endif
+ psPageArrayData->bHasOSPages = IMG_FALSE;
+
eError = PVRSRV_OK;
- psPageArrayData->bHasOSPages = IMG_FALSE;
+#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);
- /* Destroy the page pool if required */
- if ((g_ui32PagePoolMaxEntries > 0) && (g_psLinuxPagePoolCache != NULL) && (g_ui32LiveAllocs == 0))
+ if(eError != PVRSRV_OK)
{
- _DeinitPagePool();
+ PVR_DPF((PVR_DBG_ERROR, "_FreeOSPages_FreePagesAndFreeStructure: _FreeOSPages_FreePages failed"));
}
-#if defined(CONFIG_X86)
-e_exit:
+ 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;
}
@@ -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);
}
diff --git a/drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.h b/drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.h
new file mode 100644
index 000000000000..f247875cd208
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.h
@@ -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__ */
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_bridge_k.c b/drivers/gpu/rogue/services/server/env/linux/pvr_bridge_k.c
index 7ba442cd3762..108c6d859e4a 100644
--- a/drivers/gpu/rogue/services/server/env/linux/pvr_bridge_k.c
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_bridge_k.c
@@ -87,7 +87,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#if defined(DEBUG_BRIDGE_KM)
-static struct dentry *gpsPVRDebugFSBridgeStatsEntry = NULL;
+static PVR_DEBUGFS_ENTRY_DATA *gpsPVRDebugFSBridgeStatsEntry = NULL;
static struct seq_operations gsBridgeStatsReadOps;
#endif
@@ -157,7 +157,7 @@ LinuxBridgeInit(void)
&gsBridgeStatsReadOps,
NULL,
&g_BridgeDispatchTable[0],
- &gpsPVRDebugFSBridgeStatsEntry);
+ &gpsPVRDebugFSBridgeStatsEntry);
if (iResult != 0)
{
return PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -349,8 +349,8 @@ void
LinuxBridgeDeInit(void)
{
#if defined(DEBUG_BRIDGE_KM)
- PVRDebugFSRemoveEntry(gpsPVRDebugFSBridgeStatsEntry);
- gpsPVRDebugFSBridgeStatsEntry = NULL;
+ PVRDebugFSRemoveEntry(gpsPVRDebugFSBridgeStatsEntry);
+ gpsPVRDebugFSBridgeStatsEntry = NULL;
#endif
}
@@ -459,11 +459,19 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig
PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
#endif
PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
- CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pFile);
+ CONNECTION_DATA *psConnection;
IMG_INT err = -EFAULT;
OSAcquireBridgeLock();
+ psConnection = LinuxConnectionFromFile(pFile);
+ if(psConnection == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Connection is closed", __FUNCTION__));
+ OSReleaseBridgeLock();
+ return err;
+ }
+
#if defined(SUPPORT_DRM)
PVR_UNREFERENCED_PARAMETER(dev);
@@ -542,17 +550,28 @@ PVRSRV_BridgeCompatDispatchKM(struct file *pFile,
PVRSRV_BRIDGE_PACKAGE params_for_64;
struct bridge_package_from_32 params;
struct bridge_package_from_32 * const params_addr = &params;
-#if !defined(SUPPORT_DRM)
- CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pFile);
-#else
- struct drm_file *file_priv = pFile->private_data;
- CONNECTION_DATA *psConnection = LinuxConnectionFromFile(file_priv);
+#if defined(SUPPORT_DRM)
+ struct drm_file *file_priv;
#endif
+ CONNECTION_DATA *psConnection;
+
// make sure there is no padding inserted by compiler
PVR_ASSERT(sizeof(struct bridge_package_from_32) == 6 * sizeof(IMG_UINT32));
OSAcquireBridgeLock();
+#if !defined(SUPPORT_DRM)
+ psConnection = LinuxConnectionFromFile(pFile);
+#else
+ file_priv = pFile->private_data;
+ psConnection = LinuxConnectionFromFile(file_priv);
+#endif
+ if(psConnection == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Connection is closed", __FUNCTION__));
+ goto unlock_and_return;
+ }
+
if(!OSAccessOK(PVR_VERIFY_READ, (void *) arg,
sizeof(struct bridge_package_from_32)))
{
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_debug.c b/drivers/gpu/rogue/services/server/env/linux/pvr_debug.c
index ec647497faf1..965a85144dbd 100755
--- a/drivers/gpu/rogue/services/server/env/linux/pvr_debug.c
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_debug.c
@@ -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;
}
+
}
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.c b/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.c
index 044622cda23d..b37f4ad3eca0 100644
--- a/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.c
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.c
@@ -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;
+
+ if (psStatData)
+ {
+ if (psStatData->pvData)
+ {
+ /* take reference on psStatData (for duration of stat iteration) */
+ if (!_RefStatEntry((void*)psStatData))
- bResult = psStatData->pfnGetNextStat(psStatData->pvData,
- (IMG_UINT32)(*puiPosition),
- &psStatData->i32StatValue,
- &psStatData->pszStatFormat);
+ {
+ 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;
-
- (*puiPosition)++;
+ IMG_BOOL bResult = IMG_FALSE;
- 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,26 +193,81 @@ static struct seq_operations gsDebugFSStatisticReadOps =
Common internal API
*/ /**************************************************************************/
-typedef struct _PVR_DEBUGFS_PRIV_DATA_
+static int _DebugFSFileOpen(struct inode *psINode, struct file *psFile)
{
- struct seq_operations *psReadOps;
- PVRSRV_ENTRY_WRITE_FUNC *pfnWrite;
- void *pvData;
-} PVR_DEBUGFS_PRIV_DATA;
+ PVR_DEBUGFS_PRIV_DATA *psPrivData;
+ int iResult = -EIO;
+ IMG_BOOL bRefRet = IMG_FALSE;
+ PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry = NULL;
-static int _DebugFSFileOpen(struct inode *psINode, struct file *psFile)
+ mutex_lock(&gDebugFSLock);
+
+ PVR_ASSERT(psINode);
+ psPrivData = (PVR_DEBUGFS_PRIV_DATA *)psINode->i_private;
+ if (psPrivData)
+ {
+ /* Check that psPrivData is still valid to use */
+ if (psPrivData->bValid)
+ {
+ psDebugFSEntry = psPrivData->psDebugFSEntry;
+
+ /* 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)
{
- PVR_DEBUGFS_PRIV_DATA *psPrivData = (PVR_DEBUGFS_PRIV_DATA *)psINode->i_private;
int iResult;
+ PVR_DEBUGFS_PRIV_DATA *psPrivData = (PVR_DEBUGFS_PRIV_DATA *)psINode->i_private;
+ PVR_DEBUGFS_ENTRY_DATA *psDebugFSEntry = NULL;
- iResult = seq_open(psFile, psPrivData->psReadOps);
- if (iResult == 0)
+ if (psPrivData)
{
- struct seq_file *psSeqFile = psFile->private_data;
-
- psSeqFile->private = psPrivData->pvData;
+ psDebugFSEntry = psPrivData->psDebugFSEntry;
+ }
+ iResult = seq_release(psINode, psFile);
+ if (psDebugFSEntry)
+ {
+ _UnrefAndMaybeDestroyDebugFSEntry(psDebugFSEntry);
}
-
return iResult;
}
@@ -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;
+
+ if (pfnIncStatMemRefCount)
+ {
+ /* call function to take reference on the memory holding the stat */
+ psStatData->pfnIncStatMemRefCount((void*)psStatData->pvData);
+ }
+
+ psDebugFSEntry->ui32RefCount = 1;
- return psStatData;
+ 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;
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.h b/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.h
index 7ac45888bf66..3b3f52e78cee 100644
--- a/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.h
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.h
@@ -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);
-
-void *PVRDebugFSCreateStatisticEntry(const char *pszName,
- void *pvDir,
- PVRSRV_GET_NEXT_STAT_FUNC *pfnGetNextStat,
- void *pvData);
-void PVRDebugFSRemoveStatisticEntry(void *pvStatEntry);
+ PVR_DEBUGFS_DIR_DATA *psParentDir,
+ struct seq_operations *psReadOps,
+ PVRSRV_ENTRY_WRITE_FUNC *pfnWrite,
+ void *pvData,
+ PVR_DEBUGFS_ENTRY_DATA **ppsNewEntry);
+
+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__) */
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.c b/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.c
index 9bb0e920c972..06adc642971d 100644
--- a/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.c
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.c
@@ -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;
}
}
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.h b/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.h
index b681bbe64636..e4f21ee86309 100644
--- a/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.h
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.h
@@ -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);
diff --git a/drivers/gpu/rogue/services/server/include/osfunc.h b/drivers/gpu/rogue/services/server/include/osfunc.h
index 0183527561b0..3d7e006a1b1f 100644
--- a/drivers/gpu/rogue/services/server/include/osfunc.h
+++ b/drivers/gpu/rogue/services/server/include/osfunc.h
@@ -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);
diff --git a/drivers/gpu/rogue/services/server/include/pvrsrv.h b/drivers/gpu/rogue/services/server/include/pvrsrv.h
index 1a15a72de3f4..d6c3b18bc849 100644
--- a/drivers/gpu/rogue/services/server/include/pvrsrv.h
+++ b/drivers/gpu/rogue/services/server/include/pvrsrv.h
@@ -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 */
diff --git a/drivers/gpu/rogue/services/server/include/resman.h b/drivers/gpu/rogue/services/server/include/resman.h
index 76c41bb7bd39..4f81b865f558 100644
--- a/drivers/gpu/rogue/services/server/include/resman.h
+++ b/drivers/gpu/rogue/services/server/include/resman.h
@@ -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
diff --git a/drivers/gpu/rogue/services/shared/common/devicemem.c b/drivers/gpu/rogue/services/shared/common/devicemem.c
index b4d49d67fd4b..7490fe9a31b3 100755
--- a/drivers/gpu/rogue/services/shared/common/devicemem.c
+++ b/drivers/gpu/rogue/services/shared/common/devicemem.c
@@ -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);
diff --git a/drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher_linux.c b/drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher_linux.c
index 0d54ed69989e..35b734c88e93 100644
--- a/drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher_linux.c
+++ b/drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher_linux.c
@@ -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);
diff --git a/drivers/gpu/rogue/system/rk3368/rk_init.c b/drivers/gpu/rogue/system/rk3368/rk_init.c
index cffac0a0080b..28d2143b0878 100755
--- a/drivers/gpu/rogue/system/rk3368/rk_init.c
+++ b/drivers/gpu/rogue/system/rk3368/rk_init.c
@@ -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 @@ fail3:
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 @@ fail1:
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);
+ 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);
+ rk_remove_sysfs_file(&gpsPVRLDMDev->dev);
#endif
- rk33_dvfs_term();
+ rk33_dvfs_term();
#endif
-
+ }
kfree(platform);
- RgxSuspend();
}
diff --git a/drivers/gpu/rogue/system/rk3368/rk_init.h b/drivers/gpu/rogue/system/rk3368/rk_init.h
index 234b5e0c9f62..b71ad46ce0c4 100755
--- a/drivers/gpu/rogue/system/rk3368/rk_init.h
+++ b/drivers/gpu/rogue/system/rk3368/rk_init.h
@@ -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